Chat / Merge blocks placer / generator

This commit is contained in:
Jesse Boyd 2016-06-13 14:47:50 +10:00
parent 506455ae40
commit 4f0ede646e
71 changed files with 4523 additions and 4959 deletions

View File

@ -16,22 +16,21 @@ import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.uuid.UUIDWrapper; import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
/** /**
* PlotSquared API. * PlotSquared API.
@ -140,10 +139,10 @@ public class PlotAPI {
/** /**
* Get the block/biome set queue * Get the block/biome set queue
* @return SetQueue.IMP * @return GlobalBlockQueue.IMP
*/ */
public SetQueue getSetQueue() { public GlobalBlockQueue getBlockQueue() {
return SetQueue.IMP; return GlobalBlockQueue.IMP;
} }
/** /**

View File

@ -23,7 +23,6 @@ import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil; import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
@ -31,6 +30,7 @@ import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation; import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.QueueProvider;
import com.intellectualcrafters.plot.uuid.UUIDWrapper; import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector; import com.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector;
import com.plotsquared.bukkit.database.plotme.LikePlotMeConverter; import com.plotsquared.bukkit.database.plotme.LikePlotMeConverter;
@ -60,20 +60,25 @@ import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.Metrics; import com.plotsquared.bukkit.util.Metrics;
import com.plotsquared.bukkit.util.SendChunk; import com.plotsquared.bukkit.util.SendChunk;
import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.SetGenCB;
import com.plotsquared.bukkit.util.block.FastQueue_1_7; import com.plotsquared.bukkit.util.block.BukkitLocalQueue;
import com.plotsquared.bukkit.util.block.FastQueue_1_8; import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_7;
import com.plotsquared.bukkit.util.block.FastQueue_1_8_3; import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8;
import com.plotsquared.bukkit.util.block.FastQueue_1_9; import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8_3;
import com.plotsquared.bukkit.util.block.SlowQueue; import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_9;
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper; import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
import com.plotsquared.bukkit.uuid.FileUUIDHandler; import com.plotsquared.bukkit.uuid.FileUUIDHandler;
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper; import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper; import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
import com.plotsquared.bukkit.uuid.SQLUUIDHandler; import com.plotsquared.bukkit.uuid.SQLUUIDHandler;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.World; import org.bukkit.World;
@ -87,13 +92,6 @@ import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain { public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain {
public static WorldEdit worldEdit; public static WorldEdit worldEdit;
@ -417,7 +415,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
} }
@Override @Override
public PlotQueue<Chunk> initPlotQueue() { public QueueProvider initBlockQueue() {
try { try {
new SendChunk(); new SendChunk();
MainUtil.canSendChunk = true; MainUtil.canSendChunk = true;
@ -426,32 +424,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
MainUtil.canSendChunk = false; MainUtil.canSendChunk = false;
} }
if (PS.get().checkVersion(getServerVersion(), 1, 9, 0)) { if (PS.get().checkVersion(getServerVersion(), 1, 9, 0)) {
try { return QueueProvider.of(BukkitLocalQueue_1_9.class, BukkitLocalQueue.class);
return new FastQueue_1_9(); }
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) { if (PS.get().checkVersion(getServerVersion(), 1, 8, 3)) {
e.printStackTrace(); return QueueProvider.of(BukkitLocalQueue_1_8_3.class, BukkitLocalQueue.class);
return new SlowQueue();
}
} }
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) { if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
try { return QueueProvider.of(BukkitLocalQueue_1_8.class, BukkitLocalQueue.class);
return new FastQueue_1_8_3();
} catch (NoSuchMethodException | ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
try {
return new FastQueue_1_8();
} catch (NoSuchMethodException | NoSuchFieldException | ClassNotFoundException e2) {
e2.printStackTrace();
return new SlowQueue();
}
}
}
try {
return new FastQueue_1_7();
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
return new SlowQueue();
} }
return QueueProvider.of(BukkitLocalQueue_1_7.class, BukkitLocalQueue.class);
} }
@Override @Override

View File

@ -9,93 +9,103 @@ import java.util.Collection;
/** /**
* Represents a wrapper around an array class of an arbitrary reference type, * Represents a wrapper around an array class of an arbitrary reference type,
* which properly implements "value" hash code and equality functions. * which properly implements "value" hash code and equality functions.
* <p>
* This class is intended for use as a key to a map.
* </p>
* *
* <p>This class is intended for use as a key to a map.
*
* @author Glen Husman
* @param <E> The type of elements in the array. * @param <E> The type of elements in the array.
* @author Glen Husman
* @see Arrays * @see Arrays
*/ */
public final class ArrayWrapper<E> { public final class ArrayWrapper<E> {
private E[] array; /**
* Creates an array wrapper with some elements.
*
* @param elements The elements of the array.
*/
public ArrayWrapper(E... elements) {
setArray(elements);
}
/** private E[] _array;
* Creates an array wrapper with some elements.
* @param elements The elements of the array.
*/
public ArrayWrapper(E... elements) {
setArray(elements);
}
/** /**
* Converts an iterable element collection to an array of elements. * Retrieves a reference to the wrapped array instance.
* 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. * @return The array wrapped by this instance.
* @param c The type of the elements of the array. */
* @return An array of elements in the specified iterable. public E[] getArray() {
*/ return _array;
@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; * Set this wrapper to wrap a new array instance.
// Ugly hack: Count it ourselves *
for (@SuppressWarnings("unused") T element : list) { * @param array The new wrapped array.
size++; */
} public void setArray(E[] array) {
} Validate.notNull(array, "The array must not be null.");
_array = array;
}
T[] result = (T[]) Array.newInstance(c, size); /**
int i = 0; * Determines if this object has a value equivalent to another object.
for (T element : list) { // Assumes iteration order is consistent *
result[i++] = element; // Assign array element at index THEN increment counter * @see Arrays#equals(Object[], Object[])
} */
return result; @SuppressWarnings("rawtypes")
} @Override
public boolean equals(Object other) {
if (!(other instanceof ArrayWrapper)) {
return false;
}
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
}
/** /**
* Retrieves a reference to the wrapped array instance. * Gets the hash code represented by this objects value.
* @return The array wrapped by this instance. *
*/ * @return This object's hash code.
public E[] getArray() { * @see Arrays#hashCode(Object[])
return this.array; */
} @Override
public int hashCode() {
return Arrays.hashCode(_array);
}
/** /**
* Set this wrapper to wrap a new array instance. * Converts an iterable element collection to an array of elements.
* @param array The new wrapped array. * The iteration order of the specified object will be used as the array element order.
*/ *
public void setArray(E[] array) { * @param list The iterable of objects which will be converted to an array.
Validate.notNull(array, "The array must not be null."); * @param c The type of the elements of the array.
this.array = 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();
}
/**
* 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(this.array, ((ArrayWrapper) other).array);
}
/** if (size < 0) {
* Gets the hash code represented by this objects value. size = 0;
* @see Arrays#hashCode(Object[]) // Ugly hack: Count it ourselves
* @return This object's hash code. for (@SuppressWarnings("unused") T element : list) {
*/ size++;
@Override }
public int hashCode() { }
return Arrays.hashCode(this.array);
} 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;
}
} }

View File

@ -9,11 +9,11 @@ import java.io.IOException;
*/ */
interface JsonRepresentedObject { interface JsonRepresentedObject {
/** /**
* Writes the JSON representation of this object to the specified writer. * Writes the JSON representation of this object to the specified writer.
* @param writer The JSON writer which will receive the object. * @param writer The JSON writer which will receive the object.
* @throws IOException If an error occurs writing to the stream. * @throws IOException If an error occurs writing to the stream.
*/ */
void writeJson(JsonWriter writer) throws IOException; public void writeJson(JsonWriter writer) throws IOException;
} }

View File

@ -1,12 +1,12 @@
package com.plotsquared.bukkit.chat; package com.plotsquared.bukkit.chat;
import com.google.gson.stream.JsonWriter;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.google.gson.stream.JsonWriter;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
/** /**
* Represents a JSON string value. * Represents a JSON string value.
* Writes by this object will not write name values nor begin/end objects in the JSON stream. * Writes by this object will not write name values nor begin/end objects in the JSON stream.
@ -14,34 +14,34 @@ import java.util.Map;
*/ */
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable { final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
private final String value; private String _value;
public JsonString(CharSequence value) { public JsonString(CharSequence value) {
this.value = value == null ? null : value.toString(); _value = value == null ? null : value.toString();
} }
public static JsonString deserialize(Map<String, Object> map) { @Override
return new JsonString(map.get("stringValue").toString()); public void writeJson(JsonWriter writer) throws IOException {
} writer.value(getValue());
}
@Override public String getValue() {
public void writeJson(JsonWriter writer) throws IOException { return _value;
writer.value(getValue()); }
}
public String getValue() { public Map<String, Object> serialize() {
return this.value; HashMap<String, Object> theSingleValue = new HashMap<String, Object>();
} theSingleValue.put("stringValue", _value);
return theSingleValue;
}
@Override public static JsonString deserialize(Map<String, Object> map) {
public Map<String, Object> serialize() { return new JsonString(map.get("stringValue").toString());
HashMap<String, Object> theSingleValue = new HashMap<>(); }
theSingleValue.put("stringValue", this.value);
return theSingleValue; @Override
} public String toString() {
return _value;
}
@Override
public String toString() {
return this.value;
}
} }

View File

@ -3,10 +3,10 @@ package com.plotsquared.bukkit.chat;
import com.google.common.collect.BiMap; import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableBiMap;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,133 +19,137 @@ import java.util.logging.Level;
*/ */
final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable { final class MessagePart implements JsonRepresentedObject, ConfigurationSerializable, Cloneable {
static final BiMap<ChatColor, String> stylesToNames; ChatColor color = ChatColor.WHITE;
ArrayList<ChatColor> styles = new ArrayList<ChatColor>();
String clickActionName = null, clickActionData = null, hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<JsonRepresentedObject>();
static { MessagePart(final TextualComponent text) {
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder(); this.text = text;
for (ChatColor style : ChatColor.values()) { }
if (!style.isFormat()) {
continue;
}
String styleName; MessagePart() {
switch (style) { this.text = null;
case MAGIC: }
styleName = "obfuscated";
break;
case UNDERLINE:
styleName = "underlined";
break;
default:
styleName = style.name().toLowerCase();
break;
}
builder.put(style, styleName); boolean hasText() {
} return text != null;
stylesToNames = builder.build(); }
}
static { @Override
ConfigurationSerialization.registerClass(MessagePart.class); @SuppressWarnings("unchecked")
} public MessagePart clone() throws CloneNotSupportedException {
MessagePart obj = (MessagePart) super.clone();
obj.styles = (ArrayList<ChatColor>) styles.clone();
if (hoverActionData instanceof JsonString) {
obj.hoverActionData = new JsonString(((JsonString) hoverActionData).getValue());
} else if (hoverActionData instanceof FancyMessage) {
obj.hoverActionData = ((FancyMessage) hoverActionData).clone();
}
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) translationReplacements.clone();
return obj;
ChatColor color = ChatColor.WHITE; }
ArrayList<ChatColor> styles = new ArrayList<>();
String clickActionName = null, clickActionData = null, hoverActionName = null;
JsonRepresentedObject hoverActionData = null;
TextualComponent text = null;
String insertionData = null;
ArrayList<JsonRepresentedObject> translationReplacements = new ArrayList<>();
MessagePart(TextualComponent text) { static final BiMap<ChatColor, String> stylesToNames;
this.text = text;
}
MessagePart() { static {
this.text = null; ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
} for (final ChatColor style : ChatColor.values()) {
if (!style.isFormat()) {
continue;
}
@SuppressWarnings("unchecked") String styleName;
public static MessagePart deserialize(Map<String, Object> serialized) { switch (style) {
MessagePart part = new MessagePart((TextualComponent) serialized.get("text")); case MAGIC:
part.styles = (ArrayList<ChatColor>) serialized.get("styles"); styleName = "obfuscated";
part.color = ChatColor.getByChar(serialized.get("color").toString()); break;
part.hoverActionName = (String) serialized.get("hoverActionName"); case UNDERLINE:
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData"); styleName = "underlined";
part.clickActionName = (String) serialized.get("clickActionName"); break;
part.clickActionData = (String) serialized.get("clickActionData"); default:
part.insertionData = (String) serialized.get("insertion"); styleName = style.name().toLowerCase();
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements"); break;
return part; }
}
boolean hasText() { builder.put(style, styleName);
return this.text != null; }
} stylesToNames = builder.build();
}
@Override public void writeJson(JsonWriter json) {
@SuppressWarnings("unchecked") try {
public MessagePart clone() throws CloneNotSupportedException { json.beginObject();
MessagePart obj = (MessagePart) super.clone(); text.writeJson(json);
obj.styles = (ArrayList<ChatColor>) this.styles.clone(); json.name("color").value(color.name().toLowerCase());
if (this.hoverActionData instanceof JsonString) { for (final ChatColor style : styles) {
obj.hoverActionData = new JsonString(((JsonString) this.hoverActionData).getValue()); json.name(stylesToNames.get(style)).value(true);
} else if (this.hoverActionData instanceof FancyMessage) { }
obj.hoverActionData = ((FancyMessage) this.hoverActionData).clone(); if (clickActionName != null && clickActionData != null) {
} json.name("clickEvent")
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) this.translationReplacements.clone(); .beginObject()
return obj; .name("action").value(clickActionName)
.name("value").value(clickActionData)
.endObject();
}
if (hoverActionName != null && hoverActionData != null) {
json.name("hoverEvent")
.beginObject()
.name("action").value(hoverActionName)
.name("value");
hoverActionData.writeJson(json);
json.endObject();
}
if (insertionData != null) {
json.name("insertion").value(insertionData);
}
if (translationReplacements.size() > 0 && text != null && TextualComponent.isTranslatableText(text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occured during writing of JSON string", e);
}
}
} public Map<String, Object> serialize() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("text", text);
map.put("styles", styles);
map.put("color", color.getChar());
map.put("hoverActionName", hoverActionName);
map.put("hoverActionData", hoverActionData);
map.put("clickActionName", clickActionName);
map.put("clickActionData", clickActionData);
map.put("insertion", insertionData);
map.put("translationReplacements", translationReplacements);
return map;
}
@Override @SuppressWarnings("unchecked")
public void writeJson(JsonWriter json) { public static MessagePart deserialize(Map<String, Object> serialized) {
try { MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
json.beginObject(); part.styles = (ArrayList<ChatColor>) serialized.get("styles");
this.text.writeJson(json); part.color = ChatColor.getByChar(serialized.get("color").toString());
json.name("color").value(this.color.name().toLowerCase()); part.hoverActionName = (String) serialized.get("hoverActionName");
for (ChatColor style : this.styles) { part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
json.name(stylesToNames.get(style)).value(true); part.clickActionName = (String) serialized.get("clickActionName");
} part.clickActionData = (String) serialized.get("clickActionData");
if ((this.clickActionName != null) && (this.clickActionData != null)) { part.insertionData = (String) serialized.get("insertion");
json.name("clickEvent").beginObject().name("action").value(this.clickActionName).name("value").value(this.clickActionData) part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
.endObject(); return part;
} }
if ((this.hoverActionName != null) && (this.hoverActionData != null)) {
json.name("hoverEvent").beginObject().name("action").value(this.hoverActionName).name("value");
this.hoverActionData.writeJson(json);
json.endObject();
}
if (this.insertionData != null) {
json.name("insertion").value(this.insertionData);
}
if (!this.translationReplacements.isEmpty() && (this.text != null) && TextualComponent.isTranslatableText(this.text)) {
json.name("with").beginArray();
for (JsonRepresentedObject obj : this.translationReplacements) {
obj.writeJson(json);
}
json.endArray();
}
json.endObject();
} catch (IOException e) {
Bukkit.getLogger().log(Level.WARNING, "A problem occurred during writing of JSON string", e);
}
}
@Override static {
public Map<String, Object> serialize() { ConfigurationSerialization.registerClass(MessagePart.class);
HashMap<String, Object> map = new HashMap<>(); }
map.put("text", this.text);
map.put("styles", this.styles);
map.put("color", this.color.getChar());
map.put("hoverActionName", this.hoverActionName);
map.put("hoverActionData", this.hoverActionData);
map.put("clickActionName", this.clickActionName);
map.put("clickActionData", this.clickActionData);
map.put("insertion", this.insertionData);
map.put("translationReplacements", this.translationReplacements);
return map;
}
} }

View File

@ -1,9 +1,8 @@
package com.plotsquared.bukkit.chat; package com.plotsquared.bukkit.chat;
import com.intellectualcrafters.plot.PS; import org.bukkit.Bukkit;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -15,191 +14,205 @@ import java.util.Map;
*/ */
public final class Reflection { public final class Reflection {
/** private static String _versionString;
* 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 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 static synchronized String getVersion() {
return PS.get().IMP.getNMSPackage();
}
/** /**
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package. * Gets the version string from the package name of the CraftBukkit server implementation.
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this * This is needed to bypass the JAR package name changing on each update.
* method simultaneously). *
* @param className The name of the class, excluding the package, within NMS. * @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded. */
*/ public synchronized static String getVersion() {
public static synchronized Class<?> getNMSClass(String className) { if (_versionString == null) {
if (_loadedNMSClasses.containsKey(className)) { if (Bukkit.getServer() == null) {
return _loadedNMSClasses.get(className); // The server hasn't started, static initializer call?
} return null;
}
String name = Bukkit.getServer().getClass().getPackage().getName();
_versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
}
String fullName = "net.minecraft.server." + getVersion() + '.' + className; return _versionString;
Class<?> clazz; }
try {
clazz = Class.forName(fullName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
_loadedNMSClasses.put(className, null);
return null;
}
_loadedNMSClasses.put(className, clazz);
return clazz;
}
/** /**
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package. * Stores loaded classes from the {@code net.minecraft.server} 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). private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<String, Class<?>>();
* @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 static synchronized Class<?> getOBCClass(String className) {
if (_loadedOBCClasses.containsKey(className)) {
return _loadedOBCClasses.get(className);
}
String fullName = "org.bukkit.craftbukkit." + getVersion() + '.' + className; /**
Class<?> clazz; * Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
try { */
clazz = Class.forName(fullName); private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<String, Class<?>>();
} catch (ClassNotFoundException e) {
e.printStackTrace();
_loadedOBCClasses.put(className, null);
return null;
}
_loadedOBCClasses.put(className, clazz);
return clazz;
}
/** /**
* Attempts to get the NMS handle of a CraftBukkit object. * Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
* <p> * 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).
* 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. * @param className The name of the class, excluding the package, within NMS.
* </p> * @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
* @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 Class<?> getNMSClass(String className) {
*/ if (_loadedNMSClasses.containsKey(className)) {
public static synchronized Object getHandle(Object obj) { return _loadedNMSClasses.get(className);
try { }
return getMethod(obj.getClass(), "getHandle").invoke(obj);
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {
e.printStackTrace();
return null;
}
}
/** String fullName = "net.minecraft.server." + getVersion() + className;
* Retrieves a {@link Field} instance declared by the specified class with the specified name. Class<?> clazz = null;
* Java access modifiers are ignored during this retrieval. try {
* No guarantee is made as to whether the field returned will be an clazz = Class.forName(fullName);
* instance or static field. } catch (Exception e) {
* <p> e.printStackTrace();
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that _loadedNMSClasses.put(className, null);
* no field will be reflectively looked up twice. return null;
* </p> }
* <p> _loadedNMSClasses.put(className, clazz);
* If a field is deemed suitable for return, return clazz;
* {@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 static synchronized 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. * Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field * 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).
* returned will be an instance or static field. *
* <p> * @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory.CraftItemStack}.
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that * @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
* no method will be reflectively looked up twice. */
* </p> public synchronized static Class<?> getOBCClass(String className) {
* <p> if (_loadedOBCClasses.containsKey(className)) {
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code return _loadedOBCClasses.get(className);
* 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>
*
* <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 static synchronized Method getMethod(Class<?> clazz, String name, Class<?>... args) {
if (!_loadedMethods.containsKey(clazz)) {
_loadedMethods.put(clazz, new HashMap<String, Map<ArrayWrapper<Class<?>>, Method>>());
}
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz); String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
if (!loadedMethodNames.containsKey(name)) { Class<?> clazz = null;
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>()); try {
} clazz = Class.forName(fullName);
} catch (Exception e) {
e.printStackTrace();
_loadedOBCClasses.put(className, null);
return null;
}
_loadedOBCClasses.put(className, clazz);
return clazz;
}
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name); /**
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<>(args); * Attempts to get the NMS handle of a CraftBukkit object.
if (loadedSignatures.containsKey(wrappedArg)) { * <p>
return loadedSignatures.get(wrappedArg); * 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) {
try {
return getMethod(obj.getClass(), "getHandle").invoke(obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
for (Method m : clazz.getMethods()) { private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<Class<?>, Map<String, Field>>();
if (m.getName().equals(name) && Arrays.equals(args, m.getParameterTypes())) {
m.setAccessible(true); /**
loadedSignatures.put(wrappedArg, m); * Retrieves a {@link Field} instance declared by the specified class with the specified name.
return m; * 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>
loadedSignatures.put(wrappedArg, null); * A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
return null; * 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<String, Field>();
_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 (Exception e) {
// Error loading
e.printStackTrace();
// Cache field as not existing
loaded.put(name, null);
return null;
}
}
/**
* 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<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>>();
/**
* 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>
* <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>
* <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<String, Map<ArrayWrapper<Class<?>>, Method>>());
}
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz);
if (!loadedMethodNames.containsKey(name)) {
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>());
}
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<Class<?>>(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;
}
} }

View File

@ -3,8 +3,8 @@ package com.plotsquared.bukkit.chat;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable; import org.bukkit.configuration.serialization.ConfigurationSerializable;
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization; import org.bukkit.configuration.serialization.ConfigurationSerialization;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
@ -18,285 +18,280 @@ import java.util.Map;
*/ */
public abstract class TextualComponent implements Cloneable { public abstract class TextualComponent implements Cloneable {
static { static {
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class); ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class); ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
} }
static TextualComponent deserialize(Map<String, Object> map) { @Override
if (map.containsKey("key") && (map.size() == 2) && map.containsKey("value")) { public String toString() {
// Arbitrary text component return getReadableString();
return ArbitraryTextTypeComponent.deserialize(map); }
} else if ((map.size() >= 2) && map.containsKey("key") && !map.containsKey("value") /* It contains keys that START WITH value */) {
// Complex JSON object
return ComplexTextTypeComponent.deserialize(map);
}
return null; /**
} * @return The JSON key used to represent text components of this type.
*/
public abstract String getKey();
static boolean isTextKey(String key) { /**
return key.equals("translate") || key.equals("text") || key.equals("score") || key.equals("selector"); * @return A readable String
} */
public abstract String getReadableString();
static boolean isTranslatableText(TextualComponent component) { /**
return (component instanceof ComplexTextTypeComponent) && component.getKey().equals("translate"); * Clones a textual component instance.
} * The returned object should not reference this textual component instance, but should maintain the same key and value.
*/
@Override
public abstract TextualComponent clone() throws CloneNotSupportedException;
/** /**
* Create a textual component representing a string literal. * Writes the text data represented by this textual component to the specified JSON writer object.
* This is the default type of textual component when a single string literal is given to a method. * A new object within the writer is not started.
* @param textValue The text which will be represented. *
* @return The text component representing the specified literal text. * @param writer The object to which to write the JSON data.
*/ * @throws IOException If an error occurs while writing to the stream.
public static TextualComponent rawText(String textValue) { */
return new ArbitraryTextTypeComponent("text", textValue); public abstract void writeJson(JsonWriter writer) throws IOException;
}
/** static TextualComponent deserialize(Map<String, Object> map) {
* Create a textual component representing a localized string. if (map.containsKey("key") && map.size() == 2 && map.containsKey("value")) {
* The client will see this text component as their localized version of the specified string <em>key</em>, which can be overridden by a // Arbitrary text component
* resource pack. return ArbitraryTextTypeComponent.deserialize(map);
* <p> } else if (map.size() >= 2 && map.containsKey("key") && !map.containsKey("value") /* It contains keys that START WITH value */) {
* If the specified translation key is not present on the client resource pack, the translation key will be displayed as a string literal to // Complex JSON object
* the client. return ComplexTextTypeComponent.deserialize(map);
* </p> }
* @param translateKey The string key which maps to localized text.
* @return The text component representing the specified localized text.
*/
public static TextualComponent localizedText(String translateKey) {
return new ArbitraryTextTypeComponent("translate", translateKey);
}
private static void throwUnsupportedSnapshot() { return null;
throw new UnsupportedOperationException("This feature is only supported in snapshot releases."); }
}
/** static boolean isTextKey(String key) {
* Create a textual component representing a scoreboard value. return key.equals("translate") || key.equals("text") || key.equals("score") || key.equals("selector");
* The client will see their own score for the specified objective as the text represented by this component. }
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score (for the viewing player), or {@code null} if an error occurs during
* JSON serialization.
*/
public static TextualComponent objectiveScore(String scoreboardObjective) {
return objectiveScore("*", scoreboardObjective);
}
/** static boolean isTranslatableText(TextualComponent component) {
* Create a textual component representing a scoreboard value. return component instanceof ComplexTextTypeComponent && ((ComplexTextTypeComponent) component).getKey().equals("translate");
* The client will see the score of the specified player for the specified objective as the text represented by this component. }
* <p>
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
* @param playerName The name of the player whos score will be shown. If this string represents the single-character sequence "*", the viewing
* player's score will be displayed.
* Standard minecraft selectors (@a, @p, etc) are <em>not</em> supported.
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score for the specified player, or {@code null} if an error occurs during
* JSON serialization.
*/
public static TextualComponent objectiveScore(String playerName, String scoreboardObjective) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE
// OVERLOADS documentation accordingly
return new ComplexTextTypeComponent("score", /**
ImmutableMap.<String, String>builder().put("name", playerName).put("objective", scoreboardObjective).build()); * Internal class used to represent all types of text components.
} * Exception validating done is on keys and values.
*/
private static final class ArbitraryTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
/** public ArbitraryTextTypeComponent(String key, String value) {
* Create a textual component representing a player name, retrievable by using a standard minecraft selector. setKey(key);
* The client will see the players or entities captured by the specified selector as the text represented by this component. setValue(value);
* <p> }
* <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
* @param selector The minecraft player or entity selector which will capture the entities whose string representations will be displayed in
* the place of this text component.
* @return The text component representing the name of the entities captured by the selector.
*/
public static TextualComponent selector(String selector) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE
// OVERLOADS documentation accordingly
return new ArbitraryTextTypeComponent("selector", selector); @Override
} public String getKey() {
return _key;
}
@Override public void setKey(String key) {
public String toString() { Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
return getReadableString(); _key = key;
} }
/** public String getValue() {
* @return The JSON key used to represent text components of this type. return _value;
*/ }
public abstract String getKey();
/** public void setValue(String value) {
* @return A readable String Preconditions.checkArgument(value != null, "The value must be specified.");
*/ _value = value;
public abstract String getReadableString(); }
/** private String _key;
* Clones a textual component instance. private String _value;
* The returned object should not reference this textual component instance, but should maintain the same key and value.
*/
@Override
public abstract TextualComponent clone() throws CloneNotSupportedException;
/** @Override
* Writes the text data represented by this textual component to the specified JSON writer object. public TextualComponent clone() throws CloneNotSupportedException {
* A new object within the writer is not started. // Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
* @param writer The object to which to write the JSON data. return new ArbitraryTextTypeComponent(getKey(), getValue());
* @throws IOException If an error occurs while writing to the stream. }
*/
public abstract void writeJson(JsonWriter writer) throws IOException;
/** @Override
* Internal class used to represent all types of text components. public void writeJson(JsonWriter writer) throws IOException {
* Exception validating done is on keys and values. writer.name(getKey()).value(getValue());
*/ }
private static final class ArbitraryTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
private String _key; @SuppressWarnings("serial")
private String _value; public Map<String, Object> serialize() {
return new HashMap<String, Object>() {{
put("key", getKey());
put("value", getValue());
}};
}
public ArbitraryTextTypeComponent(String key, String value) { public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) {
setKey(key); return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString());
setValue(value); }
}
public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) { @Override
return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString()); public String getReadableString() {
} return getValue();
}
}
@Override /**
public String getKey() { * Internal class used to represent a text component with a nested JSON value.
return this._key; * Exception validating done is on keys and values.
} */
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
public void setKey(String key) { public ComplexTextTypeComponent(String key, Map<String, String> values) {
Preconditions.checkArgument((key != null) && !key.isEmpty(), "The key must be specified."); setKey(key);
this._key = key; setValue(values);
} }
public String getValue() { @Override
return this._value; public String getKey() {
} return _key;
}
public void setValue(String value) { public void setKey(String key) {
Preconditions.checkArgument(value != null, "The value must be specified."); Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
this._value = value; _key = key;
} }
@Override public Map<String, String> getValue() {
public TextualComponent clone() { return _value;
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone }
return new ArbitraryTextTypeComponent(getKey(), getValue());
}
@Override public void setValue(Map<String, String> value) {
public void writeJson(JsonWriter writer) throws IOException { Preconditions.checkArgument(value != null, "The value must be specified.");
writer.name(getKey()).value(getValue()); _value = value;
} }
@Override private String _key;
@SuppressWarnings("serial") private Map<String, String> _value;
public Map<String, Object> serialize() {
return new HashMap<String, Object>() {
{
put("key", getKey());
put("value", getValue());
}
};
}
@Override @Override
public String getReadableString() { public TextualComponent clone() throws CloneNotSupportedException {
return getValue(); // Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
} return new ComplexTextTypeComponent(getKey(), getValue());
} }
/** @Override
* Internal class used to represent a text component with a nested JSON value. public void writeJson(JsonWriter writer) throws IOException {
* Exception validating done is on keys and values. writer.name(getKey());
*/ writer.beginObject();
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable { for (Map.Entry<String, String> jsonPair : _value.entrySet()) {
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
}
writer.endObject();
}
private String _key; @SuppressWarnings("serial")
private Map<String, String> _value; public Map<String, Object> serialize() {
return new java.util.HashMap<String, Object>() {{
put("key", getKey());
for (Map.Entry<String, String> valEntry : getValue().entrySet()) {
put("value." + valEntry.getKey(), valEntry.getValue());
}
}};
}
public ComplexTextTypeComponent(String key, Map<String, String> values) { public static ComplexTextTypeComponent deserialize(Map<String, Object> map) {
setKey(key); String key = null;
setValue(values); Map<String, String> value = new HashMap<String, String>();
} for (Map.Entry<String, Object> valEntry : map.entrySet()) {
if (valEntry.getKey().equals("key")) {
key = (String) valEntry.getValue();
} else if (valEntry.getKey().startsWith("value.")) {
value.put(((String) valEntry.getKey()).substring(6) /* Strips out the value prefix */, valEntry.getValue().toString());
}
}
return new ComplexTextTypeComponent(key, value);
}
public static ComplexTextTypeComponent deserialize(Map<String, Object> map) { @Override
String key = null; public String getReadableString() {
Map<String, String> value = new HashMap<>(); return getKey();
for (Map.Entry<String, Object> valEntry : map.entrySet()) { }
if (valEntry.getKey().equals("key")) { }
key = (String) valEntry.getValue();
} else if (valEntry.getKey().startsWith("value.")) {
value.put(valEntry.getKey().substring(6) /* Strips out the value prefix */, valEntry.getValue().toString());
}
}
return new ComplexTextTypeComponent(key, value);
}
@Override /**
public String getKey() { * Create a textual component representing a string literal.
return this._key; * This is the default type of textual component when a single string literal is given to a method.
} *
* @param textValue The text which will be represented.
* @return The text component representing the specified literal text.
*/
public static TextualComponent rawText(String textValue) {
return new ArbitraryTextTypeComponent("text", textValue);
}
public void setKey(String key) {
Preconditions.checkArgument((key != null) && !key.isEmpty(), "The key must be specified.");
this._key = key;
}
public Map<String, String> getValue() { /**
return this._value; * Create a textual component representing a localized string.
} * The client will see this text component as their localized version of the specified string <em>key</em>, which can be overridden by a resource pack.
* <p>
* If the specified translation key is not present on the client resource pack, the translation key will be displayed as a string literal to the client.
* </p>
*
* @param translateKey The string key which maps to localized text.
* @return The text component representing the specified localized text.
*/
public static TextualComponent localizedText(String translateKey) {
return new ArbitraryTextTypeComponent("translate", translateKey);
}
public void setValue(Map<String, String> value) { private static void throwUnsupportedSnapshot() {
Preconditions.checkArgument(value != null, "The value must be specified."); throw new UnsupportedOperationException("This feature is only supported in snapshot releases.");
this._value = value; }
}
@Override /**
public TextualComponent clone() { * Create a textual component representing a scoreboard value.
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone * The client will see their own score for the specified objective as the text represented by this component.
return new ComplexTextTypeComponent(getKey(), getValue()); * <p>
} * <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score (for the viewing player), or {@code null} if an error occurs during JSON serialization.
*/
public static TextualComponent objectiveScore(String scoreboardObjective) {
return objectiveScore("*", scoreboardObjective);
}
@Override /**
public void writeJson(JsonWriter writer) throws IOException { * Create a textual component representing a scoreboard value.
writer.name(getKey()); * The client will see the score of the specified player for the specified objective as the text represented by this component.
writer.beginObject(); * <p>
for (Map.Entry<String, String> jsonPair : this._value.entrySet()) { * <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
writer.name(jsonPair.getKey()).value(jsonPair.getValue()); * </p>
} *
writer.endObject(); * @param playerName The name of the player whos score will be shown. If this string represents the single-character sequence "*", the viewing player's score will be displayed.
} * Standard minecraft selectors (@a, @p, etc) are <em>not</em> supported.
* @param scoreboardObjective The name of the objective for which to display the score.
* @return The text component representing the specified scoreboard score for the specified player, or {@code null} if an error occurs during JSON serialization.
*/
public static TextualComponent objectiveScore(String playerName, String scoreboardObjective) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
@Override return new ComplexTextTypeComponent("score", ImmutableMap.<String, String>builder()
@SuppressWarnings("serial") .put("name", playerName)
public Map<String, Object> serialize() { .put("objective", scoreboardObjective)
return new HashMap<String, Object>() { .build());
{ }
put("key", getKey());
for (Map.Entry<String, String> valEntry : getValue().entrySet()) {
put("value." + valEntry.getKey(), valEntry.getValue());
}
}
};
}
@Override /**
public String getReadableString() { * Create a textual component representing a player name, retrievable by using a standard minecraft selector.
return getKey(); * The client will see the players or entities captured by the specified selector as the text represented by this component.
} * <p>
} * <b>This method is currently guaranteed to throw an {@code UnsupportedOperationException} as it is only supported on snapshot clients.</b>
* </p>
*
* @param selector The minecraft player or entity selector which will capture the entities whose string representations will be displayed in the place of this text component.
* @return The text component representing the name of the entities captured by the selector.
*/
public static TextualComponent selector(String selector) {
throwUnsupportedSnapshot(); // Remove this line when the feature is released to non-snapshot versions, in addition to updating ALL THE OVERLOADS documentation accordingly
return new ArbitraryTextTypeComponent("selector", selector);
}
} }

View File

@ -5,6 +5,8 @@ import com.intellectualcrafters.plot.generator.GeneratorWrapper;
import com.intellectualcrafters.plot.generator.HybridGen; import com.intellectualcrafters.plot.generator.HybridGen;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator; import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotManager;
@ -12,25 +14,26 @@ import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.SetupObject; import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.block.GenChunk; import com.plotsquared.bukkit.util.block.GenChunk;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> { public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrapper<ChunkGenerator> {
private final PlotChunk<Chunk> chunkSetter; private final GenChunk chunkSetter;
private final PseudoRandom random = new PseudoRandom(); private final PseudoRandom random = new PseudoRandom();
private final IndependentPlotGenerator plotGenerator; private final IndependentPlotGenerator plotGenerator;
private final List<BlockPopulator> populators = new ArrayList<>(); private final List<BlockPopulator> populators = new ArrayList<>();
@ -46,14 +49,20 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
this.plotGenerator = generator; this.plotGenerator = generator;
this.platformGenerator = this; this.platformGenerator = this;
this.populators.add(new BlockPopulator() { this.populators.add(new BlockPopulator() {
private LocalBlockQueue queue;
@Override @Override
public void populate(World world, Random r, Chunk c) { public void populate(World world, Random r, Chunk c) {
if (queue == null) {
queue = GlobalBlockQueue.IMP.getNewQueue(world.getName(), false);
}
ChunkLoc loc = new ChunkLoc(c.getX(), c.getZ()); ChunkLoc loc = new ChunkLoc(c.getX(), c.getZ());
byte[][] resultData; byte[][] resultData;
if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) { if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) {
GenChunk result = (GenChunk) BukkitPlotGenerator.this.chunkSetter; GenChunk result = BukkitPlotGenerator.this.chunkSetter;
// Set the chunk location // Set the chunk location
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), loc.x, loc.z)); result.setChunk(c);
// Set the result data // Set the result data
result.result = new short[16][]; result.result = new short[16][];
result.result_data = new byte[16][]; result.result_data = new byte[16][];
@ -81,10 +90,10 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
} }
BukkitPlotGenerator.this.random.state = c.getX() << 16 | c.getZ() & 0xFFFF; BukkitPlotGenerator.this.random.state = c.getX() << 16 | c.getZ() & 0xFFFF;
PlotArea area = PS.get().getPlotArea(world.getName(), null); PlotArea area = PS.get().getPlotArea(world.getName(), null);
SetQueue.ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(area.worldname, c.getX(), c.getZ()); ChunkWrapper wrap = new ChunkWrapper(area.worldname, c.getX(), c.getZ());
PlotChunk<?> chunk = SetQueue.IMP.queue.getChunk(wrap); ScopedLocalBlockQueue chunk = queue.getForChunk(wrap.x, wrap.z);
if (BukkitPlotGenerator.this.plotGenerator.populateChunk(chunk, area, BukkitPlotGenerator.this.random)) { if (BukkitPlotGenerator.this.plotGenerator.populateChunk(chunk, area, BukkitPlotGenerator.this.random)) {
chunk.addToQueue(); queue.flush();
} }
} }
}); });
@ -123,13 +132,16 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
} }
@Override @Override
public void generateChunk(final PlotChunk<?> result, PlotArea settings, PseudoRandom random) { public void generateChunk(final ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
World w = BukkitUtil.getWorld(world); World w = BukkitUtil.getWorld(world);
Random r = new Random(result.getChunkWrapper().hashCode()); Location min = result.getMin();
int cx = min.getX() >> 4;
int cz = min.getZ() >> 4;
Random r = new Random(MathMan.pair((short) cx, (short) cz));
BiomeGrid grid = new BiomeGrid() { BiomeGrid grid = new BiomeGrid() {
@Override @Override
public void setBiome(int x, int z, Biome biome) { public void setBiome(int x, int z, Biome biome) {
result.setBiome(x, z, biome.ordinal()); result.setBiome(x, z, biome.name());
} }
@Override @Override
@ -139,13 +151,13 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
}; };
try { try {
// ChunkData will spill a bit // ChunkData will spill a bit
ChunkData data = cg.generateChunkData(w, r, result.getX(), result.getZ(), grid); ChunkData data = cg.generateChunkData(w, r, cx, cz, grid);
if (data != null) { if (data != null) {
return; return;
} }
} catch (Throwable ignored) {} } catch (Throwable ignored) {}
// Populator spillage // Populator spillage
short[][] tmp = cg.generateExtBlockSections(w, r, result.getX(), result.getZ(), grid); short[][] tmp = cg.generateExtBlockSections(w, r, cx, cz, grid);
if (tmp != null) { if (tmp != null) {
for (int i = 0; i < tmp.length; i++) { for (int i = 0; i < tmp.length; i++) {
short[] section = tmp[i]; short[] section = tmp[i];
@ -170,11 +182,11 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
} }
} }
for (BlockPopulator populator : cg.getDefaultPopulators(w)) { for (BlockPopulator populator : cg.getDefaultPopulators(w)) {
populator.populate(w, r, (Chunk) result.getChunk()); populator.populate(w, r, w.getChunkAt(cx, cz));
} }
} }
}; };
this.chunkSetter = new GenChunk(null, SetQueue.IMP.new ChunkWrapper(world, 0, 0)); this.chunkSetter = new GenChunk(null, new ChunkWrapper(world, 0, 0));
if (cg != null) { if (cg != null) {
this.populators.addAll(cg.getDefaultPopulators(BukkitUtil.getWorld(world))); this.populators.addAll(cg.getDefaultPopulators(BukkitUtil.getWorld(world)));
} }
@ -245,7 +257,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) { public ChunkData generateChunkData(World world, Random random, int cx, int cz, BiomeGrid grid) {
GenChunk result = (GenChunk) this.chunkSetter; GenChunk result = (GenChunk) this.chunkSetter;
// Set the chunk location // Set the chunk location
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz)); result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
// Set the result data // Set the result data
result.cd = createChunkData(world); result.cd = createChunkData(world);
result.grid = grid; result.grid = grid;
@ -266,7 +278,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
return result.cd; return result.cd;
} }
public void generate(World world, int cx, int cz, PlotChunk<?> result) { public void generate(World world, int cx, int cz, ScopedLocalBlockQueue result) {
// Load if improperly loaded // Load if improperly loaded
if (!this.loaded) { if (!this.loaded) {
String name = world.getName(); String name = world.getName();
@ -293,7 +305,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
public short[][] generateExtBlockSections(World world, Random r, int cx, int cz, BiomeGrid grid) { public short[][] generateExtBlockSections(World world, Random r, int cx, int cz, BiomeGrid grid) {
GenChunk result = (GenChunk) this.chunkSetter; GenChunk result = (GenChunk) this.chunkSetter;
// Set the chunk location // Set the chunk location
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz)); result.setChunk(new ChunkWrapper(world.getName(), cx, cz));
// Set the result data // Set the result data
result.result = new short[16][]; result.result = new short[16][];
result.result_data = new byte[16][]; result.result_data = new byte[16][];

View File

@ -1,6 +1,7 @@
package com.plotsquared.bukkit.util; package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.config.C; import com.intellectualcrafters.plot.config.C;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.ConsolePlayer; import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.PlotMessage; import com.intellectualcrafters.plot.object.PlotMessage;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
@ -45,7 +46,7 @@ public class BukkitChatManager extends ChatManager<FancyMessage> {
@Override @Override
public void send(PlotMessage plotMessage, PlotPlayer player) { public void send(PlotMessage plotMessage, PlotPlayer player) {
if (player instanceof ConsolePlayer) { if (player instanceof ConsolePlayer || !Settings.Chat.INTERACTIVE) {
player.sendMessage(plotMessage.$(this).toOldMessageFormat()); player.sendMessage(plotMessage.$(this).toOldMessageFormat());
} else { } else {
plotMessage.$(this).send(((BukkitPlayer) player).player); plotMessage.$(this).send(((BukkitPlayer) player).player);

View File

@ -9,17 +9,22 @@ import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotLoc; import com.intellectualcrafters.plot.object.PlotLoc;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import com.plotsquared.bukkit.object.entity.EntityWrapper; import com.plotsquared.bukkit.object.entity.EntityWrapper;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
@ -52,16 +57,6 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class BukkitChunkManager extends ChunkManager { public class BukkitChunkManager extends ChunkManager {
public static boolean isIn(RegionWrapper region, int x, int z) { public static boolean isIn(RegionWrapper region, int x, int z) {
@ -91,6 +86,9 @@ public class BukkitChunkManager extends ChunkManager {
String worldName1 = world1.getName(); String worldName1 = world1.getName();
String worldName2 = world2.getName(); String worldName2 = world2.getName();
LocalBlockQueue queue1 = GlobalBlockQueue.IMP.getNewQueue(worldName1, false);
LocalBlockQueue queue2 = GlobalBlockQueue.IMP.getNewQueue(worldName2, false);
for (int x = Math.max(r1.minX, sx); x <= Math.min(r1.maxX, sx + 15); x++) { for (int x = Math.max(r1.minX, sx); x <= Math.min(r1.maxX, sx + 15); x++) {
for (int z = Math.max(r1.minZ, sz); z <= Math.min(r1.maxZ, sz + 15); z++) { for (int z = Math.max(r1.minZ, sz); z <= Math.min(r1.maxZ, sz + 15); z++) {
map.saveBlocks(world1, 256, sx, sz, relX, relZ, false); map.saveBlocks(world1, 256, sx, sz, relX, relZ, false);
@ -105,24 +103,26 @@ public class BukkitChunkManager extends ChunkManager {
byte data2 = block2.getData(); byte data2 = block2.getData();
if (id1 == 0) { if (id1 == 0) {
if (id2 != 0) { if (id2 != 0) {
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) id2, data2); queue1.setBlock(x, y, z, (short) id2, data2);
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) 0, (byte) 0); queue2.setBlock(xx, y, zz, (short) 0, (byte) 0);
} }
} else if (id2 == 0) { } else if (id2 == 0) {
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) 0, (byte) 0); queue1.setBlock(x, y, z, (short) 0, (byte) 0);
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) id1, data1); queue2.setBlock(xx, y, zz, (short) id1, data1);
} else if (id1 == id2) { } else if (id1 == id2) {
if (data1 != data2) { if (data1 != data2) {
block1.setData(data2); block1.setData(data2);
block2.setData(data1); block2.setData(data1);
} }
} else { } else {
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) id2, data2); queue1.setBlock(x, y, z, (short) id2, data2);
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) id1, data1); queue2.setBlock(xx, y, zz, (short) id1, data1);
} }
} }
} }
} }
queue1.enqueue();
queue2.enqueue();
return map; return map;
} }
@ -138,22 +138,6 @@ public class BukkitChunkManager extends ChunkManager {
return chunks; return chunks;
} }
@Override
public void regenerateChunk(String world, ChunkLoc loc) {
World worldObj = Bukkit.getWorld(world);
worldObj.regenerateChunk(loc.x, loc.z);
SetQueue.IMP.queue.sendChunk(world, Collections.singletonList(loc));
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
Location pLoc = pp.getLocation();
if (!StringMan.isEqual(world, pLoc.getWorld()) || !pLoc.getChunkLoc().equals(loc)) {
continue;
}
pLoc.setY(WorldUtil.IMP.getHighestBlock(world, pLoc.getX(), pLoc.getZ()));
pp.teleport(pLoc);
}
}
@Override @Override
public boolean copyRegion(Location pos1, Location pos2, Location newPos, final Runnable whenDone) { public boolean copyRegion(Location pos1, Location pos2, Location newPos, final Runnable whenDone) {
final int relX = newPos.getX() - pos1.getX(); final int relX = newPos.getX() - pos1.getX();
@ -166,6 +150,7 @@ public class BukkitChunkManager extends ChunkManager {
final String newWorldName = newWorld.getName(); final String newWorldName = newWorld.getName();
List<ChunkLoc> chunks = new ArrayList<>(); List<ChunkLoc> chunks = new ArrayList<>();
final ContentMap map = new ContentMap(); final ContentMap map = new ContentMap();
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(newWorldName, false);
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() { ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@Override @Override
public void run(int[] value) { public void run(int[] value) {
@ -193,11 +178,12 @@ public class BukkitChunkManager extends ChunkManager {
for (int y = 0; y < blocks.length; y++) { for (int y = 0; y < blocks.length; y++) {
PlotBlock block = blocks[y]; PlotBlock block = blocks[y];
if (block != null) { if (block != null) {
SetQueue.IMP.setBlock(newWorldName, loc.x, y, loc.z, block); queue.setBlock(loc.x, y, loc.z, block);
} }
} }
} }
SetQueue.IMP.addTask(new Runnable() { queue.enqueue();
GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
map.restoreBlocks(newWorld, 0, 0); map.restoreBlocks(newWorld, 0, 0);
@ -247,12 +233,13 @@ public class BukkitChunkManager extends ChunkManager {
if (!chunkObj.load(false)) { if (!chunkObj.load(false)) {
continue; continue;
} }
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
RegionWrapper currentPlotClear = new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); RegionWrapper currentPlotClear = new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) { if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
AugmentedUtils.bypass(ignoreAugment, new Runnable() { AugmentedUtils.bypass(ignoreAugment, new Runnable() {
@Override @Override
public void run() { public void run() {
regenerateChunk(world, chunk); queue.regenChunkSafe(chunk.x, chunk.z);
} }
}); });
continue; continue;
@ -320,13 +307,12 @@ public class BukkitChunkManager extends ChunkManager {
AugmentedUtils.bypass(ignoreAugment, new Runnable() { AugmentedUtils.bypass(ignoreAugment, new Runnable() {
@Override @Override
public void run() { public void run() {
setChunkInPlotArea(null, new RunnableVal<PlotChunk<?>>() { setChunkInPlotArea(null, new RunnableVal<ScopedLocalBlockQueue>() {
@Override @Override
public void run(PlotChunk<?> value) { public void run(ScopedLocalBlockQueue value) {
int cx = value.getX(); Location min = value.getMin();
int cz = value.getZ(); int bx = min.getX();
int bx = cx << 4; int bz = min.getZ();
int bz = cz << 4;
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
PlotLoc loc = new PlotLoc(bx + x, bz + z); PlotLoc loc = new PlotLoc(bx + x, bz + z);
@ -424,7 +410,7 @@ public class BukkitChunkManager extends ChunkManager {
maps.add(swapChunk(world1, world2, chunk1, chunk2, region1, region2)); maps.add(swapChunk(world1, world2, chunk1, chunk2, region1, region2));
} }
} }
SetQueue.IMP.addTask(new Runnable() { GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
for (ContentMap map : maps) { for (ContentMap map : maps) {

View File

@ -2,7 +2,6 @@ package com.plotsquared.bukkit.util;
import com.intellectualcrafters.plot.generator.HybridUtils; import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
@ -10,19 +9,20 @@ import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import java.util.HashSet;
import java.util.Random;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.material.Directional; import org.bukkit.material.Directional;
import org.bukkit.material.MaterialData; import org.bukkit.material.MaterialData;
import java.util.HashSet;
import java.util.Random;
public class BukkitHybridUtils extends HybridUtils { public class BukkitHybridUtils extends HybridUtils {
@Override @Override
@ -42,6 +42,7 @@ public class BukkitHybridUtils extends HybridUtils {
TaskManager.runTaskAsync(new Runnable() { TaskManager.runTaskAsync(new Runnable() {
@Override @Override
public void run() { public void run() {
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
final World worldObj = Bukkit.getWorld(world); final World worldObj = Bukkit.getWorld(world);
final ChunkGenerator gen = worldObj.getGenerator(); final ChunkGenerator gen = worldObj.getGenerator();
if (gen == null) { if (gen == null) {
@ -254,10 +255,10 @@ public class BukkitHybridUtils extends HybridUtils {
for (int z = minZ; z <= maxZ; z++) { for (int z = minZ; z <= maxZ; z++) {
int zz = cbz + z; int zz = cbz + z;
for (int y = 0; y < 256; y++) { for (int y = 0; y < 256; y++) {
Block block = worldObj.getBlockAt(xx, y, zz); PlotBlock block = queue.getBlock(xx, y, zz);
int xr = xb + x; int xr = xb + x;
int zr = zb + z; int zr = zb + z;
newBlocks[y][xr][zr] = (short) block.getTypeId(); newBlocks[y][xr][zr] = block.id;
} }
} }
} }
@ -272,50 +273,4 @@ public class BukkitHybridUtils extends HybridUtils {
} }
}); });
} }
@Override
public int checkModified(String worldName, int x1, int x2, int y1, int y2, int z1, int z2,
PlotBlock[] blocks) {
World world = BukkitUtil.getWorld(worldName);
int count = 0;
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
Block block = world.getBlockAt(x, y, z);
int id = block.getTypeId();
boolean same = false;
for (PlotBlock p : blocks) {
if (id == p.id) {
same = true;
break;
}
}
if (!same) {
count++;
}
}
}
}
return count;
}
@Override
public int get_ey(String worldName, int sx, int ex, int sz, int ez, int sy) {
World world = BukkitUtil.getWorld(worldName);
int maxY = world.getMaxHeight();
int ey = sy;
for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) {
for (int y = sy; y < maxY; y++) {
if (y > ey) {
Block block = world.getBlockAt(x, y, z);
if (!block.getType().equals(Material.AIR)) {
ey = y;
}
}
}
}
}
return ey;
}
} }

View File

@ -0,0 +1,127 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
public class BukkitLocalQueue<T> extends BasicLocalBlockQueue<T> {
public BukkitLocalQueue(String world) {
super(world);
}
@Override
public LocalChunk<T> getLocalChunk(int x, int z) {
return (LocalChunk<T>) new BasicLocalChunk(this, x, z) {
// Custom stuff?
};
}
@Override
public void optimize() {
}
@Override
public PlotBlock getBlock(int x, int y, int z) {
World worldObj = Bukkit.getWorld(getWorld());
Block block = worldObj.getBlockAt(x, y, z);
if (block == null) {
return PlotBlock.get(0, 0);
}
int id = block.getTypeId();
if (id == 0) {
return PlotBlock.get(0, 0);
}
return PlotBlock.get(id, block.getData());
}
@Override
public void refreshChunk(int x, int z) {
World worldObj = Bukkit.getWorld(getWorld());
worldObj.refreshChunk(x, z);
}
@Override
public void fixChunkLighting(int x, int z) {
// Do nothing
}
@Override
public final void regenChunk(int x, int z) {
World worldObj = Bukkit.getWorld(getWorld());
worldObj.regenerateChunk(x, z);
}
@Override
public final void setComponents(LocalChunk<T> lc) {
setBlocks(lc);
setBiomes(lc);
}
public World getBukkitWorld() {
return Bukkit.getWorld(getWorld());
}
public Chunk getChunk(int x, int z) {
return getBukkitWorld().getChunkAt(x, z);
}
public void setBlocks(LocalChunk<T> lc) {
World worldObj = Bukkit.getWorld(getWorld());
Chunk chunk = worldObj.getChunkAt(lc.getX(), lc.getZ());
chunk.load(true);
for (int layer = 0; layer < lc.blocks.length; layer++) {
PlotBlock[] blocksLayer = (PlotBlock[]) lc.blocks[layer];
if (blocksLayer != null) {
for (int j = 0; j < blocksLayer.length; j++) {
PlotBlock block = blocksLayer[j];
int x = MainUtil.x_loc[layer][j];
int y = MainUtil.y_loc[layer][j];
int z = MainUtil.y_loc[layer][j];
Block existing = chunk.getBlock(x, y, z);
int existingId = existing.getTypeId();
if (existingId == block.id) {
if (existingId == 0) {
continue;
}
if (existing.getData() == block.data) {
continue;
}
}
existing.setTypeIdAndData(block.id, block.data, false);
}
}
}
}
public void setBiomes(LocalChunk<T> lc) {
if (lc.biomes != null) {
World worldObj = Bukkit.getWorld(getWorld());
int bx = lc.getX() << 4;
int bz = lc.getX() << 4;
String last = null;
Biome biome = null;
for (int x = 0; x < lc.biomes.length; x++) {
String[] biomes2 = lc.biomes[x];
if (biomes2 != null) {
for (int y = 0; y < biomes2.length; y++) {
String biomeStr = biomes2[y];
if (biomeStr != null) {
if (last == null || !StringMan.isEqual(last, biomeStr)) {
biome = Biome.valueOf(biomeStr.toUpperCase());
}
worldObj.setBiome(bx, bz, biome);
}
}
}
}
}
}
}

View File

@ -0,0 +1,130 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.SendChunk;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
public class BukkitLocalQueue_1_7 extends BukkitLocalQueue<PlotBlock[]> {
private final ReflectionUtils.RefClass classBlock = getRefClass("{nms}.Block");
private final ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
private final ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
private final ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
private final ReflectionUtils.RefMethod methodGetHandle;
private final ReflectionUtils.RefMethod methodGetChunkAt;
private final ReflectionUtils.RefMethod methodA;
private final ReflectionUtils.RefMethod methodGetById;
private final ReflectionUtils.RefMethod methodInitLighting;
private final SendChunk sendChunk;
private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
public BukkitLocalQueue_1_7(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
super(world);
this.methodGetHandle = this.classCraftWorld.getMethod("getHandle");
this.methodGetChunkAt = this.classWorld.getMethod("getChunkAt", int.class, int.class);
this.methodA = this.classChunk.getMethod("a", int.class, int.class, int.class, this.classBlock, int.class);
this.methodGetById = this.classBlock.getMethod("getById", int.class);
this.methodInitLighting = this.classChunk.getMethod("initLighting");
this.sendChunk = new SendChunk();
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (BukkitLocalQueue_1_7.this.toUpdate.isEmpty()) {
return;
}
int count = 0;
ArrayList<Chunk> chunks = new ArrayList<>();
Iterator<Map.Entry<ChunkWrapper, Chunk>> i = BukkitLocalQueue_1_7.this.toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
MainUtil.initCache();
}
public void update(Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
this.sendChunk.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
@Override
public void fixChunkLighting(int x, int z) {
Object c = this.methodGetHandle.of(getChunk(x, z)).call();
this.methodInitLighting.of(c).call();
}
@Override
public void setBlocks(LocalChunk<PlotBlock[]> lc) {
Chunk chunk = getChunk(lc.getX(), lc.getZ());
chunk.load(true);
World world = chunk.getWorld();
ChunkWrapper wrapper = new ChunkWrapper(getWorld(), lc.getX(), lc.getZ());
if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, chunk);
}
Object w = this.methodGetHandle.of(world).call();
Object c = this.methodGetChunkAt.of(w).call(lc.getX(), lc.getZ());
for (int i = 0; i < lc.blocks.length; i++) {
PlotBlock[] result2 = lc.blocks[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
PlotBlock newBlock = result2[j];
if (newBlock.id == -1) {
chunk.getBlock(x, y, z).setData(newBlock.data, false);
continue;
}
Object block = this.methodGetById.call(newBlock.id);
this.methodA.of(c).call(x, y, z, block, newBlock.data);
}
}
fixChunkLighting(lc.getX(), lc.getZ());
}
@Override
public void refreshChunk(int x, int z) {
update(Arrays.asList(Bukkit.getWorld(getWorld()).getChunkAt(x, z)));
}
}

View File

@ -1,47 +1,44 @@
package com.plotsquared.bukkit.util.block; package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass; import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.SendChunk; import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
public class FastQueue_1_8 extends SlowQueue {
private final RefMethod methodInitLighting; import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
private final RefClass classBlock = getRefClass("{nms}.Block");
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); public class BukkitLocalQueue_1_8 extends BukkitLocalQueue<PlotBlock[]> {
private final RefClass classIBlockData = getRefClass("{nms}.IBlockData");
private final RefClass classChunk = getRefClass("{nms}.Chunk"); private final ReflectionUtils.RefMethod methodInitLighting;
private final RefClass classWorld = getRefClass("{nms}.World"); private final ReflectionUtils.RefClass classBlock = getRefClass("{nms}.Block");
private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); private final ReflectionUtils.RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
private final ReflectionUtils.RefClass classIBlockData = getRefClass("{nms}.IBlockData");
private final ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
private final ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
private final ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>(); private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
private final RefMethod methodGetHandle; private final ReflectionUtils.RefMethod methodGetHandle;
private final RefMethod methodGetChunkAt; private final ReflectionUtils.RefMethod methodGetChunkAt;
private final RefMethod methodA; private final ReflectionUtils.RefMethod methodA;
private final RefMethod methodGetByCombinedId; private final ReflectionUtils.RefMethod methodGetByCombinedId;
private final RefConstructor constructorBlockPosition; private final ReflectionUtils.RefConstructor constructorBlockPosition;
private final SendChunk sendChunk; private final SendChunk sendChunk;
public FastQueue_1_8() throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException { public BukkitLocalQueue_1_8(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
super(world);
this.methodInitLighting = this.classChunk.getMethod("initLighting"); this.methodInitLighting = this.classChunk.getMethod("initLighting");
this.constructorBlockPosition = this.classBlockPosition.getConstructor(int.class, int.class, int.class); this.constructorBlockPosition = this.classBlockPosition.getConstructor(int.class, int.class, int.class);
this.methodGetByCombinedId = this.classBlock.getMethod("getByCombinedId", int.class); this.methodGetByCombinedId = this.classBlock.getMethod("getByCombinedId", int.class);
@ -52,12 +49,12 @@ public class FastQueue_1_8 extends SlowQueue {
TaskManager.runTaskRepeat(new Runnable() { TaskManager.runTaskRepeat(new Runnable() {
@Override @Override
public void run() { public void run() {
if (FastQueue_1_8.this.toUpdate.isEmpty()) { if (BukkitLocalQueue_1_8.this.toUpdate.isEmpty()) {
return; return;
} }
int count = 0; int count = 0;
ArrayList<Chunk> chunks = new ArrayList<>(); ArrayList<Chunk> chunks = new ArrayList<>();
Iterator<Entry<ChunkWrapper, Chunk>> i = FastQueue_1_8.this.toUpdate.entrySet().iterator(); Iterator<Map.Entry<ChunkWrapper, Chunk>> i = BukkitLocalQueue_1_8.this.toUpdate.entrySet().iterator();
while (i.hasNext() && count < 128) { while (i.hasNext() && count < 128) {
chunks.add(i.next().getValue()); chunks.add(i.next().getValue());
i.remove(); i.remove();
@ -72,44 +69,25 @@ public class FastQueue_1_8 extends SlowQueue {
MainUtil.initCache(); MainUtil.initCache();
} }
public void update(Collection<Chunk> chunks) { @Override
if (chunks.isEmpty()) { public void fixChunkLighting(int x, int z) {
return; Object c = this.methodGetHandle.of(getChunk(x, z)).call();
} this.methodInitLighting.of(c).call();
if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
this.sendChunk.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
} }
/**
* This should be overridden by any specialized queues.
* @param plotChunk
*/
@Override @Override
public void execute(PlotChunk<Chunk> plotChunk) { public void setBlocks(LocalChunk<PlotBlock[]> lc) {
SlowChunk sc = (SlowChunk) plotChunk; Chunk chunk = getChunk(lc.getX(), lc.getZ());
Chunk chunk = plotChunk.getChunk(); chunk.load(true);
ChunkWrapper wrapper = plotChunk.getChunkWrapper(); World world = chunk.getWorld();
ChunkWrapper wrapper = new ChunkWrapper(getWorld(), lc.getX(), lc.getZ());
if (!this.toUpdate.containsKey(wrapper)) { if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, chunk); this.toUpdate.put(wrapper, chunk);
} }
chunk.load(true);
World world = chunk.getWorld();
Object w = this.methodGetHandle.of(world).call(); Object w = this.methodGetHandle.of(world).call();
Object c = this.methodGetChunkAt.of(w).call(wrapper.x, wrapper.z); Object c = this.methodGetChunkAt.of(w).call(lc.getX(), lc.getZ());
for (int i = 0; i < sc.result.length; i++) { for (int i = 0; i < lc.blocks.length; i++) {
PlotBlock[] result2 = sc.result[i]; PlotBlock[] result2 = lc.blocks[i];
if (result2 == null) { if (result2 == null) {
continue; continue;
} }
@ -329,55 +307,31 @@ public class FastQueue_1_8 extends SlowQueue {
this.methodA.of(chunk).call(pos, combined); this.methodA.of(chunk).call(pos, combined);
} }
} }
int[][] biomes = sc.biomes; fixChunkLighting(lc.getX(), lc.getZ());
Biome[] values = Biome.values(); }
if (biomes != null) {
for (int x = 0; x < 16; x++) { public void update(Collection<Chunk> chunks) {
int[] array = biomes[x]; if (chunks.isEmpty()) {
if (array == null) { return;
continue; }
} if (!MainUtil.canSendChunk) {
for (int z = 0; z < 16; z++) { for (Chunk chunk : chunks) {
int biome = array[z]; chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
if (biome == 0) { chunk.unload(true, false);
continue; chunk.load();
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
} }
return;
}
try {
this.sendChunk.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
} }
} }
/**
* This should be overridden by any specialized queues.
* @param wrap
*/
@Override @Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) { public void refreshChunk(int x, int z) {
return new SlowChunk(wrap); update(Arrays.asList(Bukkit.getWorld(getWorld()).getChunkAt(x, z)));
}
/**
* This should be overridden by any specialized queues.
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
Object c = this.methodGetHandle.of(chunk.getChunk()).call();
this.methodInitLighting.of(c).call();
return true;
}
/**
* This should be overridden by any specialized queues.
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
for (ChunkLoc loc : locations) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
this.toUpdate.remove(wrapper);
}
this.sendChunk.sendChunk(world, locations);
} }
} }

View File

@ -1,66 +1,62 @@
package com.plotsquared.bukkit.util.block; package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod.RefExecutor;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
import com.plotsquared.bukkit.util.SendChunk; import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
public class FastQueue_1_8_3 extends SlowQueue {
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
public class BukkitLocalQueue_1_8_3 extends BukkitLocalQueue<char[]> {
private final SendChunk sendChunk; private final SendChunk sendChunk;
private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>(); private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
private final RefMethod methodGetHandleChunk; private final ReflectionUtils.RefMethod methodGetHandleChunk;
private final RefMethod methodGetHandleWorld; private final ReflectionUtils.RefMethod methodGetHandleWorld;
private final RefMethod methodInitLighting; private final ReflectionUtils.RefMethod methodInitLighting;
private final RefConstructor classBlockPositionConstructor; private final ReflectionUtils.RefConstructor classBlockPositionConstructor;
private final RefConstructor classChunkSectionConstructor; private final ReflectionUtils.RefConstructor classChunkSectionConstructor;
private final RefMethod methodX; private final ReflectionUtils.RefMethod methodX;
private final RefMethod methodAreNeighborsLoaded; private final ReflectionUtils.RefMethod methodAreNeighborsLoaded;
private final RefField fieldSections; private final ReflectionUtils.RefField fieldSections;
private final RefField fieldWorld; private final ReflectionUtils.RefField fieldWorld;
private final RefMethod methodGetIdArray; private final ReflectionUtils.RefMethod methodGetIdArray;
private final RefMethod methodGetWorld; private final ReflectionUtils.RefMethod methodGetWorld;
private final RefField tileEntityListTick; private final ReflectionUtils.RefField tileEntityListTick;
public FastQueue_1_8_3() throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException { public BukkitLocalQueue_1_8_3(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); super(world);
RefClass classCraftWorld = getRefClass("{cb}.CraftWorld"); ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
RefClass classChunk = getRefClass("{nms}.Chunk"); ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
this.methodInitLighting = classChunk.getMethod("initLighting"); this.methodInitLighting = classChunk.getMethod("initLighting");
RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); ReflectionUtils.RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
this.classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class); this.classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class);
RefClass classWorld = getRefClass("{nms}.World"); ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
this.methodX = classWorld.getMethod("x", classBlockPosition.getRealClass()); this.methodX = classWorld.getMethod("x", classBlockPosition.getRealClass());
this.fieldSections = classChunk.getField("sections"); this.fieldSections = classChunk.getField("sections");
this.fieldWorld = classChunk.getField("world"); this.fieldWorld = classChunk.getField("world");
RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); ReflectionUtils.RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
this.methodGetIdArray = classChunkSection.getMethod("getIdArray"); this.methodGetIdArray = classChunkSection.getMethod("getIdArray");
this.methodAreNeighborsLoaded = classChunk.getMethod("areNeighborsLoaded", int.class); this.methodAreNeighborsLoaded = classChunk.getMethod("areNeighborsLoaded", int.class);
this.classChunkSectionConstructor = classChunkSection.getConstructor(int.class, boolean.class, char[].class); this.classChunkSectionConstructor = classChunkSection.getConstructor(int.class, boolean.class, char[].class);
@ -71,12 +67,12 @@ public class FastQueue_1_8_3 extends SlowQueue {
TaskManager.runTaskRepeat(new Runnable() { TaskManager.runTaskRepeat(new Runnable() {
@Override @Override
public void run() { public void run() {
if (FastQueue_1_8_3.this.toUpdate.isEmpty()) { if (BukkitLocalQueue_1_8_3.this.toUpdate.isEmpty()) {
return; return;
} }
int count = 0; int count = 0;
ArrayList<Chunk> chunks = new ArrayList<>(); ArrayList<Chunk> chunks = new ArrayList<>();
Iterator<Entry<ChunkWrapper, Chunk>> i = FastQueue_1_8_3.this.toUpdate.entrySet().iterator(); Iterator<Map.Entry<ChunkWrapper, Chunk>> i = BukkitLocalQueue_1_8_3.this.toUpdate.entrySet().iterator();
while (i.hasNext() && count < 128) { while (i.hasNext() && count < 128) {
chunks.add(i.next().getValue()); chunks.add(i.next().getValue());
i.remove(); i.remove();
@ -91,42 +87,184 @@ public class FastQueue_1_8_3 extends SlowQueue {
MainUtil.initCache(); MainUtil.initCache();
} }
public void update(Collection<Chunk> chunks) { @Override
if (chunks.isEmpty()) { public LocalChunk<char[]> getLocalChunk(int x, int z) {
return; return new CharLocalChunk_1_8_3(this, x, z);
}
public class CharLocalChunk_1_8_3 extends CharLocalChunk {
public short[] count;
public short[] air;
public short[] relight;
public CharLocalChunk_1_8_3(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
} }
if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) { @Override
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ()); public void setBlock(int x, int y, int z, int id, int data) {
chunk.unload(true, false); int i = MainUtil.CACHE_I[y][x][z];
chunk.load(); int j = MainUtil.CACHE_J[y][x][z];
char[] vs = this.blocks[i];
if (vs == null) {
vs = this.blocks[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
} }
return;
} }
try {
this.sendChunk.sendChunk(chunks); public char[] getIdArray(int i) {
} catch (Throwable e) { return this.blocks[i];
e.printStackTrace(); }
MainUtil.canSendChunk = false;
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
} }
} }
/**
* This should be overridden by any specialized queues.
* @param plotChunk
*/
@Override @Override
public void execute(PlotChunk<Chunk> plotChunk) { public void setBlocks(LocalChunk lc) {
FastChunk_1_8_3 fs = (FastChunk_1_8_3) plotChunk; CharLocalChunk_1_8_3 fs = (CharLocalChunk_1_8_3) lc;
Chunk chunk = plotChunk.getChunk(); Chunk chunk = getChunk(lc.getX(), lc.getZ());
chunk.load(true);
World world = chunk.getWorld(); World world = chunk.getWorld();
ChunkWrapper wrapper = plotChunk.getChunkWrapper(); ChunkWrapper wrapper = new ChunkWrapper(getWorld(), lc.getX(), lc.getZ());
if (!this.toUpdate.containsKey(wrapper)) { if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, chunk); this.toUpdate.put(wrapper, chunk);
} }
chunk.load(true);
try { try {
boolean flag = world.getEnvironment() == Environment.NORMAL; boolean flag = world.getEnvironment() == World.Environment.NORMAL;
// Sections // Sections
Method getHandle = chunk.getClass().getDeclaredMethod("getHandle"); Method getHandle = chunk.getClass().getDeclaredMethod("getHandle");
@ -147,10 +285,10 @@ public class FastQueue_1_8_3 extends SlowQueue {
// Trim tiles // Trim tiles
boolean removed = false; boolean removed = false;
Set<Entry<?, ?>> entrySet = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet(); Set<Map.Entry<?, ?>> entrySet = (Set<Map.Entry<?, ?>>) (Set<?>) tiles.entrySet();
Iterator<Entry<?, ?>> iterator = entrySet.iterator(); Iterator<Map.Entry<?, ?>> iterator = entrySet.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entry<?, ?> tile = iterator.next(); Map.Entry<?, ?> tile = iterator.next();
Object pos = tile.getKey(); Object pos = tile.getKey();
if (getX == null) { if (getX == null) {
Class<? extends Object> clazz2 = pos.getClass().getSuperclass(); Class<? extends Object> clazz2 = pos.getClass().getSuperclass();
@ -222,23 +360,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
} catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) { } catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) {
e.printStackTrace(); e.printStackTrace();
} }
int[][] biomes = fs.biomes; fixLighting(chunk, fs, true);
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
} }
public Object newChunkSection(int i, boolean flag, char[] ids) throws ReflectiveOperationException { public Object newChunkSection(int i, boolean flag, char[] ids) throws ReflectiveOperationException {
@ -249,24 +371,14 @@ public class FastQueue_1_8_3 extends SlowQueue {
return (char[]) this.methodGetIdArray.of(obj).call(); return (char[]) this.methodGetIdArray.of(obj).call();
} }
/**
* This should be overridden by any specialized queues.
* @param wrap
*/
@Override @Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) { public void fixChunkLighting(int x, int z) {
return new FastChunk_1_8_3(wrap); Object c = this.methodGetHandleChunk.of(getChunk(x, z)).call();
this.methodInitLighting.of(c).call();
} }
/** public boolean fixLighting(Chunk chunk, CharLocalChunk_1_8_3 bc, boolean fixAll) {
* This should be overridden by any specialized queues
* @param plotChunk
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> plotChunk, boolean fixAll) {
try { try {
FastChunk_1_8_3 bc = (FastChunk_1_8_3) plotChunk;
Chunk chunk = bc.getChunk();
if (!chunk.isLoaded()) { if (!chunk.isLoaded()) {
chunk.load(false); chunk.load(false);
} else { } else {
@ -279,7 +391,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) { if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) {
World world = chunk.getWorld(); World world = chunk.getWorld();
ChunkWrapper wrapper = bc.getChunkWrapper(); ChunkWrapper wrapper = new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ());
for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) { for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) {
for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) { for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
if (x != 0 && z != 0) { if (x != 0 && z != 0) {
@ -310,7 +422,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
int X = chunk.getX() << 4; int X = chunk.getX() << 4;
int Z = chunk.getZ() << 4; int Z = chunk.getZ() << 4;
RefExecutor relight = this.methodX.of(w); ReflectionUtils.RefMethod.RefExecutor relight = this.methodX.of(w);
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
Object section = sections[j]; Object section = sections[j];
if (section == null) { if (section == null) {
@ -398,17 +510,28 @@ public class FastQueue_1_8_3 extends SlowQueue {
return array[j] >> 4; return array[j] >> 4;
} }
/** public void update(Collection<Chunk> chunks) {
* This should be overridden by any specialized queues. if (chunks.isEmpty()) {
* @param world return;
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
for (ChunkLoc loc : locations) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
this.toUpdate.remove(wrapper);
} }
this.sendChunk.sendChunk(world, locations); if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
this.sendChunk.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
@Override
public void refreshChunk(int x, int z) {
update(Arrays.asList(Bukkit.getWorld(getWorld()).getChunkAt(x, z)));
} }
} }

View File

@ -1,73 +1,67 @@
package com.plotsquared.bukkit.util.block; package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass; import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefConstructor;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefField;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod.RefExecutor;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map.Entry; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
public class FastQueue_1_9 extends SlowQueue {
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
public class BukkitLocalQueue_1_9 extends BukkitLocalQueue<char[]> {
private final Object air; private final Object air;
// private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>(); // private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
private final RefMethod methodGetHandleChunk; private final ReflectionUtils.RefMethod methodGetHandleChunk;
private final RefMethod methodInitLighting; private final ReflectionUtils.RefMethod methodInitLighting;
private final RefConstructor classBlockPositionConstructor; private final ReflectionUtils.RefConstructor classBlockPositionConstructor;
private final RefConstructor classChunkSectionConstructor; private final ReflectionUtils.RefConstructor classChunkSectionConstructor;
private final RefMethod methodW; private final ReflectionUtils.RefMethod methodW;
private final RefMethod methodAreNeighborsLoaded; private final ReflectionUtils.RefMethod methodAreNeighborsLoaded;
private final RefField fieldSections; private final ReflectionUtils.RefField fieldSections;
private final RefField fieldWorld; private final ReflectionUtils.RefField fieldWorld;
private final RefMethod methodGetBlocks; private final ReflectionUtils.RefMethod methodGetBlocks;
private final RefMethod methodGetType; private final ReflectionUtils.RefMethod methodGetType;
private final RefMethod methodSetType; private final ReflectionUtils.RefMethod methodSetType;
private final RefMethod methodGetCombinedId; private final ReflectionUtils.RefMethod methodGetCombinedId;
private final RefMethod methodGetByCombinedId; private final ReflectionUtils.RefMethod methodGetByCombinedId;
private final RefMethod methodGetWorld; private final ReflectionUtils.RefMethod methodGetWorld;
private final RefField tileEntityListTick; private final ReflectionUtils.RefField tileEntityListTick;
public BukkitLocalQueue_1_9(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
public FastQueue_1_9() throws NoSuchFieldException, NoSuchMethodException, ClassNotFoundException { super(world);
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
RefClass classChunk = getRefClass("{nms}.Chunk"); ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
this.methodInitLighting = classChunk.getMethod("initLighting"); this.methodInitLighting = classChunk.getMethod("initLighting");
RefClass classBlockPosition = getRefClass("{nms}.BlockPosition"); ReflectionUtils.RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
this.classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class); this.classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class);
RefClass classWorld = getRefClass("{nms}.World"); ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
this.tileEntityListTick = classWorld.getField("tileEntityListTick"); this.tileEntityListTick = classWorld.getField("tileEntityListTick");
this.methodGetWorld = classChunk.getMethod("getWorld"); this.methodGetWorld = classChunk.getMethod("getWorld");
this.methodW = classWorld.getMethod("w", classBlockPosition.getRealClass()); this.methodW = classWorld.getMethod("w", classBlockPosition.getRealClass());
this.fieldSections = classChunk.getField("sections"); this.fieldSections = classChunk.getField("sections");
this.fieldWorld = classChunk.getField("world"); this.fieldWorld = classChunk.getField("world");
RefClass classBlock = getRefClass("{nms}.Block"); ReflectionUtils.RefClass classBlock = getRefClass("{nms}.Block");
RefClass classIBlockData = getRefClass("{nms}.IBlockData"); ReflectionUtils.RefClass classIBlockData = getRefClass("{nms}.IBlockData");
this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass()); this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
this.methodGetByCombinedId = classBlock.getMethod("getByCombinedId", int.class); this.methodGetByCombinedId = classBlock.getMethod("getByCombinedId", int.class);
RefClass classChunkSection = getRefClass("{nms}.ChunkSection"); ReflectionUtils.RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
this.methodGetBlocks = classChunkSection.getMethod("getBlocks"); this.methodGetBlocks = classChunkSection.getMethod("getBlocks");
this.methodGetType = classChunkSection.getMethod("getType", int.class, int.class, int.class); this.methodGetType = classChunkSection.getMethod("getType", int.class, int.class, int.class);
this.methodSetType = classChunkSection.getMethod("setType", int.class, int.class, int.class, classIBlockData.getRealClass()); this.methodSetType = classChunkSection.getMethod("setType", int.class, int.class, int.class, classIBlockData.getRealClass());
@ -77,19 +71,180 @@ public class FastQueue_1_9 extends SlowQueue {
MainUtil.initCache(); MainUtil.initCache();
} }
/**
* This should be overridden by any specialized queues.
* @param plotChunk
*/
@Override @Override
public void execute(PlotChunk<Chunk> plotChunk) { public LocalChunk<char[]> getLocalChunk(int x, int z) {
final FastChunk_1_9 fs = (FastChunk_1_9) plotChunk; return new CharLocalChunk_1_8_3(this, x, z);
Chunk chunk = plotChunk.getChunk(); }
World world = chunk.getWorld();
ChunkWrapper wrapper = plotChunk.getChunkWrapper(); public class CharLocalChunk_1_8_3 extends CharLocalChunk {
public short[] count;
public short[] air;
public short[] relight;
public CharLocalChunk_1_8_3(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
char[] vs = this.blocks[i];
if (vs == null) {
vs = this.blocks[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
}
}
public char[] getIdArray(int i) {
return this.blocks[i];
}
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
}
@Override
public void setBlocks(LocalChunk lc) {
CharLocalChunk_1_8_3 fs = (CharLocalChunk_1_8_3) lc;
Chunk chunk = getChunk(lc.getX(), lc.getZ());
chunk.load(true); chunk.load(true);
World world = chunk.getWorld();
try { try {
boolean flag = world.getEnvironment() == Environment.NORMAL; boolean flag = world.getEnvironment() == World.Environment.NORMAL;
// Sections // Sections
Method getHandle = chunk.getClass().getDeclaredMethod("getHandle"); Method getHandle = chunk.getClass().getDeclaredMethod("getHandle");
@ -109,10 +264,10 @@ public class FastQueue_1_9 extends SlowQueue {
Method zm = null; Method zm = null;
// Trim tiles // Trim tiles
boolean removed = false; boolean removed = false;
Set<Entry<?, ?>> entrySet = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet(); Set<Map.Entry<?, ?>> entrySet = (Set<Map.Entry<?, ?>>) (Set<?>) tiles.entrySet();
Iterator<Entry<?, ?>> iterator = entrySet.iterator(); Iterator<Map.Entry<?, ?>> iterator = entrySet.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entry<?, ?> tile = iterator.next(); Map.Entry<?, ?> tile = iterator.next();
Object pos = tile.getKey(); Object pos = tile.getKey();
if (xm == null) { if (xm == null) {
Class<?> clazz2 = pos.getClass().getSuperclass(); Class<?> clazz2 = pos.getClass().getSuperclass();
@ -125,7 +280,7 @@ public class FastQueue_1_9 extends SlowQueue {
int lz = (int) zm.invoke(pos) & 15; int lz = (int) zm.invoke(pos) & 15;
int j = MainUtil.CACHE_I[ly][lx][lz]; int j = MainUtil.CACHE_I[ly][lx][lz];
int k = MainUtil.CACHE_J[ly][lx][lz]; int k = MainUtil.CACHE_J[ly][lx][lz];
int[] array = fs.getIdArray(j); char[] array = fs.getIdArray(j);
if (array == null) { if (array == null) {
continue; continue;
} }
@ -150,32 +305,25 @@ public class FastQueue_1_9 extends SlowQueue {
if (fs.getCount(j) == 0) { if (fs.getCount(j) == 0) {
continue; continue;
} }
int[] newArray = fs.getIdArray(j); char[] newArray = fs.getIdArray(j);
if (newArray == null) { if (newArray == null) {
continue; continue;
} }
Object section = sections[j]; Object section = sections[j];
if (section == null || fs.getCount(j) >= 4096) { if (section == null || fs.getCount(j) >= 4096) {
char[] array = new char[4096]; section = sections[j] = newChunkSection(j << 4, flag, fs.getIdArray(j));
for (int i = 0; i < newArray.length; i++) {
int combined = newArray[i];
int id = combined & 4095;
int data = combined >> 12;
array[i] = (char) ((id << 4) + data);
}
section = sections[j] = newChunkSection(j << 4, flag, array);
continue; continue;
} }
Object currentArray = getBlocks(section); Object currentArray = getBlocks(section);
RefExecutor setType = this.methodSetType.of(section); ReflectionUtils.RefMethod.RefExecutor setType = this.methodSetType.of(section);
boolean fill = true; boolean fill = true;
for (int k = 0; k < newArray.length; k++) { for (int k = 0; k < newArray.length; k++) {
int n = newArray[k]; char n = newArray[k];
switch (n) { switch (n) {
case 0: case 0:
fill = false; fill = false;
continue; continue;
case -1: { case 1: {
fill = false; fill = false;
int x = MainUtil.x_loc[j][k]; int x = MainUtil.x_loc[j][k];
int y = MainUtil.y_loc[j][k]; int y = MainUtil.y_loc[j][k];
@ -187,7 +335,9 @@ public class FastQueue_1_9 extends SlowQueue {
int x = MainUtil.x_loc[j][k]; int x = MainUtil.x_loc[j][k];
int y = MainUtil.y_loc[j][k]; int y = MainUtil.y_loc[j][k];
int z = MainUtil.z_loc[j][k]; int z = MainUtil.z_loc[j][k];
Object iBlock = this.methodGetByCombinedId.call((int) n); int id = n >> 4;
int data = n & 15;
Object iBlock = this.methodGetByCombinedId.call((int) (id & 0xFFF) + (data << 12));
setType.call(x, y & 15, z, iBlock); setType.call(x, y & 15, z, iBlock);
} }
} }
@ -199,24 +349,8 @@ public class FastQueue_1_9 extends SlowQueue {
} catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) { } catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) {
e.printStackTrace(); e.printStackTrace();
} }
int[][] biomes = fs.biomes; fixLighting(chunk, fs, true);
Biome[] values = Biome.values(); refreshChunk(fs.getX(), fs.getZ());
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
world.refreshChunk(fs.getX(), fs.getZ());
} }
public Object newChunkSection(int i, boolean flag, char[] ids) throws ReflectiveOperationException { public Object newChunkSection(int i, boolean flag, char[] ids) throws ReflectiveOperationException {
@ -227,38 +361,27 @@ public class FastQueue_1_9 extends SlowQueue {
return this.methodGetBlocks.of(obj).call(); return this.methodGetBlocks.of(obj).call();
} }
/**
* This should be overridden by any specialized queues
* @param wrap
*/
@Override @Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) { public void fixChunkLighting(int x, int z) {
return new FastChunk_1_9(wrap); Object c = this.methodGetHandleChunk.of(getChunk(x, z)).call();
this.methodInitLighting.of(c).call();
} }
/** public boolean fixLighting(Chunk chunk, CharLocalChunk_1_8_3 bc, boolean fixAll) {
* This should be overridden by any specialized queues
* @param pc
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> pc, boolean fixAll) {
try { try {
FastChunk_1_9 bc = (FastChunk_1_9) pc;
Chunk chunk = bc.getChunk();
if (!chunk.isLoaded()) { if (!chunk.isLoaded()) {
chunk.load(false); chunk.load(false);
} else { } else {
chunk.unload(true, true); chunk.unload(true, false);
chunk.load(false); chunk.load(false);
} }
// Initialize lighting // Initialize lighting
Object c = this.methodGetHandleChunk.of(chunk).call(); Object c = this.methodGetHandleChunk.of(chunk).call();
ChunkWrapper wrapper = new ChunkWrapper(getWorld(), bc.getX(), bc.getZ());
if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) { if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) {
World world = chunk.getWorld(); World world = chunk.getWorld();
ChunkWrapper wrapper = bc.getChunkWrapper();
String worldName = wrapper.world;
for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) { for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) {
for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) { for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
if (x != 0 && z != 0) { if (x != 0 && z != 0) {
@ -266,7 +389,7 @@ public class FastQueue_1_9 extends SlowQueue {
while (!other.isLoaded()) { while (!other.isLoaded()) {
other.load(true); other.load(true);
} }
ChunkManager.manager.loadChunk(worldName, new ChunkLoc(x, z), true); ChunkManager.manager.loadChunk(getWorld(), new ChunkLoc(x, z), true);
} }
} }
} }
@ -284,7 +407,7 @@ public class FastQueue_1_9 extends SlowQueue {
int X = chunk.getX() << 4; int X = chunk.getX() << 4;
int Z = chunk.getZ() << 4; int Z = chunk.getZ() << 4;
RefExecutor relight = this.methodW.of(w); ReflectionUtils.RefMethod.RefExecutor relight = this.methodW.of(w);
for (int j = 0; j < sections.length; j++) { for (int j = 0; j < sections.length; j++) {
Object section = sections[j]; Object section = sections[j];
if (section == null) { if (section == null) {
@ -293,7 +416,7 @@ public class FastQueue_1_9 extends SlowQueue {
if (bc.getRelight(j) == 0 && !fixAll || bc.getCount(j) == 0 || bc.getCount(j) >= 4096 && bc.getAir(j) == 0) { if (bc.getRelight(j) == 0 && !fixAll || bc.getCount(j) == 0 || bc.getCount(j) >= 4096 && bc.getAir(j) == 0) {
continue; continue;
} }
int[] array = bc.getIdArray(j); char[] array = bc.getIdArray(j);
if (array != null) { if (array != null) {
int l = PseudoRandom.random.random(2); int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) { for (int k = 0; k < array.length; k++) {
@ -329,7 +452,7 @@ public class FastQueue_1_9 extends SlowQueue {
int x = MainUtil.x_loc[j][k]; int x = MainUtil.x_loc[j][k];
int y = MainUtil.y_loc[j][k]; int y = MainUtil.y_loc[j][k];
int z = MainUtil.z_loc[j][k]; int z = MainUtil.z_loc[j][k];
if (isSurrounded(bc.getIdArrays(), x, y, z)) { if (isSurrounded(bc.blocks, x, y, z)) {
continue; continue;
} }
Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z); Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
@ -345,7 +468,12 @@ public class FastQueue_1_9 extends SlowQueue {
return false; return false;
} }
public boolean isSurrounded(int[][] sections, int x, int y, int z) { @Override
public void refreshChunk(int x, int z) {
getBukkitWorld().refreshChunk(x, z);
}
public boolean isSurrounded(char[][] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z)) return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z)) && isSolid(getId(sections, x + 1, y - 1, z))
&& isSolid(getId(sections, x - 1, y, z)) && isSolid(getId(sections, x - 1, y, z))
@ -361,29 +489,15 @@ public class FastQueue_1_9 extends SlowQueue {
return false; return false;
} }
public int getId(int[][] sections, int x, int y, int z) { public int getId(char[] section, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1;
}
if (y < 0 || y > 255) {
return 1;
}
int i = MainUtil.CACHE_I[y][x][z];
int[] section = sections[i];
if (section == null) { if (section == null) {
return 0; return 0;
} }
int j = MainUtil.CACHE_J[y][x][z]; int j = MainUtil.CACHE_J[y][x][z];
return section[j]; return section[j] >> 4;
} }
public int getId(Object section, int x, int y, int z) { public int getId(char[][] sections, int x, int y, int z) {
int j = MainUtil.CACHE_J[y][x][z];
Object iBlock = this.methodGetType.of(section).call(x, y & 15, z);
return (int) this.methodGetCombinedId.call(iBlock);
}
public int getId(Object[] sections, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) { if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1; return 1;
} }
@ -391,23 +505,10 @@ public class FastQueue_1_9 extends SlowQueue {
return 1; return 1;
} }
int i = MainUtil.CACHE_I[y][x][z]; int i = MainUtil.CACHE_I[y][x][z];
Object section = sections[i]; char[] section = sections[i];
if (section == null) { if (section == null) {
return 0; return 0;
} }
return getId(section, x, y, z); return getId(section, x, y, z);
} }
/**
* This should be overridden by any specialized queues
* @param world
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
World worldObj = BukkitUtil.getWorld(world);
for (ChunkLoc loc : locations) {
worldObj.refreshChunk(loc.x, loc.z);
}
}
} }

View File

@ -1,247 +0,0 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import java.util.Arrays;
public class FastChunk_1_8_3 extends PlotChunk<Chunk> {
public char[][] ids;
public short[] count;
public short[] air;
public short[] relight;
public int[][] biomes;
public Chunk chunk;
public FastChunk_1_8_3(ChunkWrapper chunk) {
super(chunk);
this.ids = new char[16][];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return BukkitUtil.getWorld(loc.world).getChunkAt(loc.x, loc.z);
}
@Override
public Chunk getChunk() {
if (this.chunk == null) {
ChunkWrapper cl = getChunkWrapper();
this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
}
return this.chunk;
}
@Override
public void setChunkWrapper(ChunkWrapper loc) {
super.setChunkWrapper(loc);
this.chunk = null;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
/**
* Get the raw data for a section.
* @param i
* @return
*/
public char[] getIdArray(int i) {
return this.ids[i];
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
char[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
}
}
@Override
public PlotChunk clone() {
FastChunk_1_8_3 toReturn = new FastChunk_1_8_3(getChunkWrapper());
toReturn.air = this.air.clone();
toReturn.count = this.count.clone();
toReturn.relight = this.relight.clone();
toReturn.ids = new char[this.ids.length][];
for (int i = 0; i < this.ids.length; i++) {
char[] matrix = this.ids[i];
if (matrix != null) {
toReturn.ids[i] = new char[matrix.length];
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
FastChunk_1_8_3 toReturn = new FastChunk_1_8_3(getChunkWrapper());
toReturn.air = this.air;
toReturn.count = this.count;
toReturn.relight = this.relight;
toReturn.ids = this.ids;
return toReturn;
}
@Override
public void setBiome(int x, int z, int biome) {
if (this.biomes == null) {
this.biomes = new int[16][16];
}
this.biomes[x][z] = biome;
}
}

View File

@ -1,251 +0,0 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import java.util.Arrays;
public class FastChunk_1_9 extends PlotChunk<Chunk> {
public int[][] ids;
public short[] count;
public short[] air;
public short[] relight;
public int[][] biomes;
public Chunk chunk;
public FastChunk_1_9(ChunkWrapper chunk) {
super(chunk);
this.ids = new int[16][];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return BukkitUtil.getWorld(loc.world).getChunkAt(loc.x, loc.z);
}
@Override
public Chunk getChunk() {
if (this.chunk == null) {
ChunkWrapper cl = getChunkWrapper();
this.chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
}
return this.chunk;
}
@Override
public void setChunkWrapper(ChunkWrapper loc) {
super.setChunkWrapper(loc);
this.chunk = null;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
/**
* Get the raw data for a section.
* @param i
* @return
*/
public int[] getIdArray(int i) {
return this.ids[i];
}
public int[][] getIdArrays() {
return this.ids;
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
int[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new int[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = -1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = id;
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = id + (data << 12);
return;
}
}
@Override
public PlotChunk clone() {
FastChunk_1_9 toReturn = new FastChunk_1_9(getChunkWrapper());
toReturn.air = this.air.clone();
toReturn.count = this.count.clone();
toReturn.relight = this.relight.clone();
toReturn.ids = new int[this.ids.length][];
for (int i = 0; i < this.ids.length; i++) {
int[] matrix = this.ids[i];
if (matrix != null) {
toReturn.ids[i] = new int[matrix.length];
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
FastChunk_1_9 toReturn = new FastChunk_1_9(getChunkWrapper());
toReturn.air = this.air;
toReturn.count = this.count;
toReturn.relight = this.relight;
toReturn.ids = this.ids;
return toReturn;
}
@Override
public void setBiome(int x, int z, int biome) {
if (this.biomes == null) {
this.biomes = new int[16][16];
}
this.biomes[x][z] = biome;
}
}

View File

@ -1,179 +0,0 @@
package com.plotsquared.bukkit.util.block;
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefClass;
import com.intellectualcrafters.plot.util.ReflectionUtils.RefMethod;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.bukkit.util.SendChunk;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Biome;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
public class FastQueue_1_7 extends SlowQueue {
private final RefClass classBlock = getRefClass("{nms}.Block");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classWorld = getRefClass("{nms}.World");
private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
private final RefMethod methodGetHandle;
private final RefMethod methodGetChunkAt;
private final RefMethod methodA;
private final RefMethod methodGetById;
private final RefMethod methodInitLighting;
private final SendChunk sendChunk;
private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
public FastQueue_1_7() throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
this.methodGetHandle = this.classCraftWorld.getMethod("getHandle");
this.methodGetChunkAt = this.classWorld.getMethod("getChunkAt", int.class, int.class);
this.methodA = this.classChunk.getMethod("a", int.class, int.class, int.class, this.classBlock, int.class);
this.methodGetById = this.classBlock.getMethod("getById", int.class);
this.methodInitLighting = this.classChunk.getMethod("initLighting");
this.sendChunk = new SendChunk();
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (FastQueue_1_7.this.toUpdate.isEmpty()) {
return;
}
int count = 0;
ArrayList<Chunk> chunks = new ArrayList<>();
Iterator<Entry<ChunkWrapper, Chunk>> i = FastQueue_1_7.this.toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
MainUtil.initCache();
}
public void update(Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) {
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
chunk.unload(true, false);
chunk.load();
}
return;
}
try {
this.sendChunk.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
/**
* This should be overridden by any specialized queues
* @param plotChunk
*/
@Override
public void execute(PlotChunk<Chunk> plotChunk) {
SlowChunk sc = (SlowChunk) plotChunk;
Chunk chunk = plotChunk.getChunk();
ChunkWrapper wrapper = plotChunk.getChunkWrapper();
if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, chunk);
}
chunk.load(true);
World world = chunk.getWorld();
Object w = this.methodGetHandle.of(world).call();
Object c = this.methodGetChunkAt.of(w).call(wrapper.x, wrapper.z);
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
PlotBlock newBlock = result2[j];
if (newBlock.id == -1) {
chunk.getBlock(x, y, z).setData(newBlock.data, false);
continue;
}
Object block = this.methodGetById.call(newBlock.id);
this.methodA.of(c).call(x, y, z, block, newBlock.data);
}
}
int[][] biomes = sc.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
/**
* This should be overridden by any specialized queues
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overridden by any specialized queues
* @param chunk
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
Object c = this.methodGetHandle.of(chunk.getChunk()).call();
this.methodInitLighting.of(c).call();
return true;
}
/**
* This should be overridden by any specialized queues
* @param world
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
World worldObj = BukkitUtil.getWorld(world);
for (ChunkLoc loc : locations) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
this.toUpdate.remove(wrapper);
}
this.sendChunk.sendChunk(world, locations);
}
}

View File

@ -1,62 +1,109 @@
package com.plotsquared.bukkit.util.block; package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.generator.ChunkGenerator.BiomeGrid; import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData; import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.material.MaterialData;
public class GenChunk extends PlotChunk<Chunk> { public class GenChunk extends ScopedLocalBlockQueue {
public final Biome[] biomes; public final Biome[] biomes;
public Chunk chunk;
public short[][] result; public short[][] result;
public byte[][] result_data; public byte[][] result_data;
public ChunkData cd; public ChunkData cd;
public BiomeGrid grid; public BiomeGrid grid;
public Chunk chunk;
public String world;
public int cx;
public int cz;
public GenChunk(Chunk chunk, ChunkWrapper wrap) { public GenChunk(Chunk chunk, ChunkWrapper wrap) {
super(wrap); super(null, new Location(null, 0, 0, 0), new Location(null, 15, 255, 15));
if ((this.chunk = chunk) == null && wrap != null) { if ((this.chunk = chunk) == null && (wrap) != null) {
World world = BukkitUtil.getWorld(wrap.world); World world = BukkitUtil.getWorld(wrap.world);
if (world != null) { if (world != null) {
chunk = world.getChunkAt(wrap.x, wrap.z); this.chunk = world.getChunkAt(wrap.x, wrap.z);
} }
} }
this.biomes = Biome.values(); this.biomes = Biome.values();
} }
@Override public void setChunk(Chunk chunk) {
public Chunk getChunkAbs() { this.chunk = chunk;
ChunkWrapper wrap = getChunkWrapper(); }
if (this.chunk == null || wrap.x != this.chunk.getX() || wrap.z != this.chunk.getZ()) {
this.chunk = BukkitUtil.getWorld(wrap.world).getChunkAt(wrap.x, wrap.z); public void setChunk(ChunkWrapper wrap) {
chunk = null;
world = wrap.world;
cx = wrap.x;
cz = wrap.z;
}
public Chunk getChunk() {
if (chunk == null) {
World worldObj = BukkitUtil.getWorld(world);
if (worldObj != null) {
this.chunk = worldObj.getChunkAt(cx, cz);
}
} }
return this.chunk; return chunk;
}
public ChunkWrapper getChunkWrapper() {
if (chunk == null) {
return new ChunkWrapper(world, cx, cz);
}
return new ChunkWrapper(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
} }
@Override @Override
public void setBiome(int x, int z, int biome) { public void fillBiome(String biomeName) {
if (grid == null) {
return;
}
Biome biome = Biome.valueOf(biomeName.toUpperCase());
for (int x = 0; x <= 15; x++) {
for (int z = 0; z < 15; z++) {
this.grid.setBiome(x, z, biome);
}
}
}
@Override
public boolean setBiome(int x, int z, String biome) {
return setBiome(x, z, Biome.valueOf(biome.toUpperCase()));
}
public boolean setBiome(int x, int z, int biome) {
if (this.grid != null) { if (this.grid != null) {
this.grid.setBiome(x, z, this.biomes[biome]); this.grid.setBiome(x, z, this.biomes[biome]);
return true;
} }
return false;
} }
public void setBiome(int x, int z, Biome biome) { public boolean setBiome(int x, int z, Biome biome) {
if (this.grid != null) { if (this.grid != null) {
this.grid.setBiome(x, z, biome); this.grid.setBiome(x, z, biome);
return true;
} }
return false;
} }
@Override @Override
public void setBlock(int x, int y, int z, int id, byte data) { public boolean setBlock(int x, int y, int z, int id, int data) {
if (this.result == null) { if (this.result == null) {
this.cd.setBlock(x, y, z, id, data); this.cd.setBlock(x, y, z, id, (byte) data);
return; return true;
} }
int i = MainUtil.CACHE_I[y][x][z]; int i = MainUtil.CACHE_I[y][x][z];
short[] v = this.result[i]; short[] v = this.result[i];
@ -70,13 +117,61 @@ public class GenChunk extends PlotChunk<Chunk> {
if (vd == null) { if (vd == null) {
this.result_data[i] = vd = new byte[4096]; this.result_data[i] = vd = new byte[4096];
} }
vd[j] = data; vd[j] = (byte) data;
} }
return true;
} }
@Override @Override
public PlotChunk clone() { public PlotBlock getBlock(int x, int y, int z) {
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper()); int i = MainUtil.CACHE_I[y][x][z];
if (result == null) {
MaterialData md = cd.getTypeAndData(x, y, z);
return PlotBlock.get(md.getItemTypeId(), md.getData());
}
short[] array = result[i];
if (array == null) {
return PlotBlock.get(0, 0);
}
int j = MainUtil.CACHE_J[y][x][z];
short id = array[j];
if (id == 0) {
return PlotBlock.get(id, 0);
}
byte[] dataArray = result_data[i];
if (dataArray == null) {
return PlotBlock.get(id, 0);
}
return PlotBlock.get(id, dataArray[j]);
}
public int getX() {
return chunk == null ? cx : chunk.getX();
}
public int getZ() {
return chunk == null ? cz : chunk.getZ();
}
@Override
public String getWorld() {
return chunk == null ? world : chunk.getWorld().getName();
}
@Override
public Location getMax() {
return new Location(getWorld(), 15 + (getX() << 4), 255, 15 + (getZ() << 4));
}
@Override
public Location getMin() {
return new Location(getWorld(), getX() << 4, 0, getZ() << 4);
}
public GenChunk clone() {
GenChunk toReturn = new GenChunk(chunk, new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ()));
if (this.result != null) { if (this.result != null) {
for (int i = 0; i < this.result.length; i++) { for (int i = 0; i < this.result.length; i++) {
short[] matrix = this.result[i]; short[] matrix = this.result[i];
@ -97,9 +192,8 @@ public class GenChunk extends PlotChunk<Chunk> {
return toReturn; return toReturn;
} }
@Override public GenChunk shallowClone() {
public PlotChunk shallowClone() { GenChunk toReturn = new GenChunk(chunk, new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ()));
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper());
toReturn.result = this.result; toReturn.result = this.result;
toReturn.result_data = this.result_data; toReturn.result_data = this.result_data;
toReturn.cd = this.cd; toReturn.cd = this.cd;

View File

@ -1,60 +0,0 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk;
public class SlowChunk extends PlotChunk<Chunk> {
public PlotBlock[][] result = new PlotBlock[16][];
public int[][] biomes;
public SlowChunk(ChunkWrapper chunk) {
super(chunk);
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return BukkitUtil.getWorld(loc.world).getChunkAt(loc.x, loc.z);
}
@Override
public void setBiome(int x, int z, int biome) {
if (this.biomes == null) {
this.biomes = new int[16][16];
}
this.biomes[x][z] = biome;
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (this.result[y >> 4] == null) {
this.result[y >> 4] = new PlotBlock[4096];
}
this.result[MainUtil.CACHE_I[y][x][z]][MainUtil.CACHE_J[y][x][z]] = PlotBlock.get((short) id, data);
}
@Override
public PlotChunk clone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
for (int i = 0; i < this.result.length; i++) {
PlotBlock[] matrix = this.result[i];
if (matrix != null) {
toReturn.result[i] = new PlotBlock[matrix.length];
System.arraycopy(matrix, 0, toReturn.result[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
toReturn.result = this.result;
return toReturn;
}
}

View File

@ -1,287 +0,0 @@
package com.plotsquared.bukkit.util.block;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.bukkit.util.BukkitUtil;
import org.bukkit.Chunk;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
public class SlowQueue implements PlotQueue<Chunk> {
private final ConcurrentHashMap<ChunkWrapper, PlotChunk<Chunk>> blocks = new ConcurrentHashMap<>();
public SlowQueue() {
MainUtil.initCache();
}
@Override
public boolean setBlock(String world, int x, int y, int z, short id, byte data) {
if (y > 255 || y < 0) {
return false;
}
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
PlotChunk<Chunk> result = this.blocks.get(wrap);
if (result == null) {
result = getChunk(wrap);
result.setBlock(x, y, z, id, data);
PlotChunk<Chunk> previous = this.blocks.put(wrap, result);
if (previous == null) {
return true;
}
this.blocks.put(wrap, previous);
result = previous;
}
result.setBlock(x, y, z, id, data);
return true;
}
@Override
public void setChunk(PlotChunk<Chunk> chunk) {
this.blocks.put(chunk.getChunkWrapper(), chunk);
}
@Override
public PlotChunk<Chunk> next() {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (this.blocks.isEmpty()) {
return null;
}
Iterator<Entry<ChunkWrapper, PlotChunk<Chunk>>> iterator = this.blocks.entrySet().iterator();
PlotChunk<Chunk> toReturn = iterator.next().getValue();
if (SetQueue.IMP.isWaiting()) {
return null;
}
iterator.remove();
execute(toReturn);
fixLighting(toReturn, true);
return toReturn;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public PlotChunk<Chunk> next(ChunkWrapper wrap, boolean fixLighting) {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (this.blocks.isEmpty()) {
return null;
}
PlotChunk<Chunk> toReturn = this.blocks.remove(wrap);
if (toReturn == null) {
return null;
}
execute(toReturn);
fixLighting(toReturn, fixLighting);
return toReturn;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public void clear() {
this.blocks.clear();
}
@Override
public void regenerateChunk(String world, ChunkLoc loc) {
BukkitUtil.getWorld(world).regenerateChunk(loc.x, loc.z);
}
/**
* This should be overridden by any specialized queues.
* @param plotChunk
*/
public void execute(PlotChunk<Chunk> plotChunk) {
SlowChunk sc = (SlowChunk) plotChunk;
Chunk chunk = plotChunk.getChunk();
chunk.load(true);
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
Block block = chunk.getBlock(x, y, z);
PlotBlock newBlock = result2[j];
if (newBlock == null) {
continue;
}
switch (newBlock.id) {
case -1:
if (block.getData() == newBlock.data) {
continue;
}
block.setData(newBlock.data);
continue;
case 0:
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 25:
case 30:
case 32:
case 37:
case 39:
case 40:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 51:
case 52:
case 54:
case 55:
case 56:
case 57:
case 58:
case 60:
case 61:
case 62:
case 7:
case 8:
case 9:
case 10:
case 11:
case 73:
case 74:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 117:
case 121:
case 122:
case 123:
case 124:
case 129:
case 133:
case 138:
case 137:
case 140:
case 165:
case 166:
case 169:
case 170:
case 172:
case 173:
case 174:
case 176:
case 177:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
if (block.getTypeId() == newBlock.id) {
continue;
}
block.setTypeId(newBlock.id, false);
continue;
default:
if (block.getTypeId() == newBlock.id && block.getData() == newBlock.data) {
continue;
}
if (newBlock.data == 0) {
block.setTypeId(newBlock.id, false);
} else {
block.setTypeIdAndData(newBlock.id, newBlock.data, false);
}
continue;
}
}
}
int[][] biomes = sc.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
}
/**
* This should be overridden by any specialized queues.
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overridden by any specialized queues.
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
// Do nothing
return true;
}
/**
* This should be overridden by any specialized queues.
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
// Do nothing
}
}

View File

@ -11,13 +11,12 @@ import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.EconHandler; import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil; import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation; import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.QueueProvider;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@ -135,10 +134,10 @@ public interface IPlotMain extends ILogger {
EconHandler getEconomyHandler(); EconHandler getEconomyHandler();
/** /**
* Get the {@link PlotQueue} class. * Get the {@link com.intellectualcrafters.plot.util.block.QueueProvider} class.
* @return * @return
*/ */
PlotQueue initPlotQueue(); QueueProvider initBlockQueue();
/** /**
* Get the {@link WorldUtil} class. * Get the {@link WorldUtil} class.

View File

@ -39,18 +39,17 @@ import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.ReflectionUtils; import com.intellectualcrafters.plot.util.ReflectionUtils;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.area.QuadMap; import com.intellectualcrafters.plot.util.area.QuadMap;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.ExpireManager; import com.intellectualcrafters.plot.util.expiry.ExpireManager;
import com.intellectualcrafters.plot.util.expiry.ExpiryTask; import com.intellectualcrafters.plot.util.expiry.ExpiryTask;
import com.plotsquared.listener.WESubscriber; import com.plotsquared.listener.WESubscriber;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -112,7 +111,6 @@ public class PS {
public YamlConfiguration worlds; public YamlConfiguration worlds;
public YamlConfiguration storage; public YamlConfiguration storage;
public YamlConfiguration commands; public YamlConfiguration commands;
public TaskManager TASK;
public WorldEdit worldedit; public WorldEdit worldedit;
public URL update; public URL update;
private ILogger logger; private ILogger logger;
@ -153,7 +151,7 @@ public class PS {
if (getJavaVersion() < 1.8) { if (getJavaVersion() < 1.8) {
PS.log(C.CONSOLE_JAVA_OUTDATED_1_8); PS.log(C.CONSOLE_JAVA_OUTDATED_1_8);
} }
this.TASK = this.IMP.getTaskManager(); TaskManager.IMP = this.IMP.getTaskManager();
setupConfigs(); setupConfigs();
this.translationFile = this.translationFile =
MainUtil.getFile(this.IMP.getDirectory(), Settings.Paths.TRANSLATIONS + File.separator + "PlotSquared.use_THIS.yml"); MainUtil.getFile(this.IMP.getDirectory(), Settings.Paths.TRANSLATIONS + File.separator + "PlotSquared.use_THIS.yml");
@ -219,7 +217,8 @@ public class PS {
// World Util // World Util
WorldUtil.IMP = this.IMP.initWorldUtil(); WorldUtil.IMP = this.IMP.initWorldUtil();
// Set block // Set block
SetQueue.IMP.queue = this.IMP.initPlotQueue(); GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1);
GlobalBlockQueue.IMP.runTask();
// Set chunk // Set chunk
ChunkManager.manager = this.IMP.initChunkManager(); ChunkManager.manager = this.IMP.initChunkManager();
// Schematic handler // Schematic handler
@ -1802,7 +1801,7 @@ public class PS {
*/ */
public void disable() { public void disable() {
try { try {
this.TASK = null; TaskManager.IMP = null;
this.database = null; this.database = null;
// Validate that all data in the db is correct // Validate that all data in the db is correct
final HashSet<Plot> plots = new HashSet<>(); final HashSet<Plot> plots = new HashSet<>();

View File

@ -10,7 +10,7 @@ import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3; import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.plotsquared.general.commands.Command; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
@ -45,7 +45,7 @@ public class Clear extends Command {
@Override @Override
public void run() { public void run() {
plot.unlink(); plot.unlink();
SetQueue.IMP.addTask(new Runnable() { GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
plot.removeRunning(); plot.removeRunning();

View File

@ -27,18 +27,17 @@ import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.ExpireManager; import com.intellectualcrafters.plot.util.expiry.ExpireManager;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis; import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import com.plotsquared.general.commands.Command; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import com.plotsquared.listener.WEManager; import com.plotsquared.listener.WEManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -48,7 +47,6 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.script.Bindings; import javax.script.Bindings;
import javax.script.ScriptContext; import javax.script.ScriptContext;
import javax.script.ScriptEngine; import javax.script.ScriptEngine;
@ -119,12 +117,12 @@ public class DebugExec extends SubCommand {
// Instances // Instances
this.scope.put("PS", PS.get()); this.scope.put("PS", PS.get());
this.scope.put("SetQueue", SetQueue.IMP); this.scope.put("GlobalBlockQueue", GlobalBlockQueue.IMP);
this.scope.put("ExpireManager", ExpireManager.IMP); this.scope.put("ExpireManager", ExpireManager.IMP);
if (PS.get().worldedit != null) { if (PS.get().worldedit != null) {
this.scope.put("WEManager", new WEManager()); this.scope.put("WEManager", new WEManager());
} }
this.scope.put("TaskManager", PS.get().TASK); this.scope.put("TaskManager", TaskManager.IMP);
this.scope.put("TitleManager", AbstractTitle.TITLE_CLASS); this.scope.put("TitleManager", AbstractTitle.TITLE_CLASS);
this.scope.put("ConsolePlayer", ConsolePlayer.getConsole()); this.scope.put("ConsolePlayer", ConsolePlayer.getConsole());
this.scope.put("SchematicHandler", SchematicHandler.manager); this.scope.put("SchematicHandler", SchematicHandler.manager);

View File

@ -8,8 +8,7 @@ import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.object.RunnableVal2; import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.object.RunnableVal3; import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue;
import com.plotsquared.general.commands.Command; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.util.HashSet; import java.util.HashSet;
@ -28,12 +27,11 @@ public class Relight extends Command {
return; return;
} }
HashSet<RegionWrapper> regions = plot.getRegions(); HashSet<RegionWrapper> regions = plot.getRegions();
final LocalBlockQueue queue = plot.getArea().getQueue(false);
ChunkManager.chunkTask(plot, new RunnableVal<int[]>() { ChunkManager.chunkTask(plot, new RunnableVal<int[]>() {
@Override @Override
public void run(int[] value) { public void run(int[] value) {
SetQueue.ChunkWrapper cw = SetQueue.IMP.new ChunkWrapper(plot.getArea().worldname, value[0], value[1]); queue.fixChunkLighting(value[0], value[1]);
PlotChunk<?> pc = SetQueue.IMP.queue.getChunk(cw);
pc.fixLighting();
} }
}, new Runnable() { }, new Runnable() {
@Override @Override

View File

@ -12,10 +12,10 @@ import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.StringComparison; import com.intellectualcrafters.plot.util.StringComparison;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.plotsquared.general.commands.Command; import com.plotsquared.general.commands.Command;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
@ -114,7 +114,7 @@ public class Set extends SubCommand {
current.setComponent(component, blocks); current.setComponent(component, blocks);
} }
MainUtil.sendMessage(player, C.GENERATING_COMPONENT); MainUtil.sendMessage(player, C.GENERATING_COMPONENT);
SetQueue.IMP.addTask(new Runnable() { GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
plot.removeRunning(); plot.removeRunning();

View File

@ -13,12 +13,11 @@ import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.SetupObject; import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -156,7 +155,7 @@ public class Template extends SubCommand {
setup.step = new ConfigurationNode[0]; setup.step = new ConfigurationNode[0];
setup.world = world; setup.world = world;
SetupUtils.manager.setupWorld(setup); SetupUtils.manager.setupWorld(setup);
SetQueue.IMP.addTask(new Runnable() { GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
MainUtil.sendMessage(player, "Done!"); MainUtil.sendMessage(player, "Done!");

View File

@ -13,6 +13,8 @@ import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.plotsquared.general.commands.CommandDeclaration; import com.plotsquared.general.commands.CommandDeclaration;
import java.io.File; import java.io.File;
@ -189,10 +191,11 @@ public class Trim extends SubCommand {
} }
} }
} }
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
TaskManager.objectTask(chunks, new RunnableVal<ChunkLoc>() { TaskManager.objectTask(chunks, new RunnableVal<ChunkLoc>() {
@Override @Override
public void run(ChunkLoc value) { public void run(ChunkLoc value) {
ChunkManager.manager.regenerateChunk(world, value); queue.regenChunk(value.x, value.z);
} }
}, this); }, this);
} }

View File

@ -1,16 +1,16 @@
package com.intellectualcrafters.plot.generator; package com.intellectualcrafters.plot.generator;
import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.LazyResult; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.block.DelegateLocalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper; import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import java.util.Set; import java.util.Set;
public class AugmentedUtils { public class AugmentedUtils {
@ -23,18 +23,10 @@ public class AugmentedUtils {
enabled = true; enabled = true;
} }
public static boolean generate(final String world, final int cx, final int cz, LazyResult<PlotChunk<?>> lazyChunk) { public static boolean generate(final String world, final int cx, final int cz, LocalBlockQueue queue) {
if (!enabled) { if (!enabled) {
return false; return false;
} }
if (lazyChunk == null) {
lazyChunk = new LazyResult<PlotChunk<?>>() {
@Override
public PlotChunk<?> create() {
return SetQueue.IMP.queue.getChunk(SetQueue.IMP.new ChunkWrapper(world, cx, cz));
}
};
}
final int bx = cx << 4; final int bx = cx << 4;
final int bz = cz << 4; final int bz = cz << 4;
RegionWrapper region = new RegionWrapper(bx, bx + 15, bz, bz + 15); RegionWrapper region = new RegionWrapper(bx, bx + 15, bz, bz + 15);
@ -44,7 +36,6 @@ public class AugmentedUtils {
} }
PseudoRandom r = new PseudoRandom(); PseudoRandom r = new PseudoRandom();
r.state = (cx << 16) | (cz & 0xFFFF); r.state = (cx << 16) | (cz & 0xFFFF);
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, cx, cz);
boolean toReturn = false; boolean toReturn = false;
for (final PlotArea area : areas) { for (final PlotArea area : areas) {
if (area.TYPE == 0) { if (area.TYPE == 0) {
@ -57,8 +48,11 @@ public class AugmentedUtils {
if (generator == null) { if (generator == null) {
continue; continue;
} }
final PlotChunk<?> result = lazyChunk.getOrCreate(); // Mask
final PlotChunk<?> primaryMask; if (queue == null) {
queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
}
LocalBlockQueue primaryMask;
// coords // coords
int bxx; int bxx;
int bzz; int bzz;
@ -70,42 +64,29 @@ public class AugmentedUtils {
bzz = Math.max(0, area.getRegion().minZ - bz); bzz = Math.max(0, area.getRegion().minZ - bz);
txx = Math.min(15, area.getRegion().maxX - bx); txx = Math.min(15, area.getRegion().maxX - bx);
tzz = Math.min(15, area.getRegion().maxZ - bz); tzz = Math.min(15, area.getRegion().maxZ - bz);
primaryMask = new PlotChunk<Object>(wrap) { primaryMask = new DelegateLocalBlockQueue(queue) {
@Override @Override
public Object getChunkAbs() { public boolean setBlock(int x, int y, int z, int id, int data) {
return null; if (area.contains(x, z)) {
} return super.setBlock(x, y, z, id, data);
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (area.contains(bx + x, bz + z)) {
result.setBlock(x, y, z, id, data);
} }
return false;
} }
@Override @Override
public void setBiome(int x, int z, int biome) { public boolean setBiome(int x, int z, String biome) {
if (area.contains(bx + x, bz + z)) { if (area.contains(x, z)) {
result.setBiome(x, z, biome); return super.setBiome(x, z, biome);
} }
} return false;
@Override
public PlotChunk clone() {
return null;
}
@Override
public PlotChunk shallowClone() {
return null;
} }
}; };
} else { } else {
bxx = bzz = 0; bxx = bzz = 0;
txx = tzz = 15; txx = tzz = 15;
primaryMask = result; primaryMask = queue;
} }
PlotChunk<?> secondaryMask; LocalBlockQueue secondaryMask;
PlotBlock air = PlotBlock.get((short) 0, (byte) 0); PlotBlock air = PlotBlock.get((short) 0, (byte) 0);
if (area.TERRAIN == 2) { if (area.TERRAIN == 2) {
PlotManager manager = area.getPlotManager(); PlotManager manager = area.getPlotManager();
@ -118,7 +99,7 @@ public class AugmentedUtils {
boolean can = manager.getPlotId(area, rx, 0, rz) == null; boolean can = manager.getPlotId(area, rx, 0, rz) == null;
if (can) { if (can) {
for (int y = 1; y < 128; y++) { for (int y = 1; y < 128; y++) {
result.setBlock(x, y, z, air); queue.setBlock(x, y, z, air);
} }
canPlace[x][z] = can; canPlace[x][z] = can;
has = true; has = true;
@ -129,30 +110,18 @@ public class AugmentedUtils {
continue; continue;
} }
toReturn = true; toReturn = true;
secondaryMask = new PlotChunk<Object>(wrap) { secondaryMask = new DelegateLocalBlockQueue(primaryMask) {
@Override @Override
public Object getChunkAbs() { public boolean setBlock(int x, int y, int z, int id, int data) {
return null;
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (canPlace[x][z]) { if (canPlace[x][z]) {
primaryMask.setBlock(x, y, z, id, data); return super.setBlock(x, y, z, id, data);
} }
return false;
} }
@Override @Override
public void setBiome(int x, int z, int biome) {} public boolean setBiome(int x, int y, String biome) {
return super.setBiome(x, y, biome);
@Override
public PlotChunk clone() {
return null;
}
@Override
public PlotChunk shallowClone() {
return null;
} }
}; };
} else { } else {
@ -160,19 +129,17 @@ public class AugmentedUtils {
for (int x = bxx; x <= txx; x++) { for (int x = bxx; x <= txx; x++) {
for (int z = bzz; z <= tzz; z++) { for (int z = bzz; z <= tzz; z++) {
for (int y = 1; y < 128; y++) { for (int y = 1; y < 128; y++) {
result.setBlock(x, y, z, air); queue.setBlock(x, y, z, air);
} }
} }
} }
toReturn = true; toReturn = true;
} }
generator.generateChunk(secondaryMask, area, r); ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, new Location(area.worldname, bx, 0, bz), new Location(area.worldname, bx + 15, 255, bz + 15));
generator.populateChunk(secondaryMask, area, r); generator.generateChunk(scoped, area, r);
} generator.populateChunk(scoped, area, r);
if (lazyChunk.get() != null) {
lazyChunk.get().addToQueue();
lazyChunk.get().flush(false);
} }
queue.flush();
return toReturn; return toReturn;
} }
} }

View File

@ -7,9 +7,8 @@ import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import java.util.ArrayList; import java.util.ArrayList;
/** /**
@ -55,20 +54,22 @@ public class ClassicPlotManager extends SquarePlotManager {
if (dpw.WALL_BLOCK.id != 0 || !dpw.WALL_BLOCK.equals(dpw.CLAIMED_WALL_BLOCK)) { if (dpw.WALL_BLOCK.id != 0 || !dpw.WALL_BLOCK.equals(dpw.CLAIMED_WALL_BLOCK)) {
setWall(dpw, plot.getId(), new PlotBlock[]{dpw.WALL_BLOCK}); setWall(dpw, plot.getId(), new PlotBlock[]{dpw.WALL_BLOCK});
} }
SetQueue.IMP.addTask(whenDone); GlobalBlockQueue.IMP.addTask(whenDone);
return true; return true;
} }
public boolean setFloor(PlotArea plotArea, PlotId plotId, PlotBlock[] blocks) { public boolean setFloor(PlotArea plotArea, PlotId plotId, PlotBlock[] blocks) {
Plot plot = plotArea.getPlotAbs(plotId); Plot plot = plotArea.getPlotAbs(plotId);
LocalBlockQueue queue = plotArea.getQueue(false);
if (plot.isBasePlot()) { if (plot.isBasePlot()) {
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea; ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
for (RegionWrapper region : plot.getRegions()) { for (RegionWrapper region : plot.getRegions()) {
Location pos1 = new Location(plotArea.worldname, region.minX, dpw.PLOT_HEIGHT, region.minZ); Location pos1 = new Location(plotArea.worldname, region.minX, dpw.PLOT_HEIGHT, region.minZ);
Location pos2 = new Location(plotArea.worldname, region.maxX, dpw.PLOT_HEIGHT, region.maxZ); Location pos2 = new Location(plotArea.worldname, region.maxX, dpw.PLOT_HEIGHT, region.maxZ);
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks); queue.setCuboid(pos1, pos2, blocks);
} }
} }
queue.enqueue();
return true; return true;
} }
@ -77,11 +78,13 @@ public class ClassicPlotManager extends SquarePlotManager {
if (!plot.isBasePlot()) { if (!plot.isBasePlot()) {
return false; return false;
} }
LocalBlockQueue queue = plotArea.getQueue(false);
for (RegionWrapper region : plot.getRegions()) { for (RegionWrapper region : plot.getRegions()) {
Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ); Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ);
Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ);
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks); queue.setCuboid(pos1, pos2, blocks);
} }
queue.enqueue();
return true; return true;
} }
@ -91,11 +94,13 @@ public class ClassicPlotManager extends SquarePlotManager {
return false; return false;
} }
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea; ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
LocalBlockQueue queue = plotArea.getQueue(false);
for (RegionWrapper region : plot.getRegions()) { for (RegionWrapper region : plot.getRegions()) {
Location pos1 = new Location(plotArea.worldname, region.minX, dpw.PLOT_HEIGHT + 1, region.minZ); Location pos1 = new Location(plotArea.worldname, region.minX, dpw.PLOT_HEIGHT + 1, region.minZ);
Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ);
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks); queue.setCuboid(pos1, pos2, blocks);
} }
queue.enqueue();
return true; return true;
} }
@ -105,11 +110,13 @@ public class ClassicPlotManager extends SquarePlotManager {
return false; return false;
} }
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea; ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
LocalBlockQueue queue = plotArea.getQueue(false);
for (RegionWrapper region : plot.getRegions()) { for (RegionWrapper region : plot.getRegions()) {
Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ); Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ);
Location pos2 = new Location(plotArea.worldname, region.maxX, dpw.PLOT_HEIGHT - 1, region.maxZ); Location pos2 = new Location(plotArea.worldname, region.maxX, dpw.PLOT_HEIGHT - 1, region.maxZ);
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks); queue.setCuboid(pos1, pos2, blocks);
} }
queue.enqueue();
return true; return true;
} }
@ -120,8 +127,10 @@ public class ClassicPlotManager extends SquarePlotManager {
} }
Location[] corners = plot.getCorners(); Location[] corners = plot.getCorners();
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea; ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
SetQueue.IMP.setBlock(plotArea.worldname, (corners[0].getX() + corners[1].getX()) / 2, dpw.PLOT_HEIGHT, LocalBlockQueue queue = plotArea.getQueue(false);
queue.setBlock((corners[0].getX() + corners[1].getX()) / 2, dpw.PLOT_HEIGHT,
(corners[0].getZ() + corners[1].getZ()) / 2, blocks[0]); (corners[0].getZ() + corners[1].getZ()) / 2, blocks[0]);
queue.enqueue();
return true; return true;
} }
@ -134,11 +143,12 @@ public class ClassicPlotManager extends SquarePlotManager {
Location bottom = plot.getBottomAbs(); Location bottom = plot.getBottomAbs();
Location top = plot.getExtendedTopAbs(); Location top = plot.getExtendedTopAbs();
PseudoRandom random = new PseudoRandom(); PseudoRandom random = new PseudoRandom();
LocalBlockQueue queue = plotArea.getQueue(false);
if (!plot.getMerged(0)) { if (!plot.getMerged(0)) {
int z = bottom.getZ(); int z = bottom.getZ();
for (int x = bottom.getX(); x <= top.getX(); x++) { for (int x = bottom.getX(); x <= top.getX(); x++) {
for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -146,7 +156,7 @@ public class ClassicPlotManager extends SquarePlotManager {
int x = bottom.getX(); int x = bottom.getX();
for (int z = bottom.getZ(); z <= top.getZ(); z++) { for (int z = bottom.getZ(); z <= top.getZ(); z++) {
for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -155,7 +165,7 @@ public class ClassicPlotManager extends SquarePlotManager {
int z = top.getZ(); int z = top.getZ();
for (int x = bottom.getX(); x <= top.getX(); x++) { for (int x = bottom.getX(); x <= top.getX(); x++) {
for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -163,7 +173,7 @@ public class ClassicPlotManager extends SquarePlotManager {
int x = top.getX(); int x = top.getX();
for (int z = bottom.getZ(); z <= top.getZ(); z++) { for (int z = bottom.getZ(); z <= top.getZ(); z++) {
for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) { for (int y = dpw.PLOT_HEIGHT; y <= 255; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -171,9 +181,10 @@ public class ClassicPlotManager extends SquarePlotManager {
for (RegionWrapper region : plot.getRegions()) { for (RegionWrapper region : plot.getRegions()) {
Location pos1 = new Location(plotArea.worldname, region.minX, 255, region.minZ); Location pos1 = new Location(plotArea.worldname, region.minX, 255, region.minZ);
Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ); Location pos2 = new Location(plotArea.worldname, region.maxX, 255, region.maxZ);
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks); queue.setCuboid(pos1, pos2, blocks);
} }
} }
queue.enqueue();
return true; return true;
} }
@ -186,11 +197,12 @@ public class ClassicPlotManager extends SquarePlotManager {
Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(3) ? 0 : 1, 0, plot.getMerged(0) ? 0 : 1); Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(3) ? 0 : 1, 0, plot.getMerged(0) ? 0 : 1);
Location top = plot.getExtendedTopAbs().add(1, 0, 1); Location top = plot.getExtendedTopAbs().add(1, 0, 1);
PseudoRandom random = new PseudoRandom(); PseudoRandom random = new PseudoRandom();
LocalBlockQueue queue = plotArea.getQueue(false);
if (!plot.getMerged(0)) { if (!plot.getMerged(0)) {
int z = bot.getZ(); int z = bot.getZ();
for (int x = bot.getX(); x < top.getX(); x++) { for (int x = bot.getX(); x < top.getX(); x++) {
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) { for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -198,7 +210,7 @@ public class ClassicPlotManager extends SquarePlotManager {
int x = bot.getX(); int x = bot.getX();
for (int z = bot.getZ(); z < top.getZ(); z++) { for (int z = bot.getZ(); z < top.getZ(); z++) {
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) { for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -206,7 +218,7 @@ public class ClassicPlotManager extends SquarePlotManager {
int z = top.getZ(); int z = top.getZ();
for (int x = bot.getX(); x < top.getX() + (plot.getMerged(1) ? 0 : 1); x++) { for (int x = bot.getX(); x < top.getX() + (plot.getMerged(1) ? 0 : 1); x++) {
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) { for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
@ -214,10 +226,11 @@ public class ClassicPlotManager extends SquarePlotManager {
int x = top.getX(); int x = top.getX();
for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(2) ? 0 : 1); z++) { for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(2) ? 0 : 1); z++) {
for (int y = 1; y <= dpw.WALL_HEIGHT; y++) { for (int y = 1; y <= dpw.WALL_HEIGHT; y++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
} }
queue.enqueue();
return true; return true;
} }
@ -230,31 +243,33 @@ public class ClassicPlotManager extends SquarePlotManager {
Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(3) ? 0 : 1, 0, plot.getMerged(0) ? 0 : 1); Location bot = plot.getExtendedBottomAbs().subtract(plot.getMerged(3) ? 0 : 1, 0, plot.getMerged(0) ? 0 : 1);
Location top = plot.getExtendedTopAbs().add(1, 0, 1); Location top = plot.getExtendedTopAbs().add(1, 0, 1);
PseudoRandom random = new PseudoRandom(); PseudoRandom random = new PseudoRandom();
LocalBlockQueue queue = plotArea.getQueue(false);
int y = dpw.WALL_HEIGHT + 1; int y = dpw.WALL_HEIGHT + 1;
if (!plot.getMerged(0)) { if (!plot.getMerged(0)) {
int z = bot.getZ(); int z = bot.getZ();
for (int x = bot.getX(); x < top.getX(); x++) { for (int x = bot.getX(); x < top.getX(); x++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
if (!plot.getMerged(3)) { if (!plot.getMerged(3)) {
int x = bot.getX(); int x = bot.getX();
for (int z = bot.getZ(); z < top.getZ(); z++) { for (int z = bot.getZ(); z < top.getZ(); z++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
if (!plot.getMerged(2)) { if (!plot.getMerged(2)) {
int z = top.getZ(); int z = top.getZ();
for (int x = bot.getX(); x < top.getX() + (plot.getMerged(1) ? 0 : 1); x++) { for (int x = bot.getX(); x < top.getX() + (plot.getMerged(1) ? 0 : 1); x++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
if (!plot.getMerged(1)) { if (!plot.getMerged(1)) {
int x = top.getX(); int x = top.getX();
for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(2) ? 0 : 1); z++) { for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(2) ? 0 : 1); z++) {
SetQueue.IMP.setBlock(plotArea.worldname, x, y, z, blocks[random.random(blocks.length)]); queue.setBlock(x, y, z, blocks[random.random(blocks.length)]);
} }
} }
queue.enqueue();
return true; return true;
} }
@ -270,24 +285,26 @@ public class ClassicPlotManager extends SquarePlotManager {
int ex = sx + dpw.ROAD_WIDTH - 1; int ex = sx + dpw.ROAD_WIDTH - 1;
int sz = pos1.getZ() - 2; int sz = pos1.getZ() - 2;
int ez = pos2.getZ() + 2; int ez = pos2.getZ() + 2;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(
new Location(plotArea.worldname, sx, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz + 1), new Location(plotArea.worldname, sx, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz + 1),
new Location(plotArea.worldname, ex, 255, ez - 1), PlotBlock.get((short) 0, (byte) 0)); new Location(plotArea.worldname, ex, 255, ez - 1), PlotBlock.get((short) 0, (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, 0, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx, 0, sz + 1),
new Location(plotArea.worldname, ex, 0, ez - 1), PlotBlock.get((short) 7, new Location(plotArea.worldname, ex, 0, ez - 1), PlotBlock.get((short) 7,
(byte) 0)); (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx, 1, sz + 1),
new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT, ez - 1), dpw.WALL_FILLING); new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT, ez - 1), dpw.WALL_FILLING);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT + 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT + 1, sz + 1),
new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT + 1, ez - 1), new Location(plotArea.worldname, sx, dpw.WALL_HEIGHT + 1, ez - 1),
dpw.WALL_BLOCK); dpw.WALL_BLOCK);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, ex, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, ex, 1, sz + 1),
new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT, ez - 1), dpw.WALL_FILLING); new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT, ez - 1), dpw.WALL_FILLING);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT + 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT + 1, sz + 1),
new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT + 1, ez - 1), new Location(plotArea.worldname, ex, dpw.WALL_HEIGHT + 1, ez - 1),
dpw.WALL_BLOCK); dpw.WALL_BLOCK);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz + 1),
new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK); new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK);
queue.enqueue();
return true; return true;
} }
@ -300,23 +317,25 @@ public class ClassicPlotManager extends SquarePlotManager {
int ez = sz + dpw.ROAD_WIDTH - 1; int ez = sz + dpw.ROAD_WIDTH - 1;
int sx = pos1.getX() - 2; int sx = pos1.getX() - 2;
int ex = pos2.getX() + 2; int ex = pos2.getX() + 2;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(
new Location(plotArea.worldname, sx + 1, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), new Location(plotArea.worldname, sx + 1, Math.min(dpw.WALL_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz),
new Location(plotArea.worldname, ex - 1, 255, ez), PlotBlock.get((short) 0, (byte) 0)); new Location(plotArea.worldname, ex - 1, 255, ez), PlotBlock.get((short) 0, (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 0, sz), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 0, sz),
new Location(plotArea.worldname, ex - 1, 0, ez), PlotBlock.get((short) 7, (byte) 0)); new Location(plotArea.worldname, ex - 1, 0, ez), PlotBlock.get((short) 7, (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, sz), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz),
new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT, sz), dpw.WALL_FILLING); new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT, sz), dpw.WALL_FILLING);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, dpw.WALL_HEIGHT + 1, sz), queue.setCuboid(new Location(plotArea.worldname, sx + 1, dpw.WALL_HEIGHT + 1, sz),
new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT + 1, sz), new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT + 1, sz),
dpw.WALL_BLOCK); dpw.WALL_BLOCK);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, ez), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, ez),
new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT, ez), dpw.WALL_FILLING); new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT, ez), dpw.WALL_FILLING);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, dpw.WALL_HEIGHT + 1, ez), queue.setCuboid(new Location(plotArea.worldname, sx + 1, dpw.WALL_HEIGHT + 1, ez),
new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT + 1, ez), new Location(plotArea.worldname, ex - 1, dpw.WALL_HEIGHT + 1, ez),
dpw.WALL_BLOCK); dpw.WALL_BLOCK);
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz + 1),
new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK); new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK);
queue.enqueue();
return true; return true;
} }
@ -328,13 +347,15 @@ public class ClassicPlotManager extends SquarePlotManager {
int ex = sx + dpw.ROAD_WIDTH - 1; int ex = sx + dpw.ROAD_WIDTH - 1;
int sz = pos2.getZ() + 1; int sz = pos2.getZ() + 1;
int ez = sz + dpw.ROAD_WIDTH - 1; int ez = sz + dpw.ROAD_WIDTH - 1;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, dpw.ROAD_HEIGHT + 1, sz + 1), LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(new Location(plotArea.worldname, sx + 1, dpw.ROAD_HEIGHT + 1, sz + 1),
new Location(plotArea.worldname, ex - 1, 255, ez - 1), PlotBlock.get( new Location(plotArea.worldname, ex - 1, 255, ez - 1), PlotBlock.get(
(short) 0, (byte) 0)); (short) 0, (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 0, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 0, sz + 1),
new Location(plotArea.worldname, ex - 1, 0, ez - 1), PlotBlock.get((short) 7, (byte) 0)); new Location(plotArea.worldname, ex - 1, 0, ez - 1), PlotBlock.get((short) 7, (byte) 0));
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz + 1),
new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK); new Location(plotArea.worldname, ex - 1, dpw.ROAD_HEIGHT, ez - 1), dpw.ROAD_BLOCK);
queue.enqueue();
return true; return true;
} }
@ -347,12 +368,14 @@ public class ClassicPlotManager extends SquarePlotManager {
int ex = sx + dpw.ROAD_WIDTH - 1; int ex = sx + dpw.ROAD_WIDTH - 1;
int sz = pos1.getZ() - 1; int sz = pos1.getZ() - 1;
int ez = pos2.getZ() + 1; int ez = pos2.getZ() + 1;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz),
new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0)); new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0));
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, 1, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx, 1, sz + 1),
new Location(plotArea.worldname, ex, dpw.PLOT_HEIGHT - 1, ez - 1), dpw.MAIN_BLOCK); new Location(plotArea.worldname, ex, dpw.PLOT_HEIGHT - 1, ez - 1), dpw.MAIN_BLOCK);
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, dpw.PLOT_HEIGHT, sz + 1), queue.setCuboid(new Location(plotArea.worldname, sx, dpw.PLOT_HEIGHT, sz + 1),
new Location(plotArea.worldname, ex, dpw.PLOT_HEIGHT, ez - 1), dpw.TOP_BLOCK); new Location(plotArea.worldname, ex, dpw.PLOT_HEIGHT, ez - 1), dpw.TOP_BLOCK);
queue.enqueue();
return true; return true;
} }
@ -365,12 +388,14 @@ public class ClassicPlotManager extends SquarePlotManager {
int ez = sz + dpw.ROAD_WIDTH - 1; int ez = sz + dpw.ROAD_WIDTH - 1;
int sx = pos1.getX() - 1; int sx = pos1.getX() - 1;
int ex = pos2.getX() + 1; int ex = pos2.getX() + 1;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz), LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(new Location(plotArea.worldname, sx, Math.min(dpw.PLOT_HEIGHT, dpw.ROAD_HEIGHT) + 1, sz),
new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0)); new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0));
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, 1, sz), queue.setCuboid(new Location(plotArea.worldname, sx + 1, 1, sz),
new Location(plotArea.worldname, ex - 1, dpw.PLOT_HEIGHT - 1, ez), dpw.MAIN_BLOCK); new Location(plotArea.worldname, ex - 1, dpw.PLOT_HEIGHT - 1, ez), dpw.MAIN_BLOCK);
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx + 1, dpw.PLOT_HEIGHT, sz), queue.setCuboid(new Location(plotArea.worldname, sx + 1, dpw.PLOT_HEIGHT, sz),
new Location(plotArea.worldname, ex - 1, dpw.PLOT_HEIGHT, ez), dpw.TOP_BLOCK); new Location(plotArea.worldname, ex - 1, dpw.PLOT_HEIGHT, ez), dpw.TOP_BLOCK);
queue.enqueue();
return true; return true;
} }
@ -382,12 +407,14 @@ public class ClassicPlotManager extends SquarePlotManager {
int ex = sx + dpw.ROAD_WIDTH - 1; int ex = sx + dpw.ROAD_WIDTH - 1;
int sz = location.getZ() + 1; int sz = location.getZ() + 1;
int ez = sz + dpw.ROAD_WIDTH - 1; int ez = sz + dpw.ROAD_WIDTH - 1;
MainUtil.setSimpleCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, dpw.ROAD_HEIGHT + 1, sz), LocalBlockQueue queue = plotArea.getQueue(false);
queue.setCuboid(new Location(plotArea.worldname, sx, dpw.ROAD_HEIGHT + 1, sz),
new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0)); new Location(plotArea.worldname, ex, 255, ez), PlotBlock.get((short) 0, (byte) 0));
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, 1, sz), queue.setCuboid(new Location(plotArea.worldname, sx, 1, sz),
new Location(plotArea.worldname, ex, dpw.ROAD_HEIGHT - 1, ez), dpw.MAIN_BLOCK); new Location(plotArea.worldname, ex, dpw.ROAD_HEIGHT - 1, ez), dpw.MAIN_BLOCK);
MainUtil.setCuboidAsync(plotArea.worldname, new Location(plotArea.worldname, sx, dpw.ROAD_HEIGHT, sz), queue.setCuboid(new Location(plotArea.worldname, sx, dpw.ROAD_HEIGHT, sz),
new Location(plotArea.worldname, ex, dpw.ROAD_HEIGHT, ez), dpw.TOP_BLOCK); new Location(plotArea.worldname, ex, dpw.ROAD_HEIGHT, ez), dpw.TOP_BLOCK);
queue.enqueue();
return true; return true;
} }

View File

@ -1,14 +1,15 @@
package com.intellectualcrafters.plot.generator; package com.intellectualcrafters.plot.generator;
import com.intellectualcrafters.jnbt.CompoundTag; import com.intellectualcrafters.jnbt.CompoundTag;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -20,12 +21,12 @@ public class HybridGen extends IndependentPlotGenerator {
} }
@Override @Override
public void generateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random) { public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
HybridPlotWorld hpw = (HybridPlotWorld) settings; HybridPlotWorld hpw = (HybridPlotWorld) settings;
// Biome // Biome
for (short x = 0; x < 16; x++) { for (short x = 0; x < 16; x++) {
for (short z = 0; z < 16; z++) { for (short z = 0; z < 16; z++) {
result.setBiome(x, z, hpw.PLOT_BIOME); result.fillBiome(hpw.PLOT_BIOME);
} }
} }
// Bedrock // Bedrock
@ -37,10 +38,11 @@ public class HybridGen extends IndependentPlotGenerator {
} }
} }
// Coords // Coords
int cx = result.getX(); Location min = result.getMin();
int cz = result.getZ(); int cx = min.getX() >> 4;
int bx = (cx << 4) - hpw.ROAD_OFFSET_X; int cz = min.getZ() >> 4;
int bz = (cz << 4) - hpw.ROAD_OFFSET_Z; int bx = (min.getX()) - hpw.ROAD_OFFSET_X;
int bz = (min.getZ()) - hpw.ROAD_OFFSET_Z;
short rbx; short rbx;
if (bx < 0) { if (bx < 0) {
rbx = (short) (hpw.SIZE + (bx % hpw.SIZE)); rbx = (short) (hpw.SIZE + (bx % hpw.SIZE));
@ -183,11 +185,12 @@ public class HybridGen extends IndependentPlotGenerator {
} }
@Override @Override
public boolean populateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random) { public boolean populateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
HybridPlotWorld hpw = (HybridPlotWorld) settings; HybridPlotWorld hpw = (HybridPlotWorld) settings;
if (hpw.G_SCH_STATE != null) { if (hpw.G_SCH_STATE != null) {
int cx = result.getX(); Location min = result.getMin();
int cz = result.getZ(); int cx = min.getX() >> 4;
int cz = min.getZ() >> 4;
int p1x = cx << 4; int p1x = cx << 4;
int p1z = cz << 4; int p1z = cz << 4;
int bx = p1x - hpw.ROAD_OFFSET_X; int bx = p1x - hpw.ROAD_OFFSET_X;

View File

@ -3,7 +3,6 @@ package com.intellectualcrafters.plot.generator;
import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.commands.Template; import com.intellectualcrafters.plot.commands.Template;
import com.intellectualcrafters.plot.config.Settings; import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.FileBytes; import com.intellectualcrafters.plot.object.FileBytes;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
@ -14,9 +13,8 @@ import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.SetQueue; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -72,6 +70,7 @@ public class HybridPlotManager extends ClassicPlotManager {
private void createSchemAbs(HybridPlotWorld hpw, Location pos1, Location pos2, boolean clear) { private void createSchemAbs(HybridPlotWorld hpw, Location pos1, Location pos2, boolean clear) {
int size = hpw.SIZE; int size = hpw.SIZE;
LocalBlockQueue queue = hpw.getQueue(false);
for (int x = pos1.getX(); x <= pos2.getX(); x++) { for (int x = pos1.getX(); x <= pos2.getX(); x++) {
short absX = (short) ((x - hpw.ROAD_OFFSET_X) % size); short absX = (short) ((x - hpw.ROAD_OFFSET_X) % size);
if (absX < 0) { if (absX < 0) {
@ -85,16 +84,17 @@ public class HybridPlotManager extends ClassicPlotManager {
HashMap<Integer, PlotBlock> blocks = hpw.G_SCH.get(MathMan.pair(absX, absZ)); HashMap<Integer, PlotBlock> blocks = hpw.G_SCH.get(MathMan.pair(absX, absZ));
if (clear) { if (clear) {
for (short y = (short) 0; y <= hpw.SCHEMATIC_HEIGHT; y++) { for (short y = (short) 0; y <= hpw.SCHEMATIC_HEIGHT; y++) {
SetQueue.IMP.setBlock(hpw.worldname, x, y, z, 0); queue.setBlock(x, y, z, 0);
} }
} }
if (blocks != null) { if (blocks != null) {
for (Entry<Integer, PlotBlock> entry : blocks.entrySet()) { for (Entry<Integer, PlotBlock> entry : blocks.entrySet()) {
SetQueue.IMP.setBlock(hpw.worldname, x, entry.getKey(), z, entry.getValue()); queue.setBlock(x, entry.getKey(), z, entry.getValue());
} }
} }
} }
} }
queue.enqueue();
} }
@Override @Override
@ -157,13 +157,14 @@ public class HybridPlotManager extends ClassicPlotManager {
bedrock = PlotBlock.get((short) 0, (byte) 0); bedrock = PlotBlock.get((short) 0, (byte) 0);
} }
final PlotBlock air = PlotBlock.get((short) 0, (byte) 0); final PlotBlock air = PlotBlock.get((short) 0, (byte) 0);
final String biome = WorldUtil.IMP.getBiomeList()[dpw.PLOT_BIOME]; final String biome = dpw.PLOT_BIOME;
final LocalBlockQueue queue = plotArea.getQueue(false);
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() { ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
@Override @Override
public void run(int[] value) { public void run(int[] value) {
// If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk // If the chunk isn't near the edge and it isn't an augmented world we can just regen the whole chunk
if (canRegen && (value[6] == 0)) { if (canRegen && (value[6] == 0)) {
ChunkManager.manager.regenerateChunk(world, new ChunkLoc(value[0], value[1])); queue.regenChunk(value[0], value[1]);
return; return;
} }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -174,25 +175,26 @@ public class HybridPlotManager extends ClassicPlotManager {
// These two locations are for each component (e.g. bedrock, main block, floor, air) // These two locations are for each component (e.g. bedrock, main block, floor, air)
Location bot = new Location(world, value[2], 0, value[3]); Location bot = new Location(world, value[2], 0, value[3]);
Location top = new Location(world, value[4], 1, value[5]); Location top = new Location(world, value[4], 1, value[5]);
MainUtil.setSimpleCuboidAsync(world, bot, top, bedrock); queue.setCuboid(bot, top, bedrock);
// Each component has a different layer // Each component has a different layer
bot.setY(1); bot.setY(1);
top.setY(dpw.PLOT_HEIGHT); top.setY(dpw.PLOT_HEIGHT);
MainUtil.setCuboidAsync(world, bot, top, filling); queue.setCuboid(bot, top, filling);
bot.setY(dpw.PLOT_HEIGHT); bot.setY(dpw.PLOT_HEIGHT);
top.setY(dpw.PLOT_HEIGHT + 1); top.setY(dpw.PLOT_HEIGHT + 1);
MainUtil.setCuboidAsync(world, bot, top, plotfloor); queue.setCuboid(bot, top, plotfloor);
bot.setY(dpw.PLOT_HEIGHT + 1); bot.setY(dpw.PLOT_HEIGHT + 1);
top.setY(256); top.setY(256);
MainUtil.setSimpleCuboidAsync(world, bot, top, air); queue.setCuboid(bot, top, air);
// And finally set the schematic, the y value is unimportant for this function // And finally set the schematic, the y value is unimportant for this function
pastePlotSchematic(dpw, bot, top); pastePlotSchematic(dpw, bot, top);
} }
}, new Runnable() { }, new Runnable() {
@Override @Override
public void run() { public void run() {
queue.enqueue();
// And notify whatever called this when plot clearing is done // And notify whatever called this when plot clearing is done
SetQueue.IMP.addTask(whenDone); GlobalBlockQueue.IMP.addTask(whenDone);
} }
}, 10); }, 10);
return true; return true;

View File

@ -8,7 +8,6 @@ import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
@ -18,9 +17,10 @@ import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.MathMan; import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import java.io.File; import java.io.File;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
@ -107,7 +107,27 @@ public abstract class HybridUtils {
run.run(); run.run();
} }
public abstract int checkModified(String world, int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock[] blocks); public int checkModified(LocalBlockQueue queue, int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock[] blocks) {
int count = 0;
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
PlotBlock block = queue.getBlock(x, y, z);
boolean same = false;
for (PlotBlock p : blocks) {
if (block.id == p.id) {
same = true;
break;
}
}
if (!same) {
count++;
}
}
}
}
return count;
}
public final ArrayList<ChunkLoc> getChunks(ChunkLoc region) { public final ArrayList<ChunkLoc> getChunks(ChunkLoc region) {
ArrayList<ChunkLoc> chunks = new ArrayList<>(); ArrayList<ChunkLoc> chunks = new ArrayList<>();
@ -139,6 +159,7 @@ public abstract class HybridUtils {
whenDone.value = 0; whenDone.value = 0;
final ClassicPlotWorld cpw = (ClassicPlotWorld) plotArea; final ClassicPlotWorld cpw = (ClassicPlotWorld) plotArea;
final ArrayDeque<RegionWrapper> zones = new ArrayDeque<>(plot.getRegions()); final ArrayDeque<RegionWrapper> zones = new ArrayDeque<>(plot.getRegions());
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(cpw.worldname, false);
Runnable run = new Runnable() { Runnable run = new Runnable() {
@Override @Override
public void run() { public void run() {
@ -159,11 +180,10 @@ public abstract class HybridUtils {
int bz = value[3]; int bz = value[3];
int ex = value[4]; int ex = value[4];
int ez = value[5]; int ez = value[5];
whenDone.value += checkModified(plot.getArea().worldname, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK); whenDone.value += checkModified(queue, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK);
whenDone.value += checkModified(plot.getArea().worldname, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK); whenDone.value += checkModified(queue, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK);
whenDone.value += checkModified( whenDone.value += checkModified(
plot.getArea().worldname, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, queue, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, new PlotBlock[]{PlotBlock.get((short) 0, (byte) 0)});
new PlotBlock[]{PlotBlock.get((short) 0, (byte) 0)});
} }
}, this, 5); }, this, 5);
@ -281,7 +301,7 @@ public abstract class HybridUtils {
PS.debug("&d - Potentially skipping 1024 chunks"); PS.debug("&d - Potentially skipping 1024 chunks");
PS.debug("&d - TODO: recommend chunkster if corrupt"); PS.debug("&d - TODO: recommend chunkster if corrupt");
} }
SetQueue.IMP.addTask(new Runnable() { GlobalBlockQueue.IMP.addTask(new Runnable() {
@Override @Override
public void run() { public void run() {
TaskManager.runTaskLater(task, 20); TaskManager.runTaskLater(task, 20);
@ -297,6 +317,7 @@ public abstract class HybridUtils {
public boolean setupRoadSchematic(Plot plot) { public boolean setupRoadSchematic(Plot plot) {
final String world = plot.getArea().worldname; final String world = plot.getArea().worldname;
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
Location bot = plot.getBottomAbs().subtract(1, 0, 1); Location bot = plot.getBottomAbs().subtract(1, 0, 1);
Location top = plot.getTopAbs(); Location top = plot.getTopAbs();
final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea(); final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea();
@ -305,10 +326,10 @@ public abstract class HybridUtils {
int sy = plotworld.ROAD_HEIGHT; int sy = plotworld.ROAD_HEIGHT;
int ex = bot.getX(); int ex = bot.getX();
int ez = top.getZ(); int ez = top.getZ();
int ey = get_ey(world, sx, ex, sz, ez, sy); int ey = get_ey(queue, sx, ex, sz, ez, sy);
int bz = sz - plotworld.ROAD_WIDTH; int bz = sz - plotworld.ROAD_WIDTH;
int tz = sz - 1; int tz = sz - 1;
int ty = get_ey(world, sx, ex, bz, tz, sy); int ty = get_ey(queue, sx, ex, bz, tz, sy);
Set<RegionWrapper> sideRoad = new HashSet<>(Collections.singletonList(new RegionWrapper(sx, ex, sy, ey, sz, ez))); Set<RegionWrapper> sideRoad = new HashSet<>(Collections.singletonList(new RegionWrapper(sx, ex, sy, ey, sz, ez)));
final Set<RegionWrapper> intersection = new HashSet<>(Collections.singletonList(new RegionWrapper(sx, ex, sy, ty, bz, tz))); final Set<RegionWrapper> intersection = new HashSet<>(Collections.singletonList(new RegionWrapper(sx, ex, sy, ty, bz, tz)));
@ -332,7 +353,22 @@ public abstract class HybridUtils {
return true; return true;
} }
public abstract int get_ey(String world, int sx, int ex, int sz, int ez, int sy); public int get_ey(LocalBlockQueue queue, int sx, int ex, int sz, int ez, int sy) {
int ey = sy;
for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) {
for (int y = sy; y < 256; y++) {
if (y > ey) {
PlotBlock block = queue.getBlock(x, y, z);
if (block.id != 0) {
ey = y;
}
}
}
}
}
return ey;
}
public boolean regenerateRoad(final PlotArea area, final ChunkLoc chunk, int extend) { public boolean regenerateRoad(final PlotArea area, final ChunkLoc chunk, int extend) {
int x = chunk.x << 4; int x = chunk.x << 4;
@ -359,6 +395,7 @@ public abstract class HybridUtils {
PlotId id2 = manager.getPlotId(plotWorld, ex, 0, ez); PlotId id2 = manager.getPlotId(plotWorld, ex, 0, ez);
x -= plotWorld.ROAD_OFFSET_X; x -= plotWorld.ROAD_OFFSET_X;
z -= plotWorld.ROAD_OFFSET_Z; z -= plotWorld.ROAD_OFFSET_Z;
LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(plotWorld.worldname, false);
if (id1 == null || id2 == null || id1 != id2) { if (id1 == null || id2 == null || id1 != id2) {
boolean result = ChunkManager.manager.loadChunk(area.worldname, chunk, false); boolean result = ChunkManager.manager.loadChunk(area.worldname, chunk, false);
if (result) { if (result) {
@ -399,26 +436,20 @@ public abstract class HybridUtils {
if (condition) { if (condition) {
HashMap<Integer, PlotBlock> blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ)); HashMap<Integer, PlotBlock> blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ));
for (short y = (short) plotWorld.ROAD_HEIGHT; y <= plotWorld.ROAD_HEIGHT + plotWorld.SCHEMATIC_HEIGHT + extend; y++) { for (short y = (short) plotWorld.ROAD_HEIGHT; y <= plotWorld.ROAD_HEIGHT + plotWorld.SCHEMATIC_HEIGHT + extend; y++) {
SetQueue.IMP.setBlock(area.worldname, x + X + plotWorld.ROAD_OFFSET_X, y, z + Z + plotWorld.ROAD_OFFSET_Z, 0); queue.setBlock(x + X + plotWorld.ROAD_OFFSET_X, y, z + Z + plotWorld.ROAD_OFFSET_Z, 0);
} }
if (blocks != null) { if (blocks != null) {
for (Entry<Integer, PlotBlock> entry : blocks.entrySet()) { for (Entry<Integer, PlotBlock> entry : blocks.entrySet()) {
SetQueue.IMP.setBlock(area.worldname, x + X + plotWorld.ROAD_OFFSET_X, entry.getKey(), queue.setBlock(x + X + plotWorld.ROAD_OFFSET_X, entry.getKey(), z + Z + plotWorld.ROAD_OFFSET_Z, entry.getValue());
z + Z + plotWorld.ROAD_OFFSET_Z, entry.getValue());
} }
} }
} }
} }
} }
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
ChunkManager.manager.unloadChunk(area.worldname, chunk, true, true);
}
});
return true; return true;
} }
} }
queue.enqueue();
return false; return false;
} }
} }

View File

@ -6,7 +6,7 @@ import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotManager; import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.SetupObject; import com.intellectualcrafters.plot.object.SetupObject;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
/** /**
* This class allows for implementation independent world generation. * This class allows for implementation independent world generation.
@ -28,9 +28,9 @@ public abstract class IndependentPlotGenerator {
* @param settings * @param settings
* @param random * @param random
*/ */
public abstract void generateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random); public abstract void generateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random);
public boolean populateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random) { public boolean populateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
return false; return false;
} }

View File

@ -0,0 +1,45 @@
package com.intellectualcrafters.plot.object;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.StringMan;
public class ChunkWrapper {
public final int x;
public final int z;
public final String world;
public ChunkWrapper(String world, int x, int z) {
this.world = world;
this.x = x;
this.z = z;
}
@Override
public int hashCode() {
return MathMan.pair((short) x, (short) z);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.hashCode() != obj.hashCode()) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ChunkWrapper other = (ChunkWrapper) obj;
return (this.x == other.x) && (this.z == other.z) && StringMan.isEqual(this.world, other.world);
}
@Override
public String toString() {
return this.world + ":" + this.x + "," + this.z;
}
}

View File

@ -17,14 +17,14 @@ import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.Permissions; import com.intellectualcrafters.plot.util.Permissions;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager; import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis; import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import com.plotsquared.listener.PlotListener; import com.plotsquared.listener.PlotListener;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Area; import java.awt.geom.Area;
import java.awt.geom.PathIterator; import java.awt.geom.PathIterator;
@ -782,7 +782,7 @@ public class Plot {
manager.claimPlot(Plot.this.area, current); manager.claimPlot(Plot.this.area, current);
} }
} }
SetQueue.IMP.addTask(run); GlobalBlockQueue.IMP.addTask(run);
return; return;
} }
Plot current = queue.poll(); Plot current = queue.poll();
@ -794,10 +794,11 @@ public class Plot {
} }
}; };
if (!isMerged() && this.area.getRegion().equals(getLargestRegion())) { if (!isMerged() && this.area.getRegion().equals(getLargestRegion())) {
final LocalBlockQueue blockQueue = area.getQueue(false);
ChunkManager.largeRegionTask(this.area.worldname, this.area.getRegion(), new RunnableVal<ChunkLoc>() { ChunkManager.largeRegionTask(this.area.worldname, this.area.getRegion(), new RunnableVal<ChunkLoc>() {
@Override @Override
public void run(ChunkLoc value) { public void run(ChunkLoc value) {
ChunkManager.manager.regenerateChunk(Plot.this.area.worldname, value); blockQueue.regenChunk(value.x, value.z);
} }
}, whenDone); }, whenDone);
} else { } else {
@ -1246,20 +1247,17 @@ public class Plot {
* This should not need to be called * This should not need to be called
*/ */
public void refreshChunks() { public void refreshChunks() {
TaskManager.runTask(new Runnable() { LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(area.worldname, false);
@Override HashSet<ChunkLoc> chunks = new HashSet<>();
public void run() { for (RegionWrapper region : Plot.this.getRegions()) {
HashSet<ChunkLoc> chunks = new HashSet<>(); for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) {
for (RegionWrapper region : Plot.this.getRegions()) { for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) {
for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) { if (chunks.add(new ChunkLoc(x, z))) {
for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) { queue.refreshChunk(x, z);
chunks.add(new ChunkLoc(x, z));
}
} }
} }
SetQueue.IMP.queue.sendChunk(Plot.this.area.worldname, chunks);
} }
}); }
} }
/** Remove the plot sign if it is set. */ /** Remove the plot sign if it is set. */
@ -1269,7 +1267,9 @@ public class Plot {
return; return;
} }
Location loc = manager.getSignLoc(this.area, this); Location loc = manager.getSignLoc(this.area, this);
SetQueue.IMP.setBlock(this.area.worldname, loc.getX(), loc.getY(), loc.getZ(), 0); LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(area.worldname, false);
queue.setBlock(loc.getX(), loc.getY(), loc.getZ(), 0);
queue.flush();
} }
/** Set the plot sign if plot signs are enabled. */ /** Set the plot sign if plot signs are enabled. */

View File

@ -15,9 +15,9 @@ import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotGameMode; import com.intellectualcrafters.plot.util.PlotGameMode;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.area.QuadMap; import com.intellectualcrafters.plot.util.area.QuadMap;
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -48,7 +48,7 @@ public abstract class PlotArea {
public boolean ALLOW_SIGNS = true; public boolean ALLOW_SIGNS = true;
public boolean MOB_SPAWNING = false; public boolean MOB_SPAWNING = false;
public boolean MOB_SPAWNER_SPAWNING = false; public boolean MOB_SPAWNER_SPAWNING = false;
public int PLOT_BIOME = 1; public String PLOT_BIOME = "FOREST";
public boolean PLOT_CHAT = false; public boolean PLOT_CHAT = false;
public boolean SCHEMATIC_CLAIM_SPECIFY = false; public boolean SCHEMATIC_CLAIM_SPECIFY = false;
public boolean SCHEMATIC_ON_CLAIM = false; public boolean SCHEMATIC_ON_CLAIM = false;
@ -91,6 +91,10 @@ public abstract class PlotArea {
this.worldhash = worldName.hashCode(); this.worldhash = worldName.hashCode();
} }
public LocalBlockQueue getQueue(boolean autoQueue) {
return GlobalBlockQueue.IMP.getNewQueue(worldname, autoQueue);
}
/** /**
* Create a new PlotArea object with no functionality/information. * Create a new PlotArea object with no functionality/information.
* - Mainly used during startup before worlds are created as a temporary object * - Mainly used during startup before worlds are created as a temporary object
@ -211,7 +215,7 @@ public abstract class PlotArea {
this.AUTO_MERGE = config.getBoolean("plot.auto_merge"); this.AUTO_MERGE = config.getBoolean("plot.auto_merge");
this.MAX_PLOT_MEMBERS = config.getInt("limits.max-members"); this.MAX_PLOT_MEMBERS = config.getInt("limits.max-members");
this.ALLOW_SIGNS = config.getBoolean("plot.create_signs"); this.ALLOW_SIGNS = config.getBoolean("plot.create_signs");
this.PLOT_BIOME = WorldUtil.IMP.getBiomeFromString(Configuration.BIOME.parseString(config.getString("plot.biome"))); this.PLOT_BIOME = Configuration.BIOME.parseString(config.getString("plot.biome"));
this.SCHEMATIC_ON_CLAIM = config.getBoolean("schematic.on_claim"); this.SCHEMATIC_ON_CLAIM = config.getBoolean("schematic.on_claim");
this.SCHEMATIC_FILE = config.getString("schematic.file"); this.SCHEMATIC_FILE = config.getString("schematic.file");
this.SCHEMATIC_CLAIM_SPECIFY = config.getBoolean("schematic.specify_on_claim"); this.SCHEMATIC_CLAIM_SPECIFY = config.getBoolean("schematic.specify_on_claim");

View File

@ -4,24 +4,23 @@ import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc; import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper; import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import com.intellectualcrafters.plot.util.block.OffsetLocalBlockQueue;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
public abstract class ChunkManager { public abstract class ChunkManager {
public static ChunkManager manager = null; public static ChunkManager manager = null;
private static RunnableVal<PlotChunk<?>> CURRENT_FORCE_CHUNK; private static RunnableVal<ScopedLocalBlockQueue> CURRENT_FORCE_CHUNK;
private static RunnableVal<PlotChunk<?>> CURRENT_ADD_CHUNK; private static RunnableVal<ScopedLocalBlockQueue> CURRENT_ADD_CHUNK;
public static ChunkLoc getChunkChunk(Location location) { public static ChunkLoc getChunkChunk(Location location) {
int x = location.getX() >> 9; int x = location.getX() >> 9;
@ -29,40 +28,41 @@ public abstract class ChunkManager {
return new ChunkLoc(x, z); return new ChunkLoc(x, z);
} }
public static void setChunkInPlotArea(RunnableVal<PlotChunk<?>> force, RunnableVal<PlotChunk<?>> add, String world, ChunkLoc loc) { public static void setChunkInPlotArea(RunnableVal<ScopedLocalBlockQueue> force, RunnableVal<ScopedLocalBlockQueue> add, String world, ChunkLoc loc) {
LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
if (PS.get().isAugmented(world)) { if (PS.get().isAugmented(world)) {
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z); OffsetLocalBlockQueue offset = new OffsetLocalBlockQueue(queue, loc.x >> 4, 0, loc.z >> 4);
PlotChunk<?> chunk = SetQueue.IMP.queue.getChunk(wrap); ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(offset, new Location(world, 0, 0, 0), new Location(world, 15, 255, 15));
if (force != null) { if (force != null) {
force.run(chunk); force.run(scoped);
} else {
scoped.regenChunk(loc.x, loc.z);
if (add != null) {
add.run(scoped);
}
} }
manager.regenerateChunk(world, loc); queue.flush();
if (add != null) {
add.run(chunk);
}
chunk.addToQueue();
chunk.flush(true);
} else { } else {
CURRENT_FORCE_CHUNK = force; CURRENT_FORCE_CHUNK = force;
CURRENT_ADD_CHUNK = add; CURRENT_ADD_CHUNK = add;
manager.regenerateChunk(world, loc); queue.regenChunk(loc.x, loc.z);
CURRENT_FORCE_CHUNK = null; CURRENT_FORCE_CHUNK = null;
CURRENT_ADD_CHUNK = null; CURRENT_ADD_CHUNK = null;
} }
} }
public static boolean preProcessChunk(PlotChunk<?> chunk) { public static boolean preProcessChunk(ScopedLocalBlockQueue queue) {
if (CURRENT_FORCE_CHUNK != null) { if (CURRENT_FORCE_CHUNK != null) {
CURRENT_FORCE_CHUNK.run(chunk); CURRENT_FORCE_CHUNK.run(queue);
CURRENT_FORCE_CHUNK = null; CURRENT_FORCE_CHUNK = null;
return true; return true;
} }
return false; return false;
} }
public static boolean postProcessChunk(PlotChunk<?> chunk) { public static boolean postProcessChunk(ScopedLocalBlockQueue queue) {
if (CURRENT_ADD_CHUNK != null) { if (CURRENT_ADD_CHUNK != null) {
CURRENT_ADD_CHUNK.run(chunk); CURRENT_ADD_CHUNK.run(queue);
CURRENT_ADD_CHUNK = null; CURRENT_ADD_CHUNK = null;
return true; return true;
} }
@ -228,20 +228,6 @@ public abstract class ChunkManager {
return chunks; return chunks;
} }
public void regenerateChunk(String world, ChunkLoc loc) {
SetQueue.IMP.regenerateChunk(world, loc);
SetQueue.IMP.queue.sendChunk(world, Collections.singletonList(loc));
for (Map.Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
Location pLoc = pp.getLocation();
if (!StringMan.isEqual(world, pLoc.getWorld()) || !pLoc.getChunkLoc().equals(loc)) {
continue;
}
pLoc.setY(WorldUtil.IMP.getHighestBlock(world, pLoc.getX(), pLoc.getZ()));
pp.teleport(pLoc);
}
}
public void deleteRegionFiles(String world, Collection<ChunkLoc> chunks) { public void deleteRegionFiles(String world, Collection<ChunkLoc> chunks) {
deleteRegionFiles(world, chunks, null); deleteRegionFiles(world, chunks, null);
} }

View File

@ -8,18 +8,14 @@ import com.intellectualcrafters.plot.database.DBFunc;
import com.intellectualcrafters.plot.flag.Flag; import com.intellectualcrafters.plot.flag.Flag;
import com.intellectualcrafters.plot.flag.FlagManager; import com.intellectualcrafters.plot.flag.FlagManager;
import com.intellectualcrafters.plot.flag.Flags; import com.intellectualcrafters.plot.flag.Flags;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.ConsolePlayer; import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.Location; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@ -202,7 +198,7 @@ public class MainUtil {
* @return true if any changes were made * @return true if any changes were made
*/ */
public static boolean resetBiome(PlotArea area, Location pos1, Location pos2) { public static boolean resetBiome(PlotArea area, Location pos1, Location pos2) {
String biome = WorldUtil.IMP.getBiomeList()[area.PLOT_BIOME]; String biome = area.PLOT_BIOME;
if (!StringMan.isEqual(WorldUtil.IMP.getBiome(area.worldname, (pos1.getX() + pos2.getX()) / 2, (pos1.getZ() + pos2.getZ()) / 2), biome)) { if (!StringMan.isEqual(WorldUtil.IMP.getBiome(area.worldname, (pos1.getX() + pos2.getX()) / 2, (pos1.getZ() + pos2.getZ()) / 2), biome)) {
MainUtil.setBiome(area.worldname, pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome); MainUtil.setBiome(area.worldname, pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome);
return true; return true;
@ -491,15 +487,6 @@ public class MainUtil {
return area.getPlotAbs(id); return area.getPlotAbs(id);
} }
/**
* Resend the chunk at a location.
* @param world
* @param loc
*/
public static void update(String world, ChunkLoc loc) {
SetQueue.IMP.queue.sendChunk(world, Collections.singletonList(loc));
}
public static File getFile(File base, String path) { public static File getFile(File base, String path) {
if (Paths.get(path).isAbsolute()) { if (Paths.get(path).isAbsolute()) {
return new File(path); return new File(path);
@ -507,46 +494,6 @@ public class MainUtil {
return new File(base, path); return new File(base, path);
} }
/**
* Set a cuboid asynchronously to a set of blocks.
* @param world
* @param pos1
* @param pos2
* @param blocks
*/
public static void setCuboidAsync(String world, Location pos1, Location pos2, PlotBlock[] blocks) {
if (blocks.length == 1) {
setSimpleCuboidAsync(world, pos1, pos2, blocks[0]);
return;
}
for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
int i = PseudoRandom.random.random(blocks.length);
PlotBlock block = blocks[i];
SetQueue.IMP.setBlock(world, x, y, z, block);
}
}
}
}
/**
* Set a cuboid asynchronously to a block.
* @param world
* @param pos1
* @param pos2
* @param newBlock
*/
public static void setSimpleCuboidAsync(String world, Location pos1, Location pos2, PlotBlock newBlock) {
for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
SetQueue.IMP.setBlock(world, x, y, z, newBlock);
}
}
}
}
/** /**
* Synchronously set the biome in a selection. * Synchronously set the biome in a selection.
* @param world * @param world

View File

@ -21,6 +21,120 @@ public class MathMan {
} }
} }
private final static int[] table = {
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57,
59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83,
84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102,
103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118,
119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145,
146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157,
158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178,
179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188,
189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197,
198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206,
207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215,
215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223,
224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231,
231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246,
246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253,
253, 254, 254, 255
};
public static long pairInt(int x, int y) {
return (((long)x) << 32) | (y & 0xffffffffL);
}
public static int unpairIntX(long pair) {
return (int)(pair >> 32);
}
public static int unpairIntY(long pair) {
return (int)pair;
}
public static byte pair16(byte x, byte y) {
return (byte) (x + (y << 4));
}
public static byte unpair16x(byte value) {
return (byte) (value & 0xF);
}
public static byte unpair16y(byte value) {
return (byte) ((value >> 4) & 0xF);
}
public static int sqrt(int x) {
int xn;
if (x >= 0x10000) {
if (x >= 0x1000000) {
if (x >= 0x10000000) {
if (x >= 0x40000000) {
xn = table[x >> 24] << 8;
} else {
xn = table[x >> 22] << 7;
}
} else {
if (x >= 0x4000000) {
xn = table[x >> 20] << 6;
} else {
xn = table[x >> 18] << 5;
}
}
xn = (xn + 1 + (x / xn)) >> 1;
xn = (xn + 1 + (x / xn)) >> 1;
return ((xn * xn) > x) ? --xn : xn;
} else {
if (x >= 0x100000) {
if (x >= 0x400000) {
xn = table[x >> 16] << 4;
} else {
xn = table[x >> 14] << 3;
}
} else {
if (x >= 0x40000) {
xn = table[x >> 12] << 2;
} else {
xn = table[x >> 10] << 1;
}
}
xn = (xn + 1 + (x / xn)) >> 1;
return ((xn * xn) > x) ? --xn : xn;
}
} else {
if (x >= 0x100) {
if (x >= 0x1000) {
if (x >= 0x4000) {
xn = (table[x >> 8]) + 1;
} else {
xn = (table[x >> 6] >> 1) + 1;
}
} else {
if (x >= 0x400) {
xn = (table[x >> 4] >> 2) + 1;
} else {
xn = (table[x >> 2] >> 3) + 1;
}
}
return ((xn * xn) > x) ? --xn : xn;
} else {
if (x >= 0) {
return table[x] >> 4;
}
}
}
throw new IllegalArgumentException("Invalid number:" + x);
}
public static double getMean(int[] array) { public static double getMean(int[] array) {
double count = 0; double count = 0;
for (int i : array) { for (int i : array) {
@ -115,7 +229,7 @@ public class MathMan {
} }
public static double sqrtApprox(double d) { public static double sqrtApprox(double d) {
return Double.longBitsToDouble(((Double.doubleToLongBits(d) - (1L << 52)) >> 1) + (1L << 61)); return Double.longBitsToDouble(((Double.doubleToLongBits(d) - (1l << 52)) >> 1) + (1l << 61));
} }
public static float invSqrt(float x) { public static float invSqrt(float x) {

View File

@ -1,261 +0,0 @@
package com.intellectualcrafters.plot.util;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.object.RunnableVal3;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
/**
* The PlotChunk class is primarily used for world generation and mass block placement.<br>
* - With mass block placement, it is associated with a queue<br>
* - World Generation has no queue, so don't use those methods in that case
* @param <T>
*/
public abstract class PlotChunk<T> implements Cloneable {
private ChunkWrapper chunk;
private T objChunk;
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*/
public PlotChunk(final ChunkWrapper chunk) {
this.chunk = chunk;
}
public ChunkWrapper getChunkWrapper() {
return this.chunk;
}
public void setChunkWrapper(final ChunkWrapper loc) {
this.chunk = loc;
this.objChunk = null;
}
public int getX() {
return chunk.x;
}
public int getZ() {
return chunk.z;
}
/**
* Adds this PlotChunk to the SetQueue for later block placement<br>
* - Will cause issues if not the right type for the implementation
*/
public void addToQueue() {
if (chunk == null) {
throw new IllegalArgumentException("Chunk location cannot be null!");
}
((PlotQueue<T>) SetQueue.IMP.queue).setChunk(this);
}
/**
* Force the queue to finish processing this chunk
* @param fixLighting
*/
public void flush(boolean fixLighting) {
((PlotQueue<T>) SetQueue.IMP.queue).next(getChunkWrapper(), fixLighting);
}
/**
* Force the queue to fix lighting for this chunk
*/
public void fixLighting() {
((PlotQueue<T>) SetQueue.IMP.queue).fixLighting(this, true);
}
/**
* Fill this chunk with a block
* @param id
* @param data
*/
public void fill(int id, byte data) {
fillCuboid(0, 15, 0, 255, 0, 15, id, data);
}
/**
* Fill this chunk with blocks (random)
* @param blocks
*/
public void fill(PlotBlock[] blocks) {
fillCuboid(0, 15, 0, 255, 0, 15, blocks);
}
/**
* Fill a cuboid in this chunk with a block
* @param x1
* @param x2
* @param y1
* @param y2
* @param z1
* @param z2
* @param id
* @param data
*/
public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, int id, byte data) {
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
for (int z = z1; z <= z2; z++) {
setBlock(x, y, z, id, data);
}
}
}
}
/**
* Fill a cuboid in this chunk with blocks
* @param x1
* @param x2
* @param y1
* @param y2
* @param z1
* @param z2
* @param blocks
*/
public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock[] blocks) {
if (blocks.length == 1) {
fillCuboid(x1, x2, y1, y2, z1, z2, blocks[0]);
return;
}
if (chunk != null) {
PseudoRandom.random.state = (chunk.x << 16) | (chunk.z & 0xFFFF);
}
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
for (int z = z1; z <= z2; z++) {
setBlock(x, y, z, blocks[PseudoRandom.random.random(blocks.length)]);
}
}
}
}
/**
* Run a task for each x,z value corresponding to the plot at that location<br>
* - Plot: The plot at the x,z (may be null)<br>
* - Location: The location in the chunk (y = 0)<br>
* - PlotChunk: Reference to this chunk object<br>
* @param task
*/
public void mapByType2D(RunnableVal3<Plot, Integer, Integer> task) {
int bx = getX() << 4;
int bz = getZ() << 4;
String world = getChunkWrapper().world;
PlotArea area = PS.get().getPlotArea(world, null);
Location loc = new Location(world, bx, 0, bz);
if (area != null) {
PlotManager manager = area.getPlotManager();
for (int x = 0; x < 16; x++) {
loc.setX(bx + x);
for (int z = 0; z < 16; z++) {
loc.setZ(bz + z);
task.run(area.getPlotAbs(loc), x, z);
}
}
} else {
for (int x = 0; x < 16; x++) {
loc.setX(bx + x);
for (int z = 0; z < 16; z++) {
loc.setZ(bz + z);
task.run(loc.getPlotAbs(), x, z);
}
}
}
}
/**
* Fill a cuboid in this chunk with a block
* @param x1
* @param x2
* @param y1
* @param y2
* @param z1
* @param z2
* @param block
*/
public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock block) {
fillCuboid(x1, x2, y1, y2, z1, z2, block.id, block.data);
}
/**
* Get the implementation specific chunk
* @Nullable If no location is tied to this container
* @return Chunk
*/
public T getChunk() {
return objChunk != null ? objChunk : getChunkAbs();
}
/**
* Get the implementation specific chunk (no caching)
* @return
*/
public abstract T getChunkAbs();
/**
* Set a block in this container
* @param x
* @param y
* @param z
* @param id
* @param data
*/
public abstract void setBlock(final int x, final int y, final int z, final int id, final byte data);
/**
* Set a block in this container
* @param x
* @param y
* @param z
* @param block
*/
public void setBlock(int x, int y, int z, PlotBlock block) {
setBlock(x, y, z, block.id, block.data);
}
/**
* Set a biome in this container
* @param x
* @param z
* @param biome
*/
public abstract void setBiome(int x, int z, int biome);
@Override
public int hashCode() {
return chunk.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PlotChunk)) {
return false;
}
return chunk.equals(((PlotChunk) obj).chunk);
}
@Override
public String toString() {
return getChunkWrapper().toString();
}
/**
* Attempt to clone this PlotChunk object<br>
* - Depending on the implementation, this may not work
* @return
*/
@Override
public abstract PlotChunk clone();
/**
* Attempt a shallow clone i.e. block mappings share the same reference<br>
* - Depending on the implementation, this may not work
* @return
*/
public abstract PlotChunk shallowClone();
}

View File

@ -1,32 +0,0 @@
package com.intellectualcrafters.plot.util;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import java.util.Collection;
public interface PlotQueue<T> {
boolean setBlock(String world, int x, int y, int z, short id, byte data);
PlotChunk<T> getChunk(ChunkWrapper wrap);
void setChunk(PlotChunk<T> chunk);
boolean fixLighting(PlotChunk<T> chunk, boolean fixAll);
void sendChunk(String world, Collection<ChunkLoc> locs);
/**
* Gets the {@link PlotChunk} and sets the requested blocks.
* @return
*/
PlotChunk<T> next();
PlotChunk<T> next(ChunkWrapper wrap, boolean fixLighting);
void clear();
void regenerateChunk(String world, ChunkLoc loc);
}

View File

@ -24,7 +24,7 @@ import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotBlock; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -136,8 +136,7 @@ public abstract class SchematicHandler {
* *
* @return boolean true if succeeded * @return boolean true if succeeded
*/ */
public void paste(final Schematic schematic, final Plot plot, final int xOffset, final int yOffset, final int zOffset, final boolean autoHeight, public void paste(final Schematic schematic, final Plot plot, final int xOffset, final int yOffset, final int zOffset, final boolean autoHeight, final RunnableVal<Boolean> whenDone) {
final RunnableVal<Boolean> whenDone) {
TaskManager.runTask(new Runnable() { TaskManager.runTask(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -160,7 +159,7 @@ public abstract class SchematicHandler {
} }
} }
final LocalBlockQueue queue = plot.getArea().getQueue(false);
Dimension dimension = schematic.getSchematicDimension(); Dimension dimension = schematic.getSchematicDimension();
final int WIDTH = dimension.getX(); final int WIDTH = dimension.getX();
final int LENGTH = dimension.getZ(); final int LENGTH = dimension.getZ();
@ -322,10 +321,10 @@ public abstract class SchematicHandler {
case 190: case 190:
case 191: case 191:
case 192: case 192:
SetQueue.IMP.setBlock(plot.getArea().worldname, xx, yy, zz, id); queue.setBlock(xx, yy, zz, id);
break; break;
default: default:
SetQueue.IMP.setBlock(plot.getArea().worldname, xx, yy, zz, PlotBlock.get((short) id, datas[i])); queue.setBlock(xx, yy, zz, PlotBlock.get((short) id, datas[i]));
break; break;
} }
} }
@ -333,31 +332,17 @@ public abstract class SchematicHandler {
} }
} }
if (!chunks.isEmpty()) { if (!chunks.isEmpty()) {
final Runnable task = this; this.run();
// Run when the queue is free
SetQueue.IMP.addTask(new Runnable() {
@Override
public void run() {
System.gc();
TaskManager.runTaskLaterAsync(task, 80);
}
});
} else { } else {
System.gc(); queue.flush();
// Finished for (Map.Entry<BlockLoc, CompoundTag> entry : schematic.getTiles().entrySet()) {
SetQueue.IMP.addTask(new Runnable() { BlockLoc loc = entry.getKey();
@Override restoreTile(plot.getArea().worldname, entry.getValue(), p1x + xOffset + loc.x, loc.y + y_offset_actual, p1z + zOffset + loc.z);
public void run() { }
for (Map.Entry<BlockLoc, CompoundTag> entry : schematic.getTiles().entrySet()) { if (whenDone != null) {
BlockLoc loc = entry.getKey(); whenDone.value = true;
restoreTile(plot.getArea().worldname, entry.getValue(), p1x + xOffset + loc.x, loc.y + y_offset_actual, p1z + zOffset + loc.z); whenDone.run();
} }
if (whenDone != null) {
whenDone.value = true;
whenDone.run();
}
}
});
} }
} }
}); });

View File

@ -1,197 +0,0 @@
package com.intellectualcrafters.plot.util;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import java.util.ArrayDeque;
import java.util.concurrent.atomic.AtomicInteger;
public class SetQueue {
public static final SetQueue IMP = new SetQueue();
private final AtomicInteger time_waiting = new AtomicInteger(2);
private final AtomicInteger time_current = new AtomicInteger(0);
private final ArrayDeque<Runnable> runnables = new ArrayDeque<>();
public PlotQueue<?> queue;
private long last;
private long last2;
public SetQueue() {
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
long free = 50 + Math.min(50 + SetQueue.this.last - (SetQueue.this.last = System.currentTimeMillis()),
SetQueue.this.last2 - System.currentTimeMillis());
SetQueue.this.time_current.incrementAndGet();
do {
if (isWaiting()) {
return;
}
PlotChunk<?> current = SetQueue.this.queue.next();
if (current == null) {
SetQueue.this.time_waiting.set(Math.max(SetQueue.this.time_waiting.get(), SetQueue.this.time_current.get() - 2));
tasks();
return;
}
} while ((SetQueue.this.last2 = System.currentTimeMillis()) - SetQueue.this.last < free);
SetQueue.this.time_waiting.set(SetQueue.this.time_current.get() - 1);
}
}, 1);
}
public boolean forceChunkSet() {
PlotChunk<?> set = this.queue.next();
return set != null;
}
public boolean isWaiting() {
return this.time_waiting.get() >= this.time_current.get();
}
public boolean isDone() {
return (this.time_waiting.get() + 1) < this.time_current.get();
}
public void setWaiting() {
this.time_waiting.set(this.time_current.get() + 1);
}
public boolean addTask(Runnable whenDone) {
if (isDone()) {
// Run
tasks();
if (whenDone != null) {
whenDone.run();
}
return true;
}
if (whenDone != null) {
this.runnables.add(whenDone);
}
return false;
}
public boolean tasks() {
if (this.runnables.isEmpty()) {
return false;
}
ArrayDeque<Runnable> tmp = this.runnables.clone();
this.runnables.clear();
for (Runnable runnable : tmp) {
runnable.run();
}
return true;
}
/**
* @param world
* @param x
* @param y
* @param z
* @param id
* @param data
* @return
*/
public boolean setBlock(String world, int x, int y, int z, short id, byte data) {
if ((y > 255) || (y < 0)) {
return false;
}
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, id, data);
}
/**
*
* @param world
* @param x
* @param y
* @param z
* @param block
* @return
*/
public boolean setBlock(String world, int x, int y, int z, PlotBlock block) {
if ((y > 255) || (y < 0)) {
return false;
}
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, block.id, block.data);
}
/**
* @param world The world
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param id
* @return
*/
public boolean setBlock(String world, int x, int y, int z, short id) {
if ((y > 255) || (y < 0)) {
return false;
}
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, id, (byte) 0);
}
/**
*
* @param world The world
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @param id
* @return
*/
public boolean setBlock(String world, int x, int y, int z, int id) {
if (y > 255 || y < 0) {
return false;
}
SetQueue.IMP.setWaiting();
return this.queue.setBlock(world, x, y, z, (short) id, (byte) 0);
}
public void regenerateChunk(String world, ChunkLoc loc) {
this.queue.regenerateChunk(world, loc);
}
public class ChunkWrapper {
public final int x;
public final int z;
public final String world;
public ChunkWrapper(String world, int x, int z) {
this.world = world;
this.x = x;
this.z = z;
}
@Override
public int hashCode() {
return (this.x << 16) | (this.z & 0xFFFF);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.hashCode() != obj.hashCode()) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ChunkWrapper other = (ChunkWrapper) obj;
return (this.x == other.x) && (this.z == other.z) && StringMan.isEqual(this.world, other.world);
}
@Override
public String toString() {
return this.world + ":" + this.x + "," + this.z;
}
}
}

View File

@ -7,51 +7,97 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public abstract class TaskManager { public abstract class TaskManager {
public static TaskManager IMP;
public static final HashSet<String> TELEPORT_QUEUE = new HashSet<>(); public static final HashSet<String> TELEPORT_QUEUE = new HashSet<>();
public static final HashMap<Integer, Integer> tasks = new HashMap<>(); public static final HashMap<Integer, Integer> tasks = new HashMap<>();
public static AtomicInteger index = new AtomicInteger(0); public static AtomicInteger index = new AtomicInteger(0);
public <T> T sync(final RunnableVal<T> function) {
return sync(function, Integer.MAX_VALUE);
}
public <T> T sync(final RunnableVal<T> function, int timeout) {
if (PS.get().isMainThread(Thread.currentThread())) {
function.run();
return function.value;
}
final AtomicBoolean running = new AtomicBoolean(true);
RunnableVal<RuntimeException> run = new RunnableVal<RuntimeException>() {
@Override
public void run(RuntimeException value) {
try {
function.run();
} catch (RuntimeException e) {
this.value = e;
} catch (Throwable neverHappens) {
neverHappens.printStackTrace();
} finally {
running.set(false);
}
synchronized (function) {
function.notifyAll();
}
}
};
TaskManager.IMP.task(run);
try {
synchronized (function) {
while (running.get()) {
function.wait(timeout);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
if (run.value != null) {
throw run.value;
}
return function.value;
}
public static int runTaskRepeat(Runnable runnable, int interval) { public static int runTaskRepeat(Runnable runnable, int interval) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
throw new IllegalArgumentException("disabled"); throw new IllegalArgumentException("disabled");
} }
return PS.get().TASK.taskRepeat(runnable, interval); return IMP.taskRepeat(runnable, interval);
} }
return -1; return -1;
} }
public static int runTaskRepeatAsync(Runnable runnable, int interval) { public static int runTaskRepeatAsync(Runnable runnable, int interval) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
throw new IllegalArgumentException("disabled"); throw new IllegalArgumentException("disabled");
} }
return PS.get().TASK.taskRepeat(runnable, interval); return IMP.taskRepeat(runnable, interval);
} }
return -1; return -1;
} }
public static void runTaskAsync(Runnable runnable) { public static void runTaskAsync(Runnable runnable) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
runnable.run(); runnable.run();
return; return;
} }
PS.get().TASK.taskAsync(runnable); IMP.taskAsync(runnable);
} }
} }
public static void runTask(Runnable runnable) { public static void runTask(Runnable runnable) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
runnable.run(); runnable.run();
return; return;
} }
PS.get().TASK.task(runnable); IMP.task(runnable);
} }
} }
@ -62,21 +108,21 @@ public abstract class TaskManager {
*/ */
public static void runTaskLater(Runnable runnable, int delay) { public static void runTaskLater(Runnable runnable, int delay) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
runnable.run(); runnable.run();
return; return;
} }
PS.get().TASK.taskLater(runnable, delay); IMP.taskLater(runnable, delay);
} }
} }
public static void runTaskLaterAsync(Runnable runnable, int delay) { public static void runTaskLaterAsync(Runnable runnable, int delay) {
if (runnable != null) { if (runnable != null) {
if (PS.get().TASK == null) { if (IMP == null) {
runnable.run(); runnable.run();
return; return;
} }
PS.get().TASK.taskLaterAsync(runnable, delay); IMP.taskLaterAsync(runnable, delay);
} }
} }

View File

@ -0,0 +1,282 @@
package com.intellectualcrafters.plot.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RunnableVal;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.MathMan;
import com.intellectualcrafters.plot.util.TaskManager;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
public abstract class BasicLocalBlockQueue<T> extends LocalBlockQueue {
private final String world;
private long modified;
private final ConcurrentHashMap<Long, LocalChunk> blocks = new ConcurrentHashMap<>();
private final ConcurrentLinkedDeque<LocalChunk> chunks = new ConcurrentLinkedDeque<>();
public BasicLocalBlockQueue(String world) {
super(world);
this.world = world;
this.modified = System.currentTimeMillis();
}
public abstract LocalChunk getLocalChunk(int x, int z);
@Override
public abstract PlotBlock getBlock(int x, int y, int z);
public abstract void setComponents(LocalChunk<T> lc);
@Override
public final String getWorld() {
return world;
}
private LocalChunk lastWrappedChunk;
private int lastX = Integer.MIN_VALUE;
private int lastZ = Integer.MIN_VALUE;
@Override
public final boolean next() {
lastX = Integer.MIN_VALUE;
lastZ = Integer.MIN_VALUE;
try {
if (this.blocks.size() == 0) {
return false;
}
synchronized (blocks) {
LocalChunk chunk = chunks.poll();
if (chunk != null) {
blocks.remove(chunk.longHash());
this.execute(chunk);
return true;
}
}
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
public final boolean execute(final LocalChunk<T> lc) {
if (lc == null) {
return false;
}
this.setComponents(lc);
return true;
}
@Override
public void startSet(boolean parallel) {
// Do nothing
}
@Override
public void endSet(boolean parallel) {
// Do nothing
}
@Override
public final int size() {
return chunks.size();
}
@Override
public final void setModified(long modified) {
this.modified = modified;
}
@Override
public final long getModified() {
return modified;
}
@Override
public final boolean setBlock(int x, int y, int z, int id, int data) {
if ((y > 255) || (y < 0)) {
return false;
}
int cx = x >> 4;
int cz = z >> 4;
if (cx != lastX || cz != lastZ) {
lastX = cx;
lastZ = cz;
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
lastWrappedChunk = this.blocks.get(pair);
if (lastWrappedChunk == null) {
lastWrappedChunk = this.getLocalChunk(x >> 4, z >> 4);
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
LocalChunk previous = this.blocks.put(pair, lastWrappedChunk);
if (previous == null) {
chunks.add(lastWrappedChunk);
return true;
}
this.blocks.put(pair, previous);
lastWrappedChunk = previous;
}
}
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
return true;
}
@Override
public final boolean setBiome(int x, int z, String biome) {
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
LocalChunk result = this.blocks.get(pair);
if (result == null) {
result = this.getLocalChunk(x >> 4, z >> 4);
LocalChunk previous = this.blocks.put(pair, result);
if (previous != null) {
this.blocks.put(pair, previous);
result = previous;
} else {
chunks.add(result);
}
}
result.setBiome(x & 15, z & 15, biome);
return true;
}
public final void setChunk(LocalChunk<T> chunk) {
LocalChunk previous = this.blocks.put(chunk.longHash(), (LocalChunk) chunk);
if (previous != null) {
chunks.remove(previous);
}
chunks.add((LocalChunk) chunk);
}
public abstract class LocalChunk<T> {
public final BasicLocalBlockQueue parent;
public final int z;
public final int x;
public T[] blocks;
public String[][] biomes;
public LocalChunk(BasicLocalBlockQueue<T> parent, int x, int z) {
this.parent = parent;
this.x = x;
this.z = z;
}
/**
* Get the parent queue this chunk belongs to
* @return
*/
public BasicLocalBlockQueue getParent() {
return parent;
}
public int getX() {
return x;
}
public int getZ() {
return z;
}
/**
* Add the chunk to the queue
*/
public void addToQueue() {
parent.setChunk(this);
}
public void fill(int id, int data) {
fillCuboid(0, 15, 0, 255, 0, 15, id, data);
}
/**
* Fill a cuboid in this chunk with a block
* @param x1
* @param x2
* @param y1
* @param y2
* @param z1
* @param z2
* @param id
* @param data
*/
public void fillCuboid(int x1, int x2, int y1, int y2, int z1, int z2, int id, int data) {
for (int x = x1; x <= x2; x++) {
for (int y = y1; y <= y2; y++) {
for (int z = z1; z <= z2; z++) {
setBlock(x, y, z, id, data);
}
}
}
}
public abstract void setBlock(final int x, final int y, final int z, final int id, final int data);
public void setBiome(int x, int z, String biome) {
if (this.biomes == null) {
this.biomes = new String[16][];
}
String[] index = this.biomes[x];
if (index == null) {
index = this.biomes[x] = new String[16];
}
index[z] = biome;
}
public long longHash() {
return MathMan.pairInt(x, z);
}
@Override
public int hashCode() {
return MathMan.pair((short) x, (short) z);
}
}
public class BasicLocalChunk extends LocalChunk<PlotBlock[]> {
public BasicLocalChunk(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
blocks = new PlotBlock[16][];
}
public void setBlock(final int x, final int y, final int z, final int id, final int data) {
PlotBlock block = PlotBlock.get(id, data);
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
PlotBlock[] array = blocks[i];
if (array == null) {
array = (blocks[i] = new PlotBlock[4096]);
}
array[j] = block;
}
}
public class CharLocalChunk extends LocalChunk<char[]> {
public CharLocalChunk(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
blocks = new char[16][];
}
public void setBlock(final int x, final int y, final int z, final int id, final int data) {
PlotBlock block = PlotBlock.get(id, data);
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
char[] array = blocks[i];
if (array == null) {
array = (blocks[i] = new char[4096]);
}
array[j] = (char) ((block.id << 4) + block.data);
}
}
@Override
public void flush() {
GlobalBlockQueue.IMP.dequeue(this);
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
while (next());
}
});
}
}

View File

@ -0,0 +1,121 @@
package com.intellectualcrafters.plot.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
public class DelegateLocalBlockQueue extends LocalBlockQueue {
private final LocalBlockQueue parent;
public LocalBlockQueue getParent() {
return parent;
}
@Override
public boolean next() {
return parent.next();
}
@Override
public void startSet(boolean parallel) {
if (parent != null) {
parent.startSet(parallel);
}
}
@Override
public void endSet(boolean parallel) {
if (parent != null) {
parent.endSet(parallel);
}
}
@Override
public int size() {
if (parent != null) {
return parent.size();
}
return 0;
}
@Override
public void optimize() {
if (parent != null) {
parent.optimize();
}
}
@Override
public void setModified(long modified) {
if (parent != null) {
parent.setModified(modified);
}
}
@Override
public long getModified() {
if (parent != null) {
return parent.getModified();
}
return 0;
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
return parent.setBlock(x, y, z, id, data);
}
@Override
public PlotBlock getBlock(int x, int y, int z) {
return parent.getBlock(x, y, z);
}
@Override
public boolean setBiome(int x, int y, String biome) {
return parent.setBiome(x, y, biome);
}
@Override
public String getWorld() {
return parent.getWorld();
}
@Override
public void flush() {
if (parent != null) {
parent.flush();
}
}
@Override
public void refreshChunk(int x, int z) {
if (parent != null) {
parent.refreshChunk(x, z);
}
}
@Override
public void fixChunkLighting(int x, int z) {
if (parent != null) {
parent.fixChunkLighting(x, z);
}
}
@Override
public void regenChunk(int x, int z) {
if (parent != null) {
parent.regenChunk(x, z);
}
}
@Override
public void enqueue() {
if (parent != null) {
parent.enqueue();
}
}
public DelegateLocalBlockQueue(LocalBlockQueue parent) {
super(parent == null ? null : parent.getWorld());
this.parent = parent;
}
}

View File

@ -0,0 +1,297 @@
package com.intellectualcrafters.plot.util.block;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.RunnableVal2;
import com.intellectualcrafters.plot.util.TaskManager;
import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
public class GlobalBlockQueue {
public static GlobalBlockQueue IMP;
private final int PARALLEL_THREADS;
private QueueProvider provider;
private final ConcurrentLinkedDeque<LocalBlockQueue> activeQueues;
private final ConcurrentLinkedDeque<LocalBlockQueue> inactiveQueues;
private final ConcurrentLinkedDeque<Runnable> runnables;
/**
* Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the server
*/
private long last;
private long secondLast;
private long lastSuccess;
private final AtomicBoolean running;
public enum QueueStage {
INACTIVE, ACTIVE, NONE;
}
public GlobalBlockQueue(QueueProvider provider, int threads) {
this.provider = provider;
activeQueues = new ConcurrentLinkedDeque<>();
inactiveQueues = new ConcurrentLinkedDeque<>();
runnables = new ConcurrentLinkedDeque<>();
running = new AtomicBoolean();
this.PARALLEL_THREADS = threads;
}
private final RunnableVal2<Long, LocalBlockQueue> SET_TASK = new RunnableVal2<Long, LocalBlockQueue>() {
@Override
public void run(Long free, LocalBlockQueue queue) {
do {
boolean more = queue.next();
if (!more) {
lastSuccess = last;
if (inactiveQueues.size() == 0 && activeQueues.size() == 0) {
tasks();
}
return;
}
} while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - GlobalBlockQueue.this.last) < free);
}
};
public void GlobalBlockQueueProvider(QueueProvider provider) {
this.provider = provider;
}
public LocalBlockQueue getNewQueue(String world, boolean autoQueue) {
LocalBlockQueue queue = provider.getNewQueue(world);
if (autoQueue) {
inactiveQueues.add(queue);
}
return queue;
}
public boolean stop() {
if (!running.get()) {
return false;
}
running.set(false);
return true;
}
public boolean runTask() {
if (running.get()) {
return false;
}
running.set(true);
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) {
lastSuccess = System.currentTimeMillis();
tasks();
return;
}
SET_TASK.value1 = 50 + Math.min((50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), GlobalBlockQueue.this.secondLast - System.currentTimeMillis());
SET_TASK.value2 = getNextQueue();
if (SET_TASK.value2 == null) {
return;
}
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread");
}
// Disable the async catcher as it can't discern async vs parallel
SET_TASK.value2.startSet(true);
try {
if (PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK));
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
// Enable it again (note that we are still on the main thread)
SET_TASK.value2.endSet(true);
}
}
}, 1);
return true;
}
public QueueStage getStage(LocalBlockQueue queue) {
if (activeQueues.contains(queue)) {
return QueueStage.ACTIVE;
} else if (inactiveQueues.contains(queue)) {
return QueueStage.INACTIVE;
}
return QueueStage.NONE;
}
public boolean isStage(LocalBlockQueue queue, QueueStage stage) {
switch (stage) {
case ACTIVE:
return activeQueues.contains(queue);
case INACTIVE:
return inactiveQueues.contains(queue);
case NONE:
return !activeQueues.contains(queue) && !inactiveQueues.contains(queue);
}
return false;
}
public void enqueue(LocalBlockQueue queue) {
inactiveQueues.remove(queue);
if (queue.size() > 0 && !activeQueues.contains(queue)) {
queue.optimize();
activeQueues.add(queue);
}
}
public void dequeue(LocalBlockQueue queue) {
inactiveQueues.remove(queue);
activeQueues.remove(queue);
}
public List<LocalBlockQueue> getAllQueues() {
ArrayList<LocalBlockQueue> list = new ArrayList<LocalBlockQueue>(activeQueues.size() + inactiveQueues.size());
list.addAll(inactiveQueues);
list.addAll(activeQueues);
return list;
}
public List<LocalBlockQueue> getActiveQueues() {
return new ArrayList<>(activeQueues);
}
public List<LocalBlockQueue> getInactiveQueues() {
return new ArrayList<>(inactiveQueues);
}
public void flush(LocalBlockQueue queue) {
SET_TASK.value1 = Long.MAX_VALUE;
SET_TASK.value2 = queue;
if (SET_TASK.value2 == null) {
return;
}
if (PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be flushed on the main thread!");
}
// Disable the async catcher as it can't discern async vs parallel
SET_TASK.value2.startSet(true);
try {
if (PARALLEL_THREADS <= 1) {
SET_TASK.run();
} else {
ArrayList<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < PARALLEL_THREADS; i++) {
threads.add(new Thread(SET_TASK));
}
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
// Enable it again (note that we are still on the main thread)
SET_TASK.value2.endSet(true);
dequeue(queue);
}
}
public LocalBlockQueue getNextQueue() {
long now = System.currentTimeMillis();
while (activeQueues.size() > 0) {
LocalBlockQueue queue = activeQueues.peek();
if (queue != null && queue.size() > 0) {
queue.setModified(now);
return queue;
} else {
activeQueues.poll();
}
}
int size = inactiveQueues.size();
if (size > 0) {
Iterator<LocalBlockQueue> iter = inactiveQueues.iterator();
try {
int total = 0;
LocalBlockQueue firstNonEmpty = null;
while (iter.hasNext()) {
LocalBlockQueue queue = iter.next();
long age = now - queue.getModified();
total += queue.size();
if (queue.size() == 0) {
if (age > 1000) {
iter.remove();
}
continue;
}
if (firstNonEmpty == null) {
firstNonEmpty = queue;
}
if (total > 64) {
firstNonEmpty.setModified(now);
return firstNonEmpty;
}
if (age > 60000) {
queue.setModified(now);
return queue;
}
}
} catch (ConcurrentModificationException e) {
e.printStackTrace();
}
}
return null;
}
public boolean isDone() {
return activeQueues.size() == 0 && inactiveQueues.size() == 0;
}
public boolean addTask(final Runnable whenDone) {
if (this.isDone()) {
// Run
this.tasks();
if (whenDone != null) {
whenDone.run();
}
return true;
}
if (whenDone != null) {
this.runnables.add(whenDone);
}
return false;
}
public synchronized boolean tasks() {
if (this.runnables.isEmpty()) {
return false;
}
final ConcurrentLinkedDeque<Runnable> tmp = new ConcurrentLinkedDeque<>(this.runnables);
this.runnables.clear();
for (final Runnable runnable : tmp) {
runnable.run();
}
return true;
}
}

View File

@ -0,0 +1,105 @@
package com.intellectualcrafters.plot.util.block;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.WorldUtil;
import java.util.Map;
public abstract class LocalBlockQueue {
public LocalBlockQueue(String world) {
// Implement this elsewhere
}
public ScopedLocalBlockQueue getForChunk(int x, int z) {
return new ScopedLocalBlockQueue(this, new Location(getWorld(), x << 4, 0, z << 4), new Location(getWorld(), 15 + (x << 4), 255, 15 + (z << 4)));
}
public abstract boolean next();
public abstract void startSet(boolean parallel);
public abstract void endSet(boolean parallel);
public abstract int size();
public abstract void optimize();
public abstract void setModified(long modified);
public abstract long getModified();
public abstract boolean setBlock(final int x, final int y, final int z, final int id, final int data);
public final boolean setBlock(int x, int y, int z, int id) {
return setBlock(x, y, z, id, 0);
}
public final boolean setBlock(int x, int y, int z, PlotBlock block) {
return setBlock(x, y, z, block.id, block.data);
}
public abstract PlotBlock getBlock(int x, int y, int z);
public abstract boolean setBiome(int x, int z, String biome);
public abstract String getWorld();
public abstract void flush();
public final void setModified() {
setModified(System.currentTimeMillis());
}
public abstract void refreshChunk(int x, int z);
public abstract void fixChunkLighting(int x, int z);
public abstract void regenChunk(int x, int z);
public final void regenChunkSafe(int x, int z) {
regenChunk(x, z);
fixChunkLighting(x, z);
ChunkLoc loc = new ChunkLoc(x, z);
for (Map.Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
Location pLoc = pp.getLocation();
if (!StringMan.isEqual(getWorld(), pLoc.getWorld()) || !pLoc.getChunkLoc().equals(loc)) {
continue;
}
pLoc.setY(WorldUtil.IMP.getHighestBlock(getWorld(), pLoc.getX(), pLoc.getZ()));
pp.teleport(pLoc);
}
}
public void enqueue() {
GlobalBlockQueue.IMP.enqueue(this);
}
public final void setCuboid(Location pos1, Location pos2, PlotBlock block) {
for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
setBlock(x, y, z, block);
}
}
}
}
public final void setCuboid(Location pos1, Location pos2, PlotBlock[] blocks) {
for (int y = pos1.getY(); y <= Math.min(255, pos2.getY()); y++) {
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
for (int z = pos1.getZ(); z <= pos2.getZ(); z++) {
int i = PseudoRandom.random.random(blocks.length);
PlotBlock block = blocks[i];
setBlock(x, y, z, block);
}
}
}
}
}

View File

@ -0,0 +1,24 @@
package com.intellectualcrafters.plot.util.block;
public class OffsetLocalBlockQueue extends DelegateLocalBlockQueue {
private final int ox;
private final int oy;
private final int oz;
public OffsetLocalBlockQueue(LocalBlockQueue parent, int ox, int oy, int oz) {
super(parent);
this.ox = ox;
this.oy = oy;
this.oz = oz;
}
@Override
public boolean setBiome(int x, int y, String biome) {
return super.setBiome(ox + x, oy + y, biome);
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
return super.setBlock(ox + x, oy + y, oz + z, id, data);
}
}

View File

@ -0,0 +1,30 @@
package com.intellectualcrafters.plot.util.block;
public abstract class QueueProvider {
public abstract LocalBlockQueue getNewQueue(String world);
public static QueueProvider of(final Class<? extends LocalBlockQueue> primary, final Class<? extends LocalBlockQueue> fallback) {
return new QueueProvider() {
private boolean failed = false;
@Override
public LocalBlockQueue getNewQueue(String world) {
if (!failed) {
try {
return (LocalBlockQueue) primary.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
e.printStackTrace();
failed = true;
}
}
try {
return (LocalBlockQueue) fallback.getConstructors()[0].newInstance(world);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
};
}
}

View File

@ -0,0 +1,88 @@
package com.intellectualcrafters.plot.util.block;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PlotManager;
import com.intellectualcrafters.plot.object.RunnableVal3;
public class ScopedLocalBlockQueue extends DelegateLocalBlockQueue {
private final int minX;
private final int minY;
private final int minZ;
private final int maxX;
private final int maxY;
private final int maxZ;
public ScopedLocalBlockQueue(LocalBlockQueue parent, Location min, Location max) {
super(parent);
this.minX = min.getX();
this.minY = min.getY();
this.minZ = min.getZ();
this.maxX = max.getX();
this.maxY = max.getY();
this.maxZ = max.getZ();
}
@Override
public boolean setBiome(int x, int z, String biome) {
return x >= minX && x <= maxX && z >= minZ && z <= maxZ && super.setBiome(x + minX, z + minZ, biome);
}
public void fillBiome(String biome) {
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z < maxZ; z++) {
setBiome(x, z, biome);
}
}
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
return x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ && super.setBlock(x + minX, y + minY, z + minZ, id, data);
}
public Location getMin() {
return new Location(getWorld(), minX, minY, minZ);
}
public Location getMax() {
return new Location(getWorld(), maxX, maxY, maxZ);
}
/**
* Run a task for each x,z value corresponding to the plot at that location<br>
* - Plot: The plot at the x,z (may be null)<br>
* - Location: The location in the chunk (y = 0)<br>
* - PlotChunk: Reference to this chunk object<br>
* @param task
*/
public void mapByType2D(RunnableVal3<Plot, Integer, Integer> task) {
int bx = minX;
int bz = minZ;
PlotArea area = PS.get().getPlotArea(getWorld(), null);
Location loc = new Location(getWorld(), bx, 0, bz);
if (area != null) {
PlotManager manager = area.getPlotManager();
for (int x = 0; x < 16; x++) {
loc.setX(bx + x);
for (int z = 0; z < 16; z++) {
loc.setZ(bz + z);
task.run(area.getPlotAbs(loc), x, z);
}
}
} else {
for (int x = 0; x < 16; x++) {
loc.setX(bx + x);
for (int z = 0; z < 16; z++) {
loc.setZ(bz + z);
task.run(loc.getPlotAbs(), x, z);
}
}
}
}
}

View File

@ -215,17 +215,11 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
case 190: case 190:
case 191: case 191:
case 192: case 192:
// if (Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
// SetQueue.IMP.setBlock(this.world, x, y, z, id);
// } else
{ {
super.setBlock(location, block); super.setBlock(location, block);
} }
break; break;
default: default:
// if (Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
// SetQueue.IMP.setBlock(this.world, x, y, z, PlotBlock.get((short) id, (byte) block.getData()));
// } else
{ {
super.setBlock(location, block); super.setBlock(location, block);
} }

View File

@ -20,7 +20,6 @@ apply plugin: 'com.github.johnrengelman.shadow'
dependencies { dependencies {
compile project(':Core') compile project(':Core')
compile 'org.spongepowered:spongeapi:5.0.0-SNAPSHOT' compile 'org.spongepowered:spongeapi:5.0.0-SNAPSHOT'
//compile 'org.mcstats.sponge:metrics:R8-SNAPSHOT'
} }
sourceCompatibility = 1.8 sourceCompatibility = 1.8

View File

@ -20,7 +20,6 @@ import com.intellectualcrafters.plot.util.EconHandler;
import com.intellectualcrafters.plot.util.EventUtil; import com.intellectualcrafters.plot.util.EventUtil;
import com.intellectualcrafters.plot.util.InventoryUtil; import com.intellectualcrafters.plot.util.InventoryUtil;
import com.intellectualcrafters.plot.util.MainUtil; import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SchematicHandler; import com.intellectualcrafters.plot.util.SchematicHandler;
import com.intellectualcrafters.plot.util.SetupUtils; import com.intellectualcrafters.plot.util.SetupUtils;
import com.intellectualcrafters.plot.util.StringMan; import com.intellectualcrafters.plot.util.StringMan;
@ -28,6 +27,7 @@ import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler; import com.intellectualcrafters.plot.util.UUIDHandler;
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation; import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
import com.intellectualcrafters.plot.util.WorldUtil; import com.intellectualcrafters.plot.util.WorldUtil;
import com.intellectualcrafters.plot.util.block.QueueProvider;
import com.intellectualcrafters.plot.uuid.UUIDWrapper; import com.intellectualcrafters.plot.uuid.UUIDWrapper;
import com.plotsquared.sponge.generator.SpongePlotGenerator; import com.plotsquared.sponge.generator.SpongePlotGenerator;
import com.plotsquared.sponge.listener.ChunkProcessor; import com.plotsquared.sponge.listener.ChunkProcessor;
@ -47,11 +47,17 @@ import com.plotsquared.sponge.util.SpongeSetupUtils;
import com.plotsquared.sponge.util.SpongeTaskManager; import com.plotsquared.sponge.util.SpongeTaskManager;
import com.plotsquared.sponge.util.SpongeTitleManager; import com.plotsquared.sponge.util.SpongeTitleManager;
import com.plotsquared.sponge.util.SpongeUtil; import com.plotsquared.sponge.util.SpongeUtil;
import com.plotsquared.sponge.util.block.FastQueue; import com.plotsquared.sponge.util.block.SpongeLocalQueue;
import com.plotsquared.sponge.util.block.SlowQueue;
import com.plotsquared.sponge.uuid.SpongeLowerOfflineUUIDWrapper; import com.plotsquared.sponge.uuid.SpongeLowerOfflineUUIDWrapper;
import com.plotsquared.sponge.uuid.SpongeOnlineUUIDWrapper; import com.plotsquared.sponge.uuid.SpongeOnlineUUIDWrapper;
import com.plotsquared.sponge.uuid.SpongeUUIDHandler; import com.plotsquared.sponge.uuid.SpongeUUIDHandler;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.spongepowered.api.Game; import org.spongepowered.api.Game;
import org.spongepowered.api.Server; import org.spongepowered.api.Server;
@ -63,20 +69,11 @@ import org.spongepowered.api.event.game.state.GameAboutToStartServerEvent;
import org.spongepowered.api.plugin.Plugin; import org.spongepowered.api.plugin.Plugin;
import org.spongepowered.api.plugin.PluginContainer; import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.profile.GameProfileManager; import org.spongepowered.api.profile.GameProfileManager;
import org.spongepowered.api.world.Chunk;
import org.spongepowered.api.world.World; import org.spongepowered.api.world.World;
import org.spongepowered.api.world.gen.GenerationPopulator; import org.spongepowered.api.world.gen.GenerationPopulator;
import org.spongepowered.api.world.gen.WorldGenerator; import org.spongepowered.api.world.gen.WorldGenerator;
import org.spongepowered.api.world.gen.WorldGeneratorModifier; import org.spongepowered.api.world.gen.WorldGeneratorModifier;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
@Plugin(id = "plotsquared", name = "PlotSquared", description = "Easy, yet powerful Plot World generation and management.", @Plugin(id = "plotsquared", name = "PlotSquared", description = "Easy, yet powerful Plot World generation and management.",
url = "https://github.com/IntellectualSites/PlotSquared", version = "3.3.3") url = "https://github.com/IntellectualSites/PlotSquared", version = "3.3.3")
public class SpongeMain implements IPlotMain { public class SpongeMain implements IPlotMain {
@ -364,14 +361,9 @@ public class SpongeMain implements IPlotMain {
} }
@Override @Override
public PlotQueue<Chunk> initPlotQueue() { public QueueProvider initBlockQueue() {
try { MainUtil.canSendChunk = true;
MainUtil.canSendChunk = true; return QueueProvider.of(SpongeLocalQueue.class, null);
return new FastQueue();
} catch (RuntimeException e) {
e.printStackTrace();
}
return new SlowQueue();
} }
@Override @Override

View File

@ -2,19 +2,17 @@ package com.plotsquared.sponge.generator;
import com.flowpowered.math.vector.Vector3i; import com.flowpowered.math.vector.Vector3i;
import com.intellectualcrafters.plot.generator.AugmentedUtils; import com.intellectualcrafters.plot.generator.AugmentedUtils;
import com.intellectualcrafters.plot.object.LazyResult; import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.util.block.DelegateLocalBlockQueue;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.sponge.util.SpongeUtil; import com.plotsquared.sponge.util.SpongeUtil;
import java.util.List;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.world.World; import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.ImmutableBiomeArea; import org.spongepowered.api.world.extent.ImmutableBiomeArea;
import org.spongepowered.api.world.extent.MutableBlockVolume; import org.spongepowered.api.world.extent.MutableBlockVolume;
import org.spongepowered.api.world.gen.GenerationPopulator; import org.spongepowered.api.world.gen.GenerationPopulator;
import org.spongepowered.api.world.gen.WorldGenerator; import org.spongepowered.api.world.gen.WorldGenerator;
import java.util.List;
public class SpongeAugmentedGenerator implements GenerationPopulator { public class SpongeAugmentedGenerator implements GenerationPopulator {
private static SpongeAugmentedGenerator generator; private static SpongeAugmentedGenerator generator;
@ -43,38 +41,28 @@ public class SpongeAugmentedGenerator implements GenerationPopulator {
int bz = min.getZ(); int bz = min.getZ();
int cx = bx >> 4; int cx = bx >> 4;
int cz = bz >> 4; int cz = bz >> 4;
AugmentedUtils.generate(world.getName(), cx, cz, new LazyResult<PlotChunk<?>>() { AugmentedUtils.generate(world.getName(), cx, cz, new DelegateLocalBlockQueue(null) {
@Override @Override
public PlotChunk<?> create() { public boolean setBlock(int x, int y, int z, int id, int data) {
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz); terrain.setBlock(bx + x, y, bz + z, SpongeUtil.getBlockState(id, data));
return new PlotChunk<ChunkWrapper>(wrap) { return true;
@Override }
public ChunkWrapper getChunkAbs() {
return getChunkWrapper(); @Override
} public PlotBlock getBlock(int x, int y, int z) {
@Override BlockState block = terrain.getBlock(bx + x, y, bz + z);
public void setBlock(int x, int y, int z, int id, byte data) { return block == null ? PlotBlock.get(0, 0) : SpongeUtil.getPlotBlock(block);
terrain.setBlock(bx + x, y, bz + z, SpongeUtil.getBlockState(id, data)); }
}
@Override @Override
public void setBiome(int x, int z, int biome) { public boolean setBiome(int x, int z, String biome) {
// TODO FIXME return false; // TODO ?
} }
@Override
public PlotChunk clone() { @Override
throw new UnsupportedOperationException("NOT IMPLEMENTED YET"); public String getWorld() {
} return world.getName();
@Override
public PlotChunk shallowClone() {
throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
}
@Override
public void addToQueue() {}
@Override
public void flush(boolean fixLighting) {}
};
} }
}); });
} }
} }

View File

@ -1,19 +1,17 @@
package com.plotsquared.sponge.generator; package com.plotsquared.sponge.generator;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.ImmutableBiomeArea;
import org.spongepowered.api.world.extent.MutableBlockVolume;
import org.spongepowered.api.world.gen.GenerationPopulator;
import com.flowpowered.math.vector.Vector3i; import com.flowpowered.math.vector.Vector3i;
import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator; import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.object.PlotArea; import com.intellectualcrafters.plot.object.PlotArea;
import com.intellectualcrafters.plot.object.PseudoRandom; import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.ChunkManager; import com.intellectualcrafters.plot.util.ChunkManager;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.sponge.util.block.GenChunk; import com.plotsquared.sponge.util.block.GenChunk;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.ImmutableBiomeArea;
import org.spongepowered.api.world.extent.MutableBlockVolume;
import org.spongepowered.api.world.gen.GenerationPopulator;
public class SpongeTerrainGen implements GenerationPopulator { public class SpongeTerrainGen implements GenerationPopulator {
@ -36,7 +34,7 @@ public class SpongeTerrainGen implements GenerationPopulator {
Vector3i min = terrain.getBlockMin(); Vector3i min = terrain.getBlockMin();
int cx = min.getX() >> 4; int cx = min.getX() >> 4;
int cz = min.getZ() >> 4; int cz = min.getZ() >> 4;
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(worldname, cx, cz); ChunkWrapper wrap = new ChunkWrapper(worldname, cx, cz);
// Create the result object // Create the result object
GenChunk result = new GenChunk(terrain, null, wrap); GenChunk result = new GenChunk(terrain, null, wrap);
// Catch any exceptions // Catch any exceptions

View File

@ -1,5 +1,6 @@
package com.plotsquared.sponge.util; package com.plotsquared.sponge.util;
import com.intellectualcrafters.plot.config.Settings;
import com.intellectualcrafters.plot.object.ConsolePlayer; import com.intellectualcrafters.plot.object.ConsolePlayer;
import com.intellectualcrafters.plot.object.PlotMessage; import com.intellectualcrafters.plot.object.PlotMessage;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
@ -139,7 +140,7 @@ public class SpongeChatManager extends ChatManager<Text.Builder> {
@Override @Override
public void send(PlotMessage plotMessage, PlotPlayer player) { public void send(PlotMessage plotMessage, PlotPlayer player) {
if (player instanceof ConsolePlayer) { if (player instanceof ConsolePlayer || !Settings.Chat.INTERACTIVE) {
player.sendMessage(plotMessage.$(this).build().toPlain()); player.sendMessage(plotMessage.$(this).build().toPlain());
} else { } else {
((SpongePlayer) player).player.sendMessage(plotMessage.$(this).build()); ((SpongePlayer) player).player.sendMessage(plotMessage.$(this).build());

View File

@ -1,60 +1,12 @@
package com.plotsquared.sponge.util; package com.plotsquared.sponge.util;
import com.intellectualcrafters.plot.generator.HybridUtils; import com.intellectualcrafters.plot.generator.HybridUtils;
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.RegionWrapper; import com.intellectualcrafters.plot.object.RegionWrapper;
import com.intellectualcrafters.plot.object.RunnableVal; import com.intellectualcrafters.plot.object.RunnableVal;
import org.spongepowered.api.block.BlockState; import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.world.World;
public class SpongeHybridUtils extends HybridUtils { public class SpongeHybridUtils extends HybridUtils {
@Override
public int checkModified(String worldName, int x1, int x2, int y1, int y2, int z1, int z2, PlotBlock[] blocks) {
World world = SpongeUtil.getWorld(worldName);
int count = 0;
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
for (int z = z1; z <= z2; z++) {
BlockState state = world.getBlock(x, y, z);
PlotBlock block = SpongeUtil.getPlotBlock(state);
boolean same = false;
for (PlotBlock p : blocks) {
if (block.id == p.id) {
same = true;
break;
}
}
if (!same) {
count++;
}
}
}
}
return count;
}
@Override
public int get_ey(String worldName, int sx, int ex, int sz, int ez, int sy) {
World world = SpongeUtil.getWorld(worldName);
int ey = sy;
for (int x = sx; x <= ex; x++) {
for (int z = sz; z <= ez; z++) {
for (int y = sy; y < 256; y++) {
if (y > ey) {
BlockState state = world.getBlock(x, y, z);
if (state.getType() != BlockTypes.AIR) {
ey = y;
}
}
}
}
}
return ey;
}
@Override @Override
public void analyzeRegion(String world, RegionWrapper region, RunnableVal<PlotAnalysis> whenDone) { public void analyzeRegion(String world, RegionWrapper region, RunnableVal<PlotAnalysis> whenDone) {
throw new UnsupportedOperationException("NOT IMPLEMENTED YET"); throw new UnsupportedOperationException("NOT IMPLEMENTED YET");

View File

@ -1,246 +0,0 @@
package com.plotsquared.sponge.util.block;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.sponge.util.SpongeUtil;
import org.spongepowered.api.world.Chunk;
import java.util.Arrays;
public class FastChunk extends PlotChunk<Chunk> {
public char[][] ids;
public short[] count;
public short[] air;
public short[] relight;
public int[][] biomes;
public Chunk chunk;
public FastChunk(ChunkWrapper chunk) {
super(chunk);
this.ids = new char[16][];
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return SpongeUtil.getWorld(loc.world).getChunk(loc.x, 0, loc.z).get();
}
@Override
public Chunk getChunk() {
if (this.chunk == null) {
ChunkWrapper cl = getChunkWrapper();
this.chunk = SpongeUtil.getWorld(cl.world).getChunk(cl.x, 0, cl.z).get();
}
return this.chunk;
}
@Override
public void setChunkWrapper(ChunkWrapper loc) {
super.setChunkWrapper(loc);
this.chunk = null;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
/**
* Get the number of block changes in a specified section.
* @param i
* @return
*/
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
/**
* Get the raw data for a section.
* @param i
* @return
*/
public char[] getIdArray(int i) {
return this.ids[i];
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
char[] vs = this.ids[i];
if (vs == null) {
vs = this.ids[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
}
}
@Override
public PlotChunk clone() {
FastChunk toReturn = new FastChunk(getChunkWrapper());
toReturn.air = this.air.clone();
toReturn.count = this.count.clone();
toReturn.relight = this.relight.clone();
toReturn.ids = new char[this.ids.length][];
for (int i = 0; i < this.ids.length; i++) {
char[] matrix = this.ids[i];
if (matrix != null) {
toReturn.ids[i] = new char[matrix.length];
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
FastChunk toReturn = new FastChunk(getChunkWrapper());
toReturn.air = this.air;
toReturn.count = this.count;
toReturn.relight = this.relight;
toReturn.ids = this.ids;
return toReturn;
}
@Override
public void setBiome(int x, int z, int biome) {
if (this.biomes == null) {
this.biomes = new int[16][16];
}
this.biomes[x][z] = biome;
}
}

View File

@ -1,326 +0,0 @@
package com.plotsquared.sponge.util.block;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.intellectualcrafters.plot.util.TaskManager;
import com.plotsquared.sponge.util.SpongeUtil;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import org.spongepowered.api.world.Chunk;
import org.spongepowered.api.world.World;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class FastQueue extends SlowQueue {
public final SendChunk chunkSender;
public final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
public FastQueue() throws RuntimeException {
TaskManager.runTaskRepeat(new Runnable() {
@Override
public void run() {
if (FastQueue.this.toUpdate.isEmpty()) {
return;
}
int count = 0;
ArrayList<Chunk> chunks = new ArrayList<>();
Iterator<Entry<ChunkWrapper, Chunk>> i = FastQueue.this.toUpdate.entrySet().iterator();
while (i.hasNext() && (count < 128)) {
chunks.add(i.next().getValue());
i.remove();
count++;
}
if (count == 0) {
return;
}
update(chunks);
}
}, 1);
this.chunkSender = new SendChunk();
MainUtil.initCache();
}
public void update(Collection<Chunk> chunks) {
if (chunks.isEmpty()) {
return;
}
if (!MainUtil.canSendChunk) {
for (Chunk chunk : chunks) {
chunk.unloadChunk();
chunk.loadChunk(false);
}
return;
}
try {
this.chunkSender.sendChunk(chunks);
} catch (Throwable e) {
e.printStackTrace();
MainUtil.canSendChunk = false;
}
}
/**
* This should be overridden by any specialized queues.
* @param plotChunk
*/
@Override
public void execute(PlotChunk<Chunk> plotChunk) {
FastChunk fs = (FastChunk) plotChunk;
Chunk spongeChunk = plotChunk.getChunk();
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld();
ChunkWrapper wrapper = plotChunk.getChunkWrapper();
if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, spongeChunk);
}
spongeChunk.loadChunk(true);
try {
boolean flag = !nmsWorld.provider.getHasNoSky();
// Sections
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
// Trim tiles
Set<Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
Iterator<Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
while (iterator.hasNext()) {
Entry<BlockPos, TileEntity> tile = iterator.next();
BlockPos pos = tile.getKey();
int lx = pos.getX() & 15;
int ly = pos.getY();
int lz = pos.getZ() & 15;
int j = MainUtil.CACHE_I[ly][lx][lz];
int k = MainUtil.CACHE_J[ly][lx][lz];
char[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
if (array[k] != 0) {
iterator.remove();
}
}
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
entities[i].clear();
}
}
// Efficiently merge sections
for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) {
continue;
}
char[] newArray = fs.getIdArray(j);
if (newArray == null) {
continue;
}
ExtendedBlockStorage section = sections[j];
if ((section == null) || (fs.getCount(j) >= 4096)) {
section = new ExtendedBlockStorage(j << 4, flag);
//section.setData(newArray); //todo
sections[j] = section;
continue;
}
BlockStateContainer currentArray = section.getData();
boolean fill = true;
for (int k = 0; k < newArray.length; k++) {
char n = newArray[k];
switch (n) {
case 0:
fill = false;
continue;
case 1:
fill = false;
//currentArray[k] = 0; //todo
continue;
default:
//currentArray[k] = n; //todo
continue;
}
}
if (fill) {
fs.setCount(j, Short.MAX_VALUE);
}
}
// Clear
} catch (Throwable e) {
e.printStackTrace();
}
int[][] biomes = fs.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
spongeChunk.setBiome(x, z, SpongeUtil.getBiome(biome));
}
}
}
}
/**
* This should be overridden by any specialized queues.
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new FastChunk(wrap);
}
/**
* This should be overridden by any specialized queues.
* @param pc
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> pc, boolean fixAll) {
try {
FastChunk bc = (FastChunk) pc;
Chunk spongeChunk = bc.getChunk();
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
if (!spongeChunk.isLoaded()) {
if (!spongeChunk.loadChunk(false)) {
return false;
}
} else {
spongeChunk.unloadChunk();
spongeChunk.loadChunk(false);
}
// TODO load adjacent chunks
nmsChunk.generateSkylightMap();
if (bc.getTotalRelight() == 0 && !fixAll) {
return true;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = pc.getX() << 4;
int Z = pc.getZ() << 4;
for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j];
if (section == null) {
continue;
}
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) {
continue;
}
BlockStateContainer array = section.getData();
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.getSerializedSize(); k++) {
int i = 0;
//i = array[k]; //todo
if (i < 16) {
continue;
}
short id = (short) (i >> 4);
switch (id) { // Lighting
default:
if (!fixAll) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
int x = MainUtil.x_loc[j][k];
int y = MainUtil.y_loc[j][k];
int z = MainUtil.z_loc[j][k];
if (isSurrounded(sections, x, y, z)) {
continue;
}
BlockPos pos = new BlockPos(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
}
}
return true;
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z))
&& isSolid(getId(sections, x - 1, y, z))
&& isSolid(getId(sections, x, y, z + 1))
&& isSolid(getId(sections, x, y, z - 1));
}
public boolean isSolid(int i) {
//return i != 0 && Block.getBlockById(i).isOpaqueCube();
throw new UnsupportedOperationException("Unsupported");
}
public int getId(ExtendedBlockStorage[] sections, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1;
}
if (y < 0 || y > 255) {
return 1;
}
int i = MainUtil.CACHE_I[y][x][z];
ExtendedBlockStorage section = sections[i];
if (section == null) {
return 0;
}
BlockStateContainer array = section.getData();
int j = MainUtil.CACHE_J[y][x][z];
//return array[j] >> 4; //todo: fix for 1.9.4
return 0;
}
/**
* This should be overridden by any specialized queues.
* @param world
* @param locations
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locations) {
World spongeWorld = SpongeUtil.getWorld(world);
for (ChunkLoc loc : locations) {
ChunkWrapper wrapper = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
if (!this.toUpdate.containsKey(wrapper)) {
this.toUpdate.put(wrapper, spongeWorld.getChunk(loc.x, 0, loc.z).get());
}
}
}
}

View File

@ -1,58 +1,88 @@
package com.plotsquared.sponge.util.block; package com.plotsquared.sponge.util.block;
import com.intellectualcrafters.plot.util.PlotChunk; import com.intellectualcrafters.plot.object.ChunkWrapper;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper; import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
import com.plotsquared.sponge.util.SpongeUtil; import com.plotsquared.sponge.util.SpongeUtil;
import org.spongepowered.api.world.Chunk; import org.spongepowered.api.world.biome.BiomeType;
import org.spongepowered.api.world.extent.MutableBiomeArea; import org.spongepowered.api.world.extent.MutableBiomeArea;
import org.spongepowered.api.world.extent.MutableBlockVolume; import org.spongepowered.api.world.extent.MutableBlockVolume;
public class GenChunk extends PlotChunk<Chunk> { public class GenChunk extends ScopedLocalBlockQueue {
private final MutableBlockVolume terrain; private final MutableBlockVolume terrain;
private final MutableBiomeArea biome; private final MutableBiomeArea biome;
private final int bz; private final int bz;
private final int bx; private final int bx;
private final String world;
public boolean modified = false; public boolean modified = false;
public GenChunk(MutableBlockVolume terrain, MutableBiomeArea biome, ChunkWrapper wrap) { public GenChunk(MutableBlockVolume terrain, MutableBiomeArea biome, ChunkWrapper wrap) {
super(wrap); super(null, new Location(null, 0, 0, 0), new Location(null, 15, 255, 15));
this.bx = wrap.x << 4; this.bx = wrap.x << 4;
this.bz = wrap.z << 4; this.bz = wrap.z << 4;
this.terrain = terrain; this.terrain = terrain;
this.biome = biome; this.biome = biome;
this.world = wrap.world;
} }
@Override @Override
public Chunk getChunkAbs() { public void fillBiome(String biomeName) {
ChunkWrapper wrap = getChunkWrapper(); if (this.biome == null) {
return SpongeUtil.getWorld(wrap.world).getChunk(wrap.x << 4, 0, wrap.z << 4).orElse(null); return;
} }
BiomeType biome = SpongeUtil.getBiome(biomeName.toUpperCase());
@Override for (int x = 0; x <= 15; x++) {
public void setBiome(int x, int z, int biome) { for (int z = 0; z < 15; z++) {
if (this.biome != null) { this.biome.setBiome(this.bx + x, this.bz + z, biome);
this.biome.setBiome(this.bx + x, this.bz + z, SpongeUtil.getBiome(biome)); }
} }
} }
@Override @Override
public void setBlock(int x, int y, int z, int id, byte data) { public boolean setBiome(int x, int z, String biomeName) {
modified = true;
BiomeType biome = SpongeUtil.getBiome(biomeName.toUpperCase());
this.biome.setBiome(this.bx + x, this.bz + z, biome);
return true;
}
@Override
public boolean setBlock(int x, int y, int z, int id, int data) {
modified = true;
this.terrain.setBlock(this.bx + x, y, this.bz + z, SpongeUtil.getBlockState(id, data)); this.terrain.setBlock(this.bx + x, y, this.bz + z, SpongeUtil.getBlockState(id, data));
return true;
} }
@Override @Override
public void setChunkWrapper(ChunkWrapper loc) { public PlotBlock getBlock(int x, int y, int z) {
super.setChunkWrapper(loc); return SpongeUtil.getPlotBlock(this.terrain.getBlock(this.bx + x, y, this.bz + z));
} }
@Override @Override
public PlotChunk clone() { public String getWorld() {
return this.world;
}
@Override
public Location getMax() {
return new Location(getWorld(), 15 + bx, 255, 15 + bz);
}
@Override
public Location getMin() {
return new Location(getWorld(), bx, 0, bz);
}
public GenChunk clone() {
throw new UnsupportedOperationException("NOT IMPLEMENTED YET"); throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
} }
@Override public GenChunk shallowClone() {
public PlotChunk shallowClone() {
throw new UnsupportedOperationException("NOT IMPLEMENTED YET"); throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
} }
} }

View File

@ -1,108 +0,0 @@
package com.plotsquared.sponge.util.block;
import com.flowpowered.math.vector.Vector3i;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.UUIDHandler;
import com.plotsquared.sponge.object.SpongePlayer;
import com.plotsquared.sponge.util.SpongeUtil;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.play.server.SPacketChunkData;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.world.Chunk;
import org.spongepowered.api.world.World;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
/**
* An utility that can be used to send chunks, rather than using bukkit code to do so (uses heavy NMS)
*
*/
public class SendChunk {
public void sendChunk(Collection<Chunk> input) {
HashSet<Chunk> chunks = new HashSet<Chunk>(input);
HashMap<String, ArrayList<Chunk>> map = new HashMap<>();
for (Chunk chunk : chunks) {
String world = chunk.getWorld().getName();
ArrayList<Chunk> list = map.get(world);
if (list == null) {
list = new ArrayList<>();
map.put(world, list);
}
list.add(chunk);
((net.minecraft.world.chunk.Chunk) chunk).generateSkylightMap();
}
for (Entry<String, PlotPlayer> entry : UUIDHandler.getPlayers().entrySet()) {
PlotPlayer pp = entry.getValue();
Plot plot = pp.getCurrentPlot();
Location loc = null;
String world;
if (plot != null) {
world = plot.getArea().worldname;
} else {
loc = pp.getLocation();
world = loc.getWorld();
}
ArrayList<Chunk> list = map.get(world);
if (list == null) {
continue;
}
if (loc == null) {
loc = pp.getLocation();
}
int cx = loc.getX() >> 4;
int cz = loc.getZ() >> 4;
Player player = ((SpongePlayer) pp).player;
int view = player.getViewDistance();
EntityPlayer nmsPlayer = (EntityPlayer) player;
if (!(nmsPlayer instanceof EntityPlayerMP)) {
PS.debug("Cannot send chunk change to: " + pp.getName());
return;
}
EntityPlayerMP nmsPlayerMP = (EntityPlayerMP) nmsPlayer;
for (Chunk chunk : list) {
Vector3i min = chunk.getBlockMin();
int dx = Math.abs(cx - (min.getX() >> 4));
int dz = Math.abs(cz - (min.getZ() >> 4));
if ((dx > view) || (dz > view)) {
continue;
}
chunks.remove(chunk);
NetHandlerPlayServer con = nmsPlayerMP.connection;
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65535);
con.sendPacket(packet);
}
}
for (Chunk chunk : chunks) {
TaskManager.runTask(new Runnable() {
@Override
public void run() {
chunk.unloadChunk();
}
});
}
}
public void sendChunk(String worldName, List<ChunkLoc> chunkLocations) {
World spongeWorld = SpongeUtil.getWorld(worldName);
ArrayList<Chunk> chunks = new ArrayList<>();
for (ChunkLoc loc : chunkLocations) {
chunks.add(spongeWorld.getChunk(loc.x, 0, loc.z).get());
}
sendChunk(chunks);
}
}

View File

@ -1,65 +0,0 @@
package com.plotsquared.sponge.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.sponge.util.SpongeUtil;
import org.spongepowered.api.world.Chunk;
public class SlowChunk extends PlotChunk<Chunk> {
public PlotBlock[][] result = new PlotBlock[16][];
public int[][] biomes;
private PlotBlock lastBlock;
public SlowChunk(ChunkWrapper chunk) {
super(chunk);
}
@Override
public Chunk getChunkAbs() {
ChunkWrapper loc = getChunkWrapper();
return SpongeUtil.getWorld(loc.world).getChunk(loc.x << 4, 0, loc.z << 4).get();
}
@Override
public void setBiome(int x, int z, int biome) {
if (this.biomes == null) {
this.biomes = new int[16][16];
}
this.biomes[x][z] = biome;
}
@Override
public void setBlock(int x, int y, int z, int id, byte data) {
if (this.result[y >> 4] == null) {
this.result[y >> 4] = new PlotBlock[4096];
}
if (id == this.lastBlock.id && data == this.lastBlock.data) {
this.result[MainUtil.CACHE_I[x][y][z]][MainUtil.CACHE_J[x][y][z]] = this.lastBlock;
} else {
this.result[MainUtil.CACHE_I[x][y][z]][MainUtil.CACHE_J[x][y][z]] = PlotBlock.get((short) id, data);
}
}
@Override
public PlotChunk clone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
for (int i = 0; i < this.result.length; i++) {
PlotBlock[] matrix = this.result[i];
if (matrix != null) {
toReturn.result[i] = new PlotBlock[matrix.length];
System.arraycopy(matrix, 0, toReturn.result[i], 0, matrix.length);
}
}
return toReturn;
}
@Override
public PlotChunk shallowClone() {
SlowChunk toReturn = new SlowChunk(getChunkWrapper());
toReturn.result = this.result;
return toReturn;
}
}

View File

@ -1,226 +0,0 @@
package com.plotsquared.sponge.util.block;
import com.flowpowered.math.vector.Vector3i;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.ChunkLoc;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.PlotChunk;
import com.intellectualcrafters.plot.util.PlotQueue;
import com.intellectualcrafters.plot.util.SetQueue;
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
import com.plotsquared.sponge.util.SpongeUtil;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.world.Chunk;
import org.spongepowered.api.world.World;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
public class SlowQueue implements PlotQueue<Chunk> {
private final ConcurrentHashMap<ChunkWrapper, PlotChunk<Chunk>> blocks = new ConcurrentHashMap<>();
@Override
public boolean setBlock(String world, int x, int y, int z, short id, byte data) {
if (y > 255 || y < 0) {
return false;
}
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, x >> 4, z >> 4);
x = x & 15;
z = z & 15;
PlotChunk<Chunk> result = this.blocks.get(wrap);
if (result == null) {
result = getChunk(wrap);
result.setBlock(x, y, z, id, data);
PlotChunk<Chunk> previous = this.blocks.put(wrap, result);
if (previous == null) {
return true;
}
this.blocks.put(wrap, previous);
result = previous;
}
result.setBlock(x, y, z, id, data);
return true;
}
@Override
public void setChunk(PlotChunk<Chunk> chunk) {
this.blocks.put(chunk.getChunkWrapper(), chunk);
}
@Override
public PlotChunk<Chunk> next() {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (this.blocks.isEmpty()) {
return null;
}
Iterator<Entry<ChunkWrapper, PlotChunk<Chunk>>> iter = this.blocks.entrySet().iterator();
PlotChunk<Chunk> toReturn = iter.next().getValue();
if (SetQueue.IMP.isWaiting()) {
return null;
}
iter.remove();
execute(toReturn);
fixLighting(toReturn, true);
return toReturn;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public PlotChunk<Chunk> next(ChunkWrapper wrap, boolean fixLighting) {
if (!PS.get().isMainThread(Thread.currentThread())) {
throw new IllegalStateException("Must be called from main thread!");
}
try {
if (this.blocks.isEmpty()) {
return null;
}
PlotChunk<Chunk> toReturn = this.blocks.remove(wrap);
if (toReturn == null) {
return null;
}
execute(toReturn);
fixLighting(toReturn, fixLighting);
return toReturn;
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
@Override
public void clear() {
this.blocks.clear();
}
@Override
public void regenerateChunk(String world, ChunkLoc loc) {
World spongeWorld = SpongeUtil.getWorld(world);
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeWorld;
Optional<Chunk> chunkOpt = spongeWorld.getChunk(loc.x, 0, loc.z);
if (chunkOpt.isPresent()) {
try {
Chunk spongeChunk = chunkOpt.get();
IChunkProvider provider = nmsWorld.getChunkProvider();
if (!(provider instanceof ChunkProviderServer)) {
PS.debug("Not valid world generator for: " + world);
}
/* ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
IChunkProvider chunkProvider = chunkServer.serverChunkGenerator;
long pos = ChunkCoordIntPair.chunkXZ2Int(loc.x, loc.z);
net.minecraft.world.chunk.Chunk mcChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
if (chunkServer.chunkExists(loc.x, loc.z)) {
mcChunk = chunkServer.loadChunk(loc.x, loc.z);
mcChunk.onChunkUnload();
}
Field fieldDroppedChunksSet;
try {
fieldDroppedChunksSet = chunkServer.getClass().getField("droppedChunksSet");
} catch (Throwable t) {
fieldDroppedChunksSet = ReflectionUtils.findField(chunkServer.getClass(), Set.class);
}
Set<Long> set = (Set<Long>) fieldDroppedChunksSet.get(chunkServer);
set.remove(pos);
ReflectionUtils.findField(chunkServer.getClass(),)
chunkServer.id2ChunkMap.remove(pos);
mcChunk = chunkProvider.provideChunk(loc.x, loc.z);
chunkServer.id2ChunkMap.add(pos, mcChunk);
chunkServer.loadedChunks.add(mcChunk);
if (mcChunk != null) {
mcChunk.onChunkLoad();
mcChunk.populateChunk(chunkProvider, chunkProvider, loc.x, loc.z);
SetQueue.IMP.queue.sendChunk(world, Arrays.asList(loc));
}
else {
PS.debug("CHUNK IS NULL!?");
}*/
} catch (Throwable e) {
e.printStackTrace();
}
}
}
/**
* This should be overriden by any specialized queues.
* @param plotChunk
*/
public void execute(PlotChunk<Chunk> plotChunk) {
SlowChunk sc = (SlowChunk) plotChunk;
Chunk chunk = plotChunk.getChunk();
chunk.loadChunk(true);
Vector3i min = chunk.getBlockMin();
int bx = min.getX();
int bz = min.getZ();
for (int i = 0; i < sc.result.length; i++) {
PlotBlock[] result2 = sc.result[i];
if (result2 == null) {
continue;
}
for (int j = 0; j < 4096; j++) {
int x = MainUtil.x_loc[i][j];
int y = MainUtil.y_loc[i][j];
int z = MainUtil.z_loc[i][j];
PlotBlock newBlock = result2[j];
BlockState state = SpongeUtil.getBlockState(newBlock.id, newBlock.data);
chunk.setBlock(bx + x, y, bz + z, state, false);
}
}
int[][] biomes = sc.biomes;
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.setBiome(bx + x, bz + z, SpongeUtil.getBiome(biome));
}
}
}
}
/**
* This should be overriden by any specialized queues.
* @param wrap
*/
@Override
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
return new SlowChunk(wrap);
}
/**
* This should be overriden by any specialized queues.
* @param fixAll
*/
@Override
public boolean fixLighting(PlotChunk<Chunk> chunk, boolean fixAll) {
// Do nothing
return true;
}
/**
* This should be overriden by any specialized queues.
* @param locs
*/
@Override
public void sendChunk(String world, Collection<ChunkLoc> locs) {
// Do nothing
}
}

View File

@ -0,0 +1,500 @@
package com.plotsquared.sponge.util.block;
import com.intellectualcrafters.plot.object.PlotBlock;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.intellectualcrafters.plot.util.MainUtil;
import com.intellectualcrafters.plot.util.StringMan;
import com.intellectualcrafters.plot.util.TaskManager;
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
import com.plotsquared.sponge.util.SpongeUtil;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityTracker;
import net.minecraft.entity.EntityTrackerEntry;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.SPacketChunkData;
import net.minecraft.network.play.server.SPacketDestroyEntities;
import net.minecraft.server.management.PlayerChunkMap;
import net.minecraft.util.ClassInheritanceMultiMap;
import net.minecraft.util.IntHashMap;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.biome.BiomeType;
import org.spongepowered.api.world.extent.UnmodifiableBlockVolume;
import org.spongepowered.api.world.extent.worker.MutableBlockVolumeWorker;
import org.spongepowered.api.world.extent.worker.procedure.BlockVolumeMapper;
public class SpongeLocalQueue extends BasicLocalBlockQueue<char[]> {
public SpongeLocalQueue(String world) {
super(world);
}
@Override
public LocalChunk<char[]> getLocalChunk(int x, int z) {
return new CharLocalChunk_Sponge(this, x, z) {
// Custom stuff?
};
}
@Override
public void optimize() {
}
public World getSpongeWorld() {
return SpongeUtil.getWorld(getWorld());
}
@Override
public PlotBlock getBlock(int x, int y, int z) {
World worldObj = getSpongeWorld();
BlockState block = worldObj.getBlock(x, y, z);
if (block == null) {
return PlotBlock.get(0, 0);
}
return SpongeUtil.getPlotBlock(block);
}
@Override
public void refreshChunk(int x, int z) {
World world = getSpongeWorld();
Chunk nmsChunk = ((net.minecraft.world.World) world).getChunkProvider().provideChunk(x, z);
if (nmsChunk == null || !nmsChunk.isLoaded()) {
return;
}
try {
ChunkPos pos = nmsChunk.getChunkCoordIntPair();
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
if (!chunkMap.contains(x, z)) {
return;
}
EntityTracker tracker = w.getEntityTracker();
HashSet<EntityPlayerMP> players = new HashSet<>();
for (EntityPlayer player : w.playerEntities) {
if (player instanceof EntityPlayerMP) {
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
players.add((EntityPlayerMP) player);
}
}
}
if (players.size() == 0) {
return;
}
HashSet<EntityTrackerEntry> entities = new HashSet<>();
ClassInheritanceMultiMap<Entity>[] entitieSlices = nmsChunk.getEntityLists();
IntHashMap<EntityTrackerEntry> entries = null;
for (Field field : tracker.getClass().getDeclaredFields()) {
if (field.getType() == IntHashMap.class) {
field.setAccessible(true);
entries = (IntHashMap<EntityTrackerEntry>) field.get(tracker);
}
}
for (ClassInheritanceMultiMap<Entity> slice : entitieSlices) {
if (slice == null) {
continue;
}
for (Entity ent : slice) {
EntityTrackerEntry entry = entries != null ? entries.lookup(ent.getEntityId()) : null;
if (entry == null) {
continue;
}
entities.add(entry);
SPacketDestroyEntities packet = new SPacketDestroyEntities(ent.getEntityId());
for (EntityPlayerMP player : players) {
player.connection.sendPacket(packet);
}
}
}
// Send chunks
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65535);
for (EntityPlayerMP player : players) {
player.connection.sendPacket(packet);
}
// send ents
for (EntityTrackerEntry entry : entities) {
try {
TaskManager.IMP.taskLater(new Runnable() {
@Override
public void run() {
for (EntityPlayerMP player : players) {
if (entry.isVisibleTo(player)) {
entry.removeFromTrackedPlayers(player);
if (entry.getTrackedEntity() != player) {
entry.updatePlayerEntity(player);
}
}
}
}
}, 2);
} catch (Throwable e) {
e.printStackTrace();
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
public void fixChunkLighting(int x, int z) {
Chunk nmsChunk = getChunk(getSpongeWorld(), x, z);
nmsChunk.generateSkylightMap();
}
public class CharLocalChunk_Sponge extends CharLocalChunk {
public short[] count;
public short[] air;
public short[] relight;
public CharLocalChunk_Sponge(BasicLocalBlockQueue parent, int x, int z) {
super(parent, x, z);
this.count = new short[16];
this.air = new short[16];
this.relight = new short[16];
}
@Override
public void setBlock(int x, int y, int z, int id, int data) {
int i = MainUtil.CACHE_I[y][x][z];
int j = MainUtil.CACHE_J[y][x][z];
char[] vs = this.blocks[i];
if (vs == null) {
vs = this.blocks[i] = new char[4096];
this.count[i]++;
} else if (vs[j] == 0) {
this.count[i]++;
}
switch (id) {
case 0:
this.air[i]++;
vs[j] = (char) 1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
this.relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (char) (id << 4);
return;
case 130:
case 76:
case 62:
this.relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = (char) ((id << 4) + data);
return;
}
}
public char[] getIdArray(int i) {
return this.blocks[i];
}
public int getCount(int i) {
return this.count[i];
}
public int getAir(int i) {
return this.air[i];
}
public void setCount(int i, short value) {
this.count[i] = value;
}
public int getRelight(int i) {
return this.relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0) {
Arrays.fill(this.count, (short) 1);
Arrays.fill(this.relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.relight[i];
}
return total;
}
}
public boolean isSurrounded(char[][] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z))
&& isSolid(getId(sections, x - 1, y, z))
&& isSolid(getId(sections, x, y, z + 1))
&& isSolid(getId(sections, x, y, z - 1));
}
public boolean isSolid(int i) {
return i != 0 && Block.getBlockById(i).isVisuallyOpaque();
}
public int getId(char[][] sections, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1;
}
if (y < 0 || y > 255) {
return 1;
}
int i = MainUtil.CACHE_I[y][x][z];
char[] section = sections[i];
if (section == null) {
return 0;
}
int j = MainUtil.CACHE_I[y][x][z];
int combined = section[j];
return combined >> 4;
}
public boolean fixLighting(CharLocalChunk_Sponge bc, Chunk nmsChunk) {
try {
if (!nmsChunk.isLoaded()) {
return false;
}
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
nmsChunk.generateSkylightMap();
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
int X = bc.getX() << 4;
int Z = bc.getZ() << 4;
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(0, 0, 0);
for (int j = 0; j < sections.length; j++) {
ExtendedBlockStorage section = sections[j];
if (section == null) {
continue;
}
if ((bc.getCount(j) == 0) || ((bc.getCount(j) >= 4096) && (bc.getAir(j) == 0)) || bc.getAir(j) == 4096) {
continue;
}
char[] array = bc.getIdArray(j);
if (array != null) {
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) {
int i = array[k];
if (i < 16) {
continue;
}
short id = (short) (i >> 4);
switch (id) { // Lighting
default:
if ((k & 1) == l) {
l = 1 - l;
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
int x = MainUtil.x_loc[j][k];
int y = MainUtil.y_loc[j][k];
int z = MainUtil.z_loc[j][k];
if (isSurrounded(bc.blocks, x, y, z)) {
continue;
}
pos.setPos(X + x, y, Z + z);
nmsWorld.checkLight(pos);
}
}
}
}
return true;
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
@Override
public final void regenChunk(int x, int z) {
World worldObj = getSpongeWorld();
throw new UnsupportedOperationException("NOT SUPPORTED");
}
@Override
public final void setComponents(LocalChunk<char[]> lc) {
setBlocks(lc);
setBiomes(lc);
}
public Chunk getChunk(World world, int x, int z) {
net.minecraft.world.chunk.Chunk chunk = ((net.minecraft.world.World) world).getChunkProvider().provideChunk(x, z);
if (chunk != null && !chunk.isLoaded()) {
chunk.onChunkLoad();
}
return chunk;
}
private BlockState AIR = BlockTypes.AIR.getDefaultState();
public void setBlocks(LocalChunk<char[]> lc) {
World worldObj = getSpongeWorld();
org.spongepowered.api.world.Chunk spongeChunk = (org.spongepowered.api.world.Chunk) getChunk(worldObj, lc.getX(), lc.getZ());
char[][] ids = ((CharLocalChunk) lc).blocks;
MutableBlockVolumeWorker<? extends org.spongepowered.api.world.Chunk> blockWorker = spongeChunk.getBlockWorker();
blockWorker.map(new BlockVolumeMapper() {
@Override
public BlockState map(UnmodifiableBlockVolume volume, int xx, int y, int zz) {
int x = xx & 15;
int z = zz & 15;
int i = MainUtil.CACHE_I[y][x][z];
char[] array = ids[i];
if (array == null) {
return null;
}
int combinedId = array[MainUtil.CACHE_J[y][x][z]];
switch (combinedId) {
case 0:
return null;
case 1:
return AIR;
default:
int id = combinedId >> 4;
Block block = Block.getBlockById(id);
int data = combinedId & 0xf;
IBlockState ibd;
if (data != 0) {
ibd = block.getStateFromMeta(data);
} else {
ibd = block.getDefaultState();
}
return (BlockState) ibd;
}
}
});
}
public void setBiomes(LocalChunk<char[]> lc) {
if (lc.biomes != null) {
World worldObj = getSpongeWorld();
int bx = lc.getX() << 4;
int bz = lc.getX() << 4;
String last = null;
BiomeType biome = null;
for (int x = 0; x < lc.biomes.length; x++) {
String[] biomes2 = lc.biomes[x];
if (biomes2 != null) {
for (int y = 0; y < biomes2.length; y++) {
String biomeStr = biomes2[y];
if (biomeStr != null) {
if (last == null || !StringMan.isEqual(last, biomeStr)) {
biome = SpongeUtil.getBiome(biomeStr.toUpperCase());
}
worldObj.setBiome(bx, bz, biome);
}
}
}
}
}
}
}

BIN
fanciful-master.zip Normal file

Binary file not shown.