mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2024-11-22 13:16:45 +01:00
Chat / Merge blocks placer / generator
This commit is contained in:
parent
506455ae40
commit
4f0ede646e
@ -16,22 +16,21 @@ import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
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.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
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.
|
||||
@ -140,10 +139,10 @@ public class PlotAPI {
|
||||
|
||||
/**
|
||||
* Get the block/biome set queue
|
||||
* @return SetQueue.IMP
|
||||
* @return GlobalBlockQueue.IMP
|
||||
*/
|
||||
public SetQueue getSetQueue() {
|
||||
return SetQueue.IMP;
|
||||
public GlobalBlockQueue getBlockQueue() {
|
||||
return GlobalBlockQueue.IMP;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,6 @@ import com.intellectualcrafters.plot.util.EconHandler;
|
||||
import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.InventoryUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotQueue;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
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.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.intellectualcrafters.plot.util.block.QueueProvider;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.bukkit.database.plotme.ClassicPlotMeConnector;
|
||||
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.SendChunk;
|
||||
import com.plotsquared.bukkit.util.SetGenCB;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_7;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_8;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_8_3;
|
||||
import com.plotsquared.bukkit.util.block.FastQueue_1_9;
|
||||
import com.plotsquared.bukkit.util.block.SlowQueue;
|
||||
import com.plotsquared.bukkit.util.block.BukkitLocalQueue;
|
||||
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_7;
|
||||
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8;
|
||||
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_8_3;
|
||||
import com.plotsquared.bukkit.util.block.BukkitLocalQueue_1_9;
|
||||
import com.plotsquared.bukkit.uuid.DefaultUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.FileUUIDHandler;
|
||||
import com.plotsquared.bukkit.uuid.LowerOfflineUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.OfflineUUIDWrapper;
|
||||
import com.plotsquared.bukkit.uuid.SQLUUIDHandler;
|
||||
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.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
@ -87,13 +92,6 @@ import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
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 static WorldEdit worldEdit;
|
||||
@ -417,7 +415,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotQueue<Chunk> initPlotQueue() {
|
||||
public QueueProvider initBlockQueue() {
|
||||
try {
|
||||
new SendChunk();
|
||||
MainUtil.canSendChunk = true;
|
||||
@ -426,32 +424,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain
|
||||
MainUtil.canSendChunk = false;
|
||||
}
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 9, 0)) {
|
||||
try {
|
||||
return new FastQueue_1_9();
|
||||
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
return new SlowQueue();
|
||||
}
|
||||
return QueueProvider.of(BukkitLocalQueue_1_9.class, BukkitLocalQueue.class);
|
||||
}
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 8, 3)) {
|
||||
return QueueProvider.of(BukkitLocalQueue_1_8_3.class, BukkitLocalQueue.class);
|
||||
}
|
||||
if (PS.get().checkVersion(getServerVersion(), 1, 8, 0)) {
|
||||
try {
|
||||
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_8.class, BukkitLocalQueue.class);
|
||||
}
|
||||
return QueueProvider.of(BukkitLocalQueue_1_7.class, BukkitLocalQueue.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,93 +9,103 @@ import java.util.Collection;
|
||||
/**
|
||||
* Represents a wrapper around an array class of an arbitrary reference type,
|
||||
* which properly implements "value" hash code and equality functions.
|
||||
* <p>
|
||||
* This class is intended for use as a key to a map.
|
||||
* </p>
|
||||
*
|
||||
* <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.
|
||||
* @author Glen Husman
|
||||
* @see Arrays
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an array wrapper with some elements.
|
||||
* @param elements The elements of the array.
|
||||
*/
|
||||
public ArrayWrapper(E... elements) {
|
||||
setArray(elements);
|
||||
}
|
||||
private E[] _array;
|
||||
|
||||
/**
|
||||
* Converts an iterable element collection to an array of elements.
|
||||
* The iteration order of the specified object will be used as the array element order.
|
||||
* @param list The iterable of objects which will be converted to an array.
|
||||
* @param c The type of the elements of the array.
|
||||
* @return An array of elements in the specified iterable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] toArray(Iterable<? extends T> list, Class<T> c) {
|
||||
int size = -1;
|
||||
if (list instanceof Collection<?>) {
|
||||
@SuppressWarnings("rawtypes") Collection coll = (Collection) list;
|
||||
size = coll.size();
|
||||
}
|
||||
/**
|
||||
* Retrieves a reference to the wrapped array instance.
|
||||
*
|
||||
* @return The array wrapped by this instance.
|
||||
*/
|
||||
public E[] getArray() {
|
||||
return _array;
|
||||
}
|
||||
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
// Ugly hack: Count it ourselves
|
||||
for (@SuppressWarnings("unused") T element : list) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Set this wrapper to wrap a new array instance.
|
||||
*
|
||||
* @param array The new wrapped array.
|
||||
*/
|
||||
public void setArray(E[] array) {
|
||||
Validate.notNull(array, "The array must not be null.");
|
||||
_array = array;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* Determines if this object has a value equivalent to another object.
|
||||
*
|
||||
* @see Arrays#equals(Object[], Object[])
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a reference to the wrapped array instance.
|
||||
* @return The array wrapped by this instance.
|
||||
*/
|
||||
public E[] getArray() {
|
||||
return this.array;
|
||||
}
|
||||
/**
|
||||
* Gets the hash code represented by this objects value.
|
||||
*
|
||||
* @return This object's hash code.
|
||||
* @see Arrays#hashCode(Object[])
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this wrapper to wrap a new array instance.
|
||||
* @param array The new wrapped array.
|
||||
*/
|
||||
public void setArray(E[] array) {
|
||||
Validate.notNull(array, "The array must not be null.");
|
||||
this.array = array;
|
||||
}
|
||||
/**
|
||||
* Converts an iterable element collection to an array of elements.
|
||||
* The iteration order of the specified object will be used as the array element order.
|
||||
*
|
||||
* @param list The iterable of objects which will be converted to an array.
|
||||
* @param c The type of the elements of the array.
|
||||
* @return An array of elements in the specified iterable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] toArray(Iterable<? extends T> list, Class<T> c) {
|
||||
int size = -1;
|
||||
if (list instanceof Collection<?>) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Collection coll = (Collection) list;
|
||||
size = coll.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hash code represented by this objects value.
|
||||
* @see Arrays#hashCode(Object[])
|
||||
* @return This object's hash code.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(this.array);
|
||||
}
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
// Ugly hack: Count it ourselves
|
||||
for (@SuppressWarnings("unused") T element : list) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
T[] result = (T[]) Array.newInstance(c, size);
|
||||
int i = 0;
|
||||
for (T element : list) { // Assumes iteration order is consistent
|
||||
result[i++] = element; // Assign array element at index THEN increment counter
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,11 +9,11 @@ import java.io.IOException;
|
||||
*/
|
||||
interface JsonRepresentedObject {
|
||||
|
||||
/**
|
||||
* Writes the JSON representation of this object to the specified writer.
|
||||
* @param writer The JSON writer which will receive the object.
|
||||
* @throws IOException If an error occurs writing to the stream.
|
||||
*/
|
||||
void writeJson(JsonWriter writer) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes the JSON representation of this object to the specified writer.
|
||||
* @param writer The JSON writer which will receive the object.
|
||||
* @throws IOException If an error occurs writing to the stream.
|
||||
*/
|
||||
public void writeJson(JsonWriter writer) throws IOException;
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
/**
|
||||
* Represents a JSON string value.
|
||||
* Writes by this object will not write name values nor begin/end objects in the JSON stream.
|
||||
@ -14,34 +14,34 @@ import java.util.Map;
|
||||
*/
|
||||
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
|
||||
|
||||
private final String value;
|
||||
private String _value;
|
||||
|
||||
public JsonString(CharSequence value) {
|
||||
this.value = value == null ? null : value.toString();
|
||||
}
|
||||
public JsonString(CharSequence value) {
|
||||
_value = value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
public static JsonString deserialize(Map<String, Object> map) {
|
||||
return new JsonString(map.get("stringValue").toString());
|
||||
}
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.value(getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.value(getValue());
|
||||
}
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
public Map<String, Object> serialize() {
|
||||
HashMap<String, Object> theSingleValue = new HashMap<String, Object>();
|
||||
theSingleValue.put("stringValue", _value);
|
||||
return theSingleValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
HashMap<String, Object> theSingleValue = new HashMap<>();
|
||||
theSingleValue.put("stringValue", this.value);
|
||||
return theSingleValue;
|
||||
}
|
||||
public static JsonString deserialize(Map<String, Object> map) {
|
||||
return new JsonString(map.get("stringValue").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@ package com.plotsquared.bukkit.chat;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
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.ChatColor;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -19,133 +19,137 @@ import java.util.logging.Level;
|
||||
*/
|
||||
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 {
|
||||
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
|
||||
for (ChatColor style : ChatColor.values()) {
|
||||
if (!style.isFormat()) {
|
||||
continue;
|
||||
}
|
||||
MessagePart(final TextualComponent text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
String styleName;
|
||||
switch (style) {
|
||||
case MAGIC:
|
||||
styleName = "obfuscated";
|
||||
break;
|
||||
case UNDERLINE:
|
||||
styleName = "underlined";
|
||||
break;
|
||||
default:
|
||||
styleName = style.name().toLowerCase();
|
||||
break;
|
||||
}
|
||||
MessagePart() {
|
||||
this.text = null;
|
||||
}
|
||||
|
||||
builder.put(style, styleName);
|
||||
}
|
||||
stylesToNames = builder.build();
|
||||
}
|
||||
boolean hasText() {
|
||||
return text != null;
|
||||
}
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(MessagePart.class);
|
||||
}
|
||||
@Override
|
||||
@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) {
|
||||
this.text = text;
|
||||
}
|
||||
static final BiMap<ChatColor, String> stylesToNames;
|
||||
|
||||
MessagePart() {
|
||||
this.text = null;
|
||||
}
|
||||
static {
|
||||
ImmutableBiMap.Builder<ChatColor, String> builder = ImmutableBiMap.builder();
|
||||
for (final ChatColor style : ChatColor.values()) {
|
||||
if (!style.isFormat()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static MessagePart deserialize(Map<String, Object> serialized) {
|
||||
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
|
||||
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
|
||||
part.color = ChatColor.getByChar(serialized.get("color").toString());
|
||||
part.hoverActionName = (String) serialized.get("hoverActionName");
|
||||
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
|
||||
part.clickActionName = (String) serialized.get("clickActionName");
|
||||
part.clickActionData = (String) serialized.get("clickActionData");
|
||||
part.insertionData = (String) serialized.get("insertion");
|
||||
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
|
||||
return part;
|
||||
}
|
||||
String styleName;
|
||||
switch (style) {
|
||||
case MAGIC:
|
||||
styleName = "obfuscated";
|
||||
break;
|
||||
case UNDERLINE:
|
||||
styleName = "underlined";
|
||||
break;
|
||||
default:
|
||||
styleName = style.name().toLowerCase();
|
||||
break;
|
||||
}
|
||||
|
||||
boolean hasText() {
|
||||
return this.text != null;
|
||||
}
|
||||
builder.put(style, styleName);
|
||||
}
|
||||
stylesToNames = builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public MessagePart clone() throws CloneNotSupportedException {
|
||||
MessagePart obj = (MessagePart) super.clone();
|
||||
obj.styles = (ArrayList<ChatColor>) this.styles.clone();
|
||||
if (this.hoverActionData instanceof JsonString) {
|
||||
obj.hoverActionData = new JsonString(((JsonString) this.hoverActionData).getValue());
|
||||
} else if (this.hoverActionData instanceof FancyMessage) {
|
||||
obj.hoverActionData = ((FancyMessage) this.hoverActionData).clone();
|
||||
}
|
||||
obj.translationReplacements = (ArrayList<JsonRepresentedObject>) this.translationReplacements.clone();
|
||||
return obj;
|
||||
public void writeJson(JsonWriter json) {
|
||||
try {
|
||||
json.beginObject();
|
||||
text.writeJson(json);
|
||||
json.name("color").value(color.name().toLowerCase());
|
||||
for (final ChatColor style : styles) {
|
||||
json.name(stylesToNames.get(style)).value(true);
|
||||
}
|
||||
if (clickActionName != null && clickActionData != null) {
|
||||
json.name("clickEvent")
|
||||
.beginObject()
|
||||
.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
|
||||
public void writeJson(JsonWriter json) {
|
||||
try {
|
||||
json.beginObject();
|
||||
this.text.writeJson(json);
|
||||
json.name("color").value(this.color.name().toLowerCase());
|
||||
for (ChatColor style : this.styles) {
|
||||
json.name(stylesToNames.get(style)).value(true);
|
||||
}
|
||||
if ((this.clickActionName != null) && (this.clickActionData != null)) {
|
||||
json.name("clickEvent").beginObject().name("action").value(this.clickActionName).name("value").value(this.clickActionData)
|
||||
.endObject();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public static MessagePart deserialize(Map<String, Object> serialized) {
|
||||
MessagePart part = new MessagePart((TextualComponent) serialized.get("text"));
|
||||
part.styles = (ArrayList<ChatColor>) serialized.get("styles");
|
||||
part.color = ChatColor.getByChar(serialized.get("color").toString());
|
||||
part.hoverActionName = (String) serialized.get("hoverActionName");
|
||||
part.hoverActionData = (JsonRepresentedObject) serialized.get("hoverActionData");
|
||||
part.clickActionName = (String) serialized.get("clickActionName");
|
||||
part.clickActionData = (String) serialized.get("clickActionData");
|
||||
part.insertionData = (String) serialized.get("insertion");
|
||||
part.translationReplacements = (ArrayList<JsonRepresentedObject>) serialized.get("translationReplacements");
|
||||
return part;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
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;
|
||||
}
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(MessagePart.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
package com.plotsquared.bukkit.chat;
|
||||
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@ -15,191 +14,205 @@ import java.util.Map;
|
||||
*/
|
||||
public final class Reflection {
|
||||
|
||||
/**
|
||||
* Stores loaded classes from the {@code net.minecraft.server} package.
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<>();
|
||||
/**
|
||||
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<>();
|
||||
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<>();
|
||||
/**
|
||||
* Contains loaded methods in a cache.
|
||||
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
|
||||
*/
|
||||
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<>();
|
||||
private static String _versionString;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
private Reflection() { }
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this
|
||||
* method simultaneously).
|
||||
* @param className The name of the class, excluding the package, within NMS.
|
||||
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public static synchronized Class<?> getNMSClass(String className) {
|
||||
if (_loadedNMSClasses.containsKey(className)) {
|
||||
return _loadedNMSClasses.get(className);
|
||||
}
|
||||
/**
|
||||
* Gets the version string from the package name of the CraftBukkit server implementation.
|
||||
* This is needed to bypass the JAR package name changing on each update.
|
||||
*
|
||||
* @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
|
||||
*/
|
||||
public synchronized static String getVersion() {
|
||||
if (_versionString == null) {
|
||||
if (Bukkit.getServer() == null) {
|
||||
// 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;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
_loadedNMSClasses.put(className, null);
|
||||
return null;
|
||||
}
|
||||
_loadedNMSClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
return _versionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this
|
||||
* method simultaneously).
|
||||
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory
|
||||
* .CraftItemStack}.
|
||||
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public static synchronized Class<?> getOBCClass(String className) {
|
||||
if (_loadedOBCClasses.containsKey(className)) {
|
||||
return _loadedOBCClasses.get(className);
|
||||
}
|
||||
/**
|
||||
* Stores loaded classes from the {@code net.minecraft.server} package.
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<String, Class<?>>();
|
||||
|
||||
String fullName = "org.bukkit.craftbukkit." + getVersion() + '.' + className;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
_loadedOBCClasses.put(className, null);
|
||||
return null;
|
||||
}
|
||||
_loadedOBCClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
/**
|
||||
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<String, Class<?>>();
|
||||
|
||||
/**
|
||||
* Attempts to get the NMS handle of a CraftBukkit object.
|
||||
* <p>
|
||||
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the
|
||||
* runtime type of the specified object.
|
||||
* </p>
|
||||
* @param obj The object for which to retrieve an NMS handle.
|
||||
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
|
||||
*/
|
||||
public static synchronized Object getHandle(Object obj) {
|
||||
try {
|
||||
return getMethod(obj.getClass(), "getHandle").invoke(obj);
|
||||
} catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
|
||||
*
|
||||
* @param className The name of the class, excluding the package, within NMS.
|
||||
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getNMSClass(String className) {
|
||||
if (_loadedNMSClasses.containsKey(className)) {
|
||||
return _loadedNMSClasses.get(className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
|
||||
* Java access modifiers are ignored during this retrieval.
|
||||
* No guarantee is made as to whether the field returned will be an
|
||||
* instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
|
||||
* no field will be reflectively looked up twice.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a field is deemed suitable for return,
|
||||
* {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* </p>
|
||||
* @param clazz The class which contains the field to retrieve.
|
||||
* @param name The declared name of the field in the class.
|
||||
* @return A field object with the specified name declared by the specified class.
|
||||
* @see Class#getDeclaredField(String)
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
}
|
||||
String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
_loadedNMSClasses.put(className, null);
|
||||
return null;
|
||||
}
|
||||
_loadedNMSClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 static synchronized Method getMethod(Class<?> clazz, String name, Class<?>... args) {
|
||||
if (!_loadedMethods.containsKey(clazz)) {
|
||||
_loadedMethods.put(clazz, new HashMap<String, Map<ArrayWrapper<Class<?>>, Method>>());
|
||||
}
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
|
||||
*
|
||||
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory.CraftItemStack}.
|
||||
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getOBCClass(String className) {
|
||||
if (_loadedOBCClasses.containsKey(className)) {
|
||||
return _loadedOBCClasses.get(className);
|
||||
}
|
||||
|
||||
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz);
|
||||
if (!loadedMethodNames.containsKey(name)) {
|
||||
loadedMethodNames.put(name, new HashMap<ArrayWrapper<Class<?>>, Method>());
|
||||
}
|
||||
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
|
||||
Class<?> clazz = null;
|
||||
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);
|
||||
if (loadedSignatures.containsKey(wrappedArg)) {
|
||||
return loadedSignatures.get(wrappedArg);
|
||||
}
|
||||
/**
|
||||
* Attempts to get the NMS handle of a CraftBukkit object.
|
||||
* <p>
|
||||
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the runtime type of the specified object.
|
||||
* </p>
|
||||
*
|
||||
* @param obj The object for which to retrieve an NMS handle.
|
||||
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
|
||||
*/
|
||||
public synchronized static Object getHandle(Object obj) {
|
||||
try {
|
||||
return getMethod(obj.getClass(), "getHandle").invoke(obj);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<Class<?>, Map<String, Field>>();
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
|
||||
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
|
||||
* returned will be an instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
|
||||
* no field will be reflectively looked up twice.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a field is deemed suitable for return, {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* </p>
|
||||
*
|
||||
* @param clazz The class which contains the field to retrieve.
|
||||
* @param name The declared name of the field in the class.
|
||||
* @return A field object with the specified name declared by the specified class.
|
||||
* @see Class#getDeclaredField(String)
|
||||
*/
|
||||
public synchronized static Field getField(Class<?> clazz, String name) {
|
||||
Map<String, Field> loaded;
|
||||
if (!_loadedFields.containsKey(clazz)) {
|
||||
loaded = new HashMap<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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package com.plotsquared.bukkit.chat;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerializable;
|
||||
import com.intellectualcrafters.configuration.serialization.ConfigurationSerialization;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
@ -18,285 +18,280 @@ import java.util.Map;
|
||||
*/
|
||||
public abstract class TextualComponent implements Cloneable {
|
||||
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
|
||||
}
|
||||
static {
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ArbitraryTextTypeComponent.class);
|
||||
ConfigurationSerialization.registerClass(TextualComponent.ComplexTextTypeComponent.class);
|
||||
}
|
||||
|
||||
static TextualComponent deserialize(Map<String, Object> map) {
|
||||
if (map.containsKey("key") && (map.size() == 2) && map.containsKey("value")) {
|
||||
// Arbitrary text component
|
||||
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);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReadableString();
|
||||
}
|
||||
|
||||
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.
|
||||
* 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);
|
||||
}
|
||||
/**
|
||||
* Writes the text data represented by this textual component to the specified JSON writer object.
|
||||
* A new object within the writer is not started.
|
||||
*
|
||||
* @param writer The object to which to write the JSON data.
|
||||
* @throws IOException If an error occurs while writing to the stream.
|
||||
*/
|
||||
public abstract void writeJson(JsonWriter writer) throws IOException;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
static TextualComponent deserialize(Map<String, Object> map) {
|
||||
if (map.containsKey("key") && map.size() == 2 && map.containsKey("value")) {
|
||||
// Arbitrary text component
|
||||
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);
|
||||
}
|
||||
|
||||
private static void throwUnsupportedSnapshot() {
|
||||
throw new UnsupportedOperationException("This feature is only supported in snapshot releases.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* 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 isTextKey(String key) {
|
||||
return key.equals("translate") || key.equals("text") || key.equals("score") || key.equals("selector");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* 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
|
||||
static boolean isTranslatableText(TextualComponent component) {
|
||||
return component instanceof ComplexTextTypeComponent && ((ComplexTextTypeComponent) component).getKey().equals("translate");
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
/**
|
||||
* Create a textual component representing a player name, retrievable by using a standard minecraft selector.
|
||||
* 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
|
||||
public ArbitraryTextTypeComponent(String key, String value) {
|
||||
setKey(key);
|
||||
setValue(value);
|
||||
}
|
||||
|
||||
return new ArbitraryTextTypeComponent("selector", selector);
|
||||
}
|
||||
@Override
|
||||
public String getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReadableString();
|
||||
}
|
||||
public void setKey(String key) {
|
||||
Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
|
||||
_key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The JSON key used to represent text components of this type.
|
||||
*/
|
||||
public abstract String getKey();
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A readable String
|
||||
*/
|
||||
public abstract String getReadableString();
|
||||
public void setValue(String value) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
_value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private String _key;
|
||||
private String _value;
|
||||
|
||||
/**
|
||||
* Writes the text data represented by this textual component to the specified JSON writer object.
|
||||
* A new object within the writer is not started.
|
||||
* @param writer The object to which to write the JSON data.
|
||||
* @throws IOException If an error occurs while writing to the stream.
|
||||
*/
|
||||
public abstract void writeJson(JsonWriter writer) throws IOException;
|
||||
@Override
|
||||
public TextualComponent clone() throws CloneNotSupportedException {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ArbitraryTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.name(getKey()).value(getValue());
|
||||
}
|
||||
|
||||
private String _key;
|
||||
private String _value;
|
||||
@SuppressWarnings("serial")
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<String, Object>() {{
|
||||
put("key", getKey());
|
||||
put("value", getValue());
|
||||
}};
|
||||
}
|
||||
|
||||
public ArbitraryTextTypeComponent(String key, String value) {
|
||||
setKey(key);
|
||||
setValue(value);
|
||||
}
|
||||
public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) {
|
||||
return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString());
|
||||
}
|
||||
|
||||
public static ArbitraryTextTypeComponent deserialize(Map<String, Object> map) {
|
||||
return new ArbitraryTextTypeComponent(map.get("key").toString(), map.get("value").toString());
|
||||
}
|
||||
@Override
|
||||
public String getReadableString() {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return this._key;
|
||||
}
|
||||
/**
|
||||
* Internal class used to represent a text component with a nested JSON value.
|
||||
* Exception validating done is on keys and values.
|
||||
*/
|
||||
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
|
||||
|
||||
public void setKey(String key) {
|
||||
Preconditions.checkArgument((key != null) && !key.isEmpty(), "The key must be specified.");
|
||||
this._key = key;
|
||||
}
|
||||
public ComplexTextTypeComponent(String key, Map<String, String> values) {
|
||||
setKey(key);
|
||||
setValue(values);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this._value;
|
||||
}
|
||||
@Override
|
||||
public String getKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
this._value = value;
|
||||
}
|
||||
public void setKey(String key) {
|
||||
Preconditions.checkArgument(key != null && !key.isEmpty(), "The key must be specified.");
|
||||
_key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextualComponent clone() {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ArbitraryTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
public Map<String, String> getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.name(getKey()).value(getValue());
|
||||
}
|
||||
public void setValue(Map<String, String> value) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
_value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("serial")
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<String, Object>() {
|
||||
{
|
||||
put("key", getKey());
|
||||
put("value", getValue());
|
||||
}
|
||||
};
|
||||
}
|
||||
private String _key;
|
||||
private Map<String, String> _value;
|
||||
|
||||
@Override
|
||||
public String getReadableString() {
|
||||
return getValue();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public TextualComponent clone() throws CloneNotSupportedException {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ComplexTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class used to represent a text component with a nested JSON value.
|
||||
* Exception validating done is on keys and values.
|
||||
*/
|
||||
private static final class ComplexTextTypeComponent extends TextualComponent implements ConfigurationSerializable {
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.name(getKey());
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, String> jsonPair : _value.entrySet()) {
|
||||
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
|
||||
}
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
private String _key;
|
||||
private Map<String, String> _value;
|
||||
@SuppressWarnings("serial")
|
||||
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) {
|
||||
setKey(key);
|
||||
setValue(values);
|
||||
}
|
||||
public static ComplexTextTypeComponent deserialize(Map<String, Object> map) {
|
||||
String key = null;
|
||||
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) {
|
||||
String key = null;
|
||||
Map<String, String> value = new HashMap<>();
|
||||
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 getReadableString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return this._key;
|
||||
}
|
||||
/**
|
||||
* Create a textual component representing a string literal.
|
||||
* 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) {
|
||||
Preconditions.checkArgument(value != null, "The value must be specified.");
|
||||
this._value = value;
|
||||
}
|
||||
private static void throwUnsupportedSnapshot() {
|
||||
throw new UnsupportedOperationException("This feature is only supported in snapshot releases.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextualComponent clone() {
|
||||
// Since this is a private and final class, we can just reinstantiate this class instead of casting super.clone
|
||||
return new ComplexTextTypeComponent(getKey(), getValue());
|
||||
}
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.name(getKey());
|
||||
writer.beginObject();
|
||||
for (Map.Entry<String, String> jsonPair : this._value.entrySet()) {
|
||||
writer.name(jsonPair.getKey()).value(jsonPair.getValue());
|
||||
}
|
||||
writer.endObject();
|
||||
}
|
||||
/**
|
||||
* Create a textual component representing a scoreboard value.
|
||||
* 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
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("serial")
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<String, Object>() {
|
||||
{
|
||||
put("key", getKey());
|
||||
for (Map.Entry<String, String> valEntry : getValue().entrySet()) {
|
||||
put("value." + valEntry.getKey(), valEntry.getValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return new ComplexTextTypeComponent("score", ImmutableMap.<String, String>builder()
|
||||
.put("name", playerName)
|
||||
.put("objective", scoreboardObjective)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReadableString() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a textual component representing a player name, retrievable by using a standard minecraft selector.
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import com.intellectualcrafters.plot.generator.GeneratorWrapper;
|
||||
import com.intellectualcrafters.plot.generator.HybridGen;
|
||||
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
|
||||
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.PlotId;
|
||||
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.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
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.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.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
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> {
|
||||
|
||||
private final PlotChunk<Chunk> chunkSetter;
|
||||
private final GenChunk chunkSetter;
|
||||
private final PseudoRandom random = new PseudoRandom();
|
||||
private final IndependentPlotGenerator plotGenerator;
|
||||
private final List<BlockPopulator> populators = new ArrayList<>();
|
||||
@ -46,14 +49,20 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
|
||||
this.plotGenerator = generator;
|
||||
this.platformGenerator = this;
|
||||
this.populators.add(new BlockPopulator() {
|
||||
|
||||
private LocalBlockQueue queue;
|
||||
|
||||
@Override
|
||||
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());
|
||||
byte[][] resultData;
|
||||
if (!BukkitPlotGenerator.this.dataMap.containsKey(loc)) {
|
||||
GenChunk result = (GenChunk) BukkitPlotGenerator.this.chunkSetter;
|
||||
GenChunk result = BukkitPlotGenerator.this.chunkSetter;
|
||||
// Set the chunk location
|
||||
result.setChunkWrapper(SetQueue.IMP.new ChunkWrapper(world.getName(), loc.x, loc.z));
|
||||
result.setChunk(c);
|
||||
// Set the result data
|
||||
result.result = new short[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;
|
||||
PlotArea area = PS.get().getPlotArea(world.getName(), null);
|
||||
SetQueue.ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(area.worldname, c.getX(), c.getZ());
|
||||
PlotChunk<?> chunk = SetQueue.IMP.queue.getChunk(wrap);
|
||||
ChunkWrapper wrap = new ChunkWrapper(area.worldname, c.getX(), c.getZ());
|
||||
ScopedLocalBlockQueue chunk = queue.getForChunk(wrap.x, wrap.z);
|
||||
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
|
||||
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);
|
||||
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() {
|
||||
@Override
|
||||
public void setBiome(int x, int z, Biome biome) {
|
||||
result.setBiome(x, z, biome.ordinal());
|
||||
result.setBiome(x, z, biome.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,13 +151,13 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
|
||||
};
|
||||
try {
|
||||
// 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) {
|
||||
return;
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
// 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) {
|
||||
for (int i = 0; i < tmp.length; i++) {
|
||||
short[] section = tmp[i];
|
||||
@ -170,11 +182,11 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
GenChunk result = (GenChunk) this.chunkSetter;
|
||||
// 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
|
||||
result.cd = createChunkData(world);
|
||||
result.grid = grid;
|
||||
@ -266,7 +278,7 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap
|
||||
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
|
||||
if (!this.loaded) {
|
||||
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) {
|
||||
GenChunk result = (GenChunk) this.chunkSetter;
|
||||
// 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
|
||||
result.result = new short[16][];
|
||||
result.result_data = new byte[16][];
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.plotsquared.bukkit.util;
|
||||
|
||||
import com.intellectualcrafters.plot.config.C;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.ConsolePlayer;
|
||||
import com.intellectualcrafters.plot.object.PlotMessage;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
@ -45,7 +46,7 @@ public class BukkitChatManager extends ChatManager<FancyMessage> {
|
||||
|
||||
@Override
|
||||
public void send(PlotMessage plotMessage, PlotPlayer player) {
|
||||
if (player instanceof ConsolePlayer) {
|
||||
if (player instanceof ConsolePlayer || !Settings.Chat.INTERACTIVE) {
|
||||
player.sendMessage(plotMessage.$(this).toOldMessageFormat());
|
||||
} else {
|
||||
plotMessage.$(this).send(((BukkitPlayer) player).player);
|
||||
|
@ -9,17 +9,22 @@ import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotLoc;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
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.UUIDHandler;
|
||||
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.block.ScopedLocalBlockQueue;
|
||||
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.Chunk;
|
||||
import org.bukkit.DyeColor;
|
||||
@ -52,16 +57,6 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
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 static boolean isIn(RegionWrapper region, int x, int z) {
|
||||
@ -91,6 +86,9 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
String worldName1 = world1.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 z = Math.max(r1.minZ, sz); z <= Math.min(r1.maxZ, sz + 15); z++) {
|
||||
map.saveBlocks(world1, 256, sx, sz, relX, relZ, false);
|
||||
@ -105,24 +103,26 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
byte data2 = block2.getData();
|
||||
if (id1 == 0) {
|
||||
if (id2 != 0) {
|
||||
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) id2, data2);
|
||||
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) 0, (byte) 0);
|
||||
queue1.setBlock(x, y, z, (short) id2, data2);
|
||||
queue2.setBlock(xx, y, zz, (short) 0, (byte) 0);
|
||||
}
|
||||
} else if (id2 == 0) {
|
||||
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) 0, (byte) 0);
|
||||
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) id1, data1);
|
||||
queue1.setBlock(x, y, z, (short) 0, (byte) 0);
|
||||
queue2.setBlock(xx, y, zz, (short) id1, data1);
|
||||
} else if (id1 == id2) {
|
||||
if (data1 != data2) {
|
||||
block1.setData(data2);
|
||||
block2.setData(data1);
|
||||
}
|
||||
} else {
|
||||
SetQueue.IMP.setBlock(worldName1, x, y, z, (short) id2, data2);
|
||||
SetQueue.IMP.setBlock(worldName2, xx, y, zz, (short) id1, data1);
|
||||
queue1.setBlock(x, y, z, (short) id2, data2);
|
||||
queue2.setBlock(xx, y, zz, (short) id1, data1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
queue1.enqueue();
|
||||
queue2.enqueue();
|
||||
return map;
|
||||
}
|
||||
|
||||
@ -138,22 +138,6 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
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
|
||||
public boolean copyRegion(Location pos1, Location pos2, Location newPos, final Runnable whenDone) {
|
||||
final int relX = newPos.getX() - pos1.getX();
|
||||
@ -166,6 +150,7 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
final String newWorldName = newWorld.getName();
|
||||
List<ChunkLoc> chunks = new ArrayList<>();
|
||||
final ContentMap map = new ContentMap();
|
||||
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(newWorldName, false);
|
||||
ChunkManager.chunkTask(pos1, pos2, new RunnableVal<int[]>() {
|
||||
@Override
|
||||
public void run(int[] value) {
|
||||
@ -193,11 +178,12 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
for (int y = 0; y < blocks.length; y++) {
|
||||
PlotBlock block = blocks[y];
|
||||
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
|
||||
public void run() {
|
||||
map.restoreBlocks(newWorld, 0, 0);
|
||||
@ -247,12 +233,13 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
if (!chunkObj.load(false)) {
|
||||
continue;
|
||||
}
|
||||
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
|
||||
RegionWrapper currentPlotClear = new RegionWrapper(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ());
|
||||
if (xxb >= p1x && xxt <= p2x && zzb >= p1z && zzt <= p2z) {
|
||||
AugmentedUtils.bypass(ignoreAugment, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
regenerateChunk(world, chunk);
|
||||
queue.regenChunkSafe(chunk.x, chunk.z);
|
||||
}
|
||||
});
|
||||
continue;
|
||||
@ -320,13 +307,12 @@ public class BukkitChunkManager extends ChunkManager {
|
||||
AugmentedUtils.bypass(ignoreAugment, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setChunkInPlotArea(null, new RunnableVal<PlotChunk<?>>() {
|
||||
setChunkInPlotArea(null, new RunnableVal<ScopedLocalBlockQueue>() {
|
||||
@Override
|
||||
public void run(PlotChunk<?> value) {
|
||||
int cx = value.getX();
|
||||
int cz = value.getZ();
|
||||
int bx = cx << 4;
|
||||
int bz = cz << 4;
|
||||
public void run(ScopedLocalBlockQueue value) {
|
||||
Location min = value.getMin();
|
||||
int bx = min.getX();
|
||||
int bz = min.getZ();
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; 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));
|
||||
}
|
||||
}
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ContentMap map : maps) {
|
||||
|
@ -2,7 +2,6 @@ package com.plotsquared.bukkit.util;
|
||||
|
||||
import com.intellectualcrafters.plot.generator.HybridUtils;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
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.MathMan;
|
||||
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.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
import org.bukkit.material.Directional;
|
||||
import org.bukkit.material.MaterialData;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
|
||||
public class BukkitHybridUtils extends HybridUtils {
|
||||
|
||||
@Override
|
||||
@ -42,6 +42,7 @@ public class BukkitHybridUtils extends HybridUtils {
|
||||
TaskManager.runTaskAsync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
|
||||
final World worldObj = Bukkit.getWorld(world);
|
||||
final ChunkGenerator gen = worldObj.getGenerator();
|
||||
if (gen == null) {
|
||||
@ -254,10 +255,10 @@ public class BukkitHybridUtils extends HybridUtils {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
int zz = cbz + z;
|
||||
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 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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)));
|
||||
}
|
||||
}
|
@ -1,47 +1,44 @@
|
||||
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.ChunkWrapper;
|
||||
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.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.ReflectionUtils;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
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.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
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;
|
||||
private final RefClass classBlock = getRefClass("{nms}.Block");
|
||||
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
|
||||
private final RefClass classIBlockData = getRefClass("{nms}.IBlockData");
|
||||
private final RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
private final RefClass classWorld = getRefClass("{nms}.World");
|
||||
private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
|
||||
import static com.intellectualcrafters.plot.util.ReflectionUtils.getRefClass;
|
||||
|
||||
public class BukkitLocalQueue_1_8 extends BukkitLocalQueue<PlotBlock[]> {
|
||||
|
||||
private final ReflectionUtils.RefMethod methodInitLighting;
|
||||
private final ReflectionUtils.RefClass classBlock = getRefClass("{nms}.Block");
|
||||
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 RefMethod methodGetHandle;
|
||||
private final RefMethod methodGetChunkAt;
|
||||
private final RefMethod methodA;
|
||||
private final RefMethod methodGetByCombinedId;
|
||||
private final RefConstructor constructorBlockPosition;
|
||||
private final ReflectionUtils.RefMethod methodGetHandle;
|
||||
private final ReflectionUtils.RefMethod methodGetChunkAt;
|
||||
private final ReflectionUtils.RefMethod methodA;
|
||||
private final ReflectionUtils.RefMethod methodGetByCombinedId;
|
||||
private final ReflectionUtils.RefConstructor constructorBlockPosition;
|
||||
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.constructorBlockPosition = this.classBlockPosition.getConstructor(int.class, int.class, 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() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (FastQueue_1_8.this.toUpdate.isEmpty()) {
|
||||
if (BukkitLocalQueue_1_8.this.toUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
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) {
|
||||
chunks.add(i.next().getValue());
|
||||
i.remove();
|
||||
@ -72,44 +69,25 @@ public class FastQueue_1_8 extends SlowQueue {
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
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);
|
||||
}
|
||||
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];
|
||||
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;
|
||||
}
|
||||
@ -329,55 +307,31 @@ public class FastQueue_1_8 extends SlowQueue {
|
||||
this.methodA.of(chunk).call(pos, combined);
|
||||
}
|
||||
}
|
||||
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]);
|
||||
}
|
||||
fixChunkLighting(lc.getX(), lc.getZ());
|
||||
}
|
||||
|
||||
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 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) {
|
||||
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);
|
||||
public void refreshChunk(int x, int z) {
|
||||
update(Arrays.asList(Bukkit.getWorld(getWorld()).getChunkAt(x, z)));
|
||||
}
|
||||
}
|
@ -1,66 +1,62 @@
|
||||
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.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
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.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.ReflectionUtils;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
|
||||
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.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Map;
|
||||
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 HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
|
||||
private final RefMethod methodGetHandleChunk;
|
||||
private final RefMethod methodGetHandleWorld;
|
||||
private final RefMethod methodInitLighting;
|
||||
private final RefConstructor classBlockPositionConstructor;
|
||||
private final RefConstructor classChunkSectionConstructor;
|
||||
private final RefMethod methodX;
|
||||
private final RefMethod methodAreNeighborsLoaded;
|
||||
private final RefField fieldSections;
|
||||
private final RefField fieldWorld;
|
||||
private final RefMethod methodGetIdArray;
|
||||
private final RefMethod methodGetWorld;
|
||||
private final RefField tileEntityListTick;
|
||||
private final ReflectionUtils.RefMethod methodGetHandleChunk;
|
||||
private final ReflectionUtils.RefMethod methodGetHandleWorld;
|
||||
private final ReflectionUtils.RefMethod methodInitLighting;
|
||||
private final ReflectionUtils.RefConstructor classBlockPositionConstructor;
|
||||
private final ReflectionUtils.RefConstructor classChunkSectionConstructor;
|
||||
private final ReflectionUtils.RefMethod methodX;
|
||||
private final ReflectionUtils.RefMethod methodAreNeighborsLoaded;
|
||||
private final ReflectionUtils.RefField fieldSections;
|
||||
private final ReflectionUtils.RefField fieldWorld;
|
||||
private final ReflectionUtils.RefMethod methodGetIdArray;
|
||||
private final ReflectionUtils.RefMethod methodGetWorld;
|
||||
private final ReflectionUtils.RefField tileEntityListTick;
|
||||
|
||||
public FastQueue_1_8_3() throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
|
||||
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
|
||||
public BukkitLocalQueue_1_8_3(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
|
||||
super(world);
|
||||
ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
ReflectionUtils.RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
|
||||
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
|
||||
RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
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);
|
||||
RefClass classWorld = getRefClass("{nms}.World");
|
||||
ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
|
||||
this.methodX = classWorld.getMethod("x", classBlockPosition.getRealClass());
|
||||
this.fieldSections = classChunk.getField("sections");
|
||||
this.fieldWorld = classChunk.getField("world");
|
||||
RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
|
||||
ReflectionUtils.RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
|
||||
this.methodGetIdArray = classChunkSection.getMethod("getIdArray");
|
||||
this.methodAreNeighborsLoaded = classChunk.getMethod("areNeighborsLoaded", int.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() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (FastQueue_1_8_3.this.toUpdate.isEmpty()) {
|
||||
if (BukkitLocalQueue_1_8_3.this.toUpdate.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int count = 0;
|
||||
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) {
|
||||
chunks.add(i.next().getValue());
|
||||
i.remove();
|
||||
@ -91,42 +87,184 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
MainUtil.initCache();
|
||||
}
|
||||
|
||||
public void update(Collection<Chunk> chunks) {
|
||||
if (chunks.isEmpty()) {
|
||||
return;
|
||||
@Override
|
||||
public LocalChunk<char[]> getLocalChunk(int x, int z) {
|
||||
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) {
|
||||
chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ());
|
||||
chunk.unload(true, false);
|
||||
chunk.load();
|
||||
|
||||
@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;
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
this.sendChunk.sendChunk(chunks);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
MainUtil.canSendChunk = false;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param plotChunk
|
||||
*/
|
||||
@Override
|
||||
public void execute(PlotChunk<Chunk> plotChunk) {
|
||||
FastChunk_1_8_3 fs = (FastChunk_1_8_3) plotChunk;
|
||||
Chunk chunk = plotChunk.getChunk();
|
||||
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);
|
||||
World world = chunk.getWorld();
|
||||
ChunkWrapper wrapper = plotChunk.getChunkWrapper();
|
||||
ChunkWrapper wrapper = new ChunkWrapper(getWorld(), lc.getX(), lc.getZ());
|
||||
if (!this.toUpdate.containsKey(wrapper)) {
|
||||
this.toUpdate.put(wrapper, chunk);
|
||||
}
|
||||
chunk.load(true);
|
||||
try {
|
||||
boolean flag = world.getEnvironment() == Environment.NORMAL;
|
||||
boolean flag = world.getEnvironment() == World.Environment.NORMAL;
|
||||
|
||||
// Sections
|
||||
Method getHandle = chunk.getClass().getDeclaredMethod("getHandle");
|
||||
@ -147,10 +285,10 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
|
||||
// Trim tiles
|
||||
boolean removed = false;
|
||||
Set<Entry<?, ?>> entrySet = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet();
|
||||
Iterator<Entry<?, ?>> iterator = entrySet.iterator();
|
||||
Set<Map.Entry<?, ?>> entrySet = (Set<Map.Entry<?, ?>>) (Set<?>) tiles.entrySet();
|
||||
Iterator<Map.Entry<?, ?>> iterator = entrySet.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Entry<?, ?> tile = iterator.next();
|
||||
Map.Entry<?, ?> tile = iterator.next();
|
||||
Object pos = tile.getKey();
|
||||
if (getX == null) {
|
||||
Class<? extends Object> clazz2 = pos.getClass().getSuperclass();
|
||||
@ -222,23 +360,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
} catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int[][] biomes = fs.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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fixLighting(chunk, fs, true);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param wrap
|
||||
*/
|
||||
@Override
|
||||
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
|
||||
return new FastChunk_1_8_3(wrap);
|
||||
public void fixChunkLighting(int x, int z) {
|
||||
Object c = this.methodGetHandleChunk.of(getChunk(x, z)).call();
|
||||
this.methodInitLighting.of(c).call();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues
|
||||
* @param plotChunk
|
||||
*/
|
||||
@Override
|
||||
public boolean fixLighting(PlotChunk<Chunk> plotChunk, boolean fixAll) {
|
||||
public boolean fixLighting(Chunk chunk, CharLocalChunk_1_8_3 bc, boolean fixAll) {
|
||||
try {
|
||||
FastChunk_1_8_3 bc = (FastChunk_1_8_3) plotChunk;
|
||||
Chunk chunk = bc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
chunk.load(false);
|
||||
} else {
|
||||
@ -279,7 +391,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
|
||||
if (fixAll && !(boolean) this.methodAreNeighborsLoaded.of(c).call(1)) {
|
||||
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 z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
|
||||
if (x != 0 && z != 0) {
|
||||
@ -310,7 +422,7 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
int X = chunk.getX() << 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++) {
|
||||
Object section = sections[j];
|
||||
if (section == null) {
|
||||
@ -398,17 +510,28 @@ public class FastQueue_1_8_3 extends SlowQueue {
|
||||
return array[j] >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param world
|
||||
* @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);
|
||||
public void update(Collection<Chunk> chunks) {
|
||||
if (chunks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
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)));
|
||||
}
|
||||
}
|
@ -1,73 +1,67 @@
|
||||
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.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
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.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 com.intellectualcrafters.plot.util.ReflectionUtils;
|
||||
import com.intellectualcrafters.plot.util.block.BasicLocalBlockQueue;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Map;
|
||||
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 HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
|
||||
private final RefMethod methodGetHandleChunk;
|
||||
private final RefMethod methodInitLighting;
|
||||
private final RefConstructor classBlockPositionConstructor;
|
||||
private final RefConstructor classChunkSectionConstructor;
|
||||
private final RefMethod methodW;
|
||||
private final RefMethod methodAreNeighborsLoaded;
|
||||
private final RefField fieldSections;
|
||||
private final RefField fieldWorld;
|
||||
private final RefMethod methodGetBlocks;
|
||||
private final RefMethod methodGetType;
|
||||
private final RefMethod methodSetType;
|
||||
private final RefMethod methodGetCombinedId;
|
||||
private final RefMethod methodGetByCombinedId;
|
||||
private final RefMethod methodGetWorld;
|
||||
// private final HashMap<ChunkWrapper, Chunk> toUpdate = new HashMap<>();
|
||||
private final ReflectionUtils.RefMethod methodGetHandleChunk;
|
||||
private final ReflectionUtils.RefMethod methodInitLighting;
|
||||
private final ReflectionUtils.RefConstructor classBlockPositionConstructor;
|
||||
private final ReflectionUtils.RefConstructor classChunkSectionConstructor;
|
||||
private final ReflectionUtils.RefMethod methodW;
|
||||
private final ReflectionUtils.RefMethod methodAreNeighborsLoaded;
|
||||
private final ReflectionUtils.RefField fieldSections;
|
||||
private final ReflectionUtils.RefField fieldWorld;
|
||||
private final ReflectionUtils.RefMethod methodGetBlocks;
|
||||
private final ReflectionUtils.RefMethod methodGetType;
|
||||
private final ReflectionUtils.RefMethod methodSetType;
|
||||
private final ReflectionUtils.RefMethod methodGetCombinedId;
|
||||
private final ReflectionUtils.RefMethod methodGetByCombinedId;
|
||||
private final ReflectionUtils.RefMethod methodGetWorld;
|
||||
|
||||
private final RefField tileEntityListTick;
|
||||
private final ReflectionUtils.RefField tileEntityListTick;
|
||||
|
||||
|
||||
public FastQueue_1_9() throws NoSuchFieldException, NoSuchMethodException, ClassNotFoundException {
|
||||
RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
public BukkitLocalQueue_1_9(String world) throws NoSuchMethodException, ClassNotFoundException, NoSuchFieldException {
|
||||
super(world);
|
||||
ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
|
||||
RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
ReflectionUtils.RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
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);
|
||||
RefClass classWorld = getRefClass("{nms}.World");
|
||||
ReflectionUtils.RefClass classWorld = getRefClass("{nms}.World");
|
||||
this.tileEntityListTick = classWorld.getField("tileEntityListTick");
|
||||
this.methodGetWorld = classChunk.getMethod("getWorld");
|
||||
this.methodW = classWorld.getMethod("w", classBlockPosition.getRealClass());
|
||||
this.fieldSections = classChunk.getField("sections");
|
||||
this.fieldWorld = classChunk.getField("world");
|
||||
RefClass classBlock = getRefClass("{nms}.Block");
|
||||
RefClass classIBlockData = getRefClass("{nms}.IBlockData");
|
||||
ReflectionUtils.RefClass classBlock = getRefClass("{nms}.Block");
|
||||
ReflectionUtils.RefClass classIBlockData = getRefClass("{nms}.IBlockData");
|
||||
this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
|
||||
this.methodGetByCombinedId = classBlock.getMethod("getByCombinedId", int.class);
|
||||
RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
|
||||
ReflectionUtils.RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
|
||||
this.methodGetBlocks = classChunkSection.getMethod("getBlocks");
|
||||
this.methodGetType = classChunkSection.getMethod("getType", int.class, int.class, int.class);
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param plotChunk
|
||||
*/
|
||||
@Override
|
||||
public void execute(PlotChunk<Chunk> plotChunk) {
|
||||
final FastChunk_1_9 fs = (FastChunk_1_9) plotChunk;
|
||||
Chunk chunk = plotChunk.getChunk();
|
||||
World world = chunk.getWorld();
|
||||
ChunkWrapper wrapper = plotChunk.getChunkWrapper();
|
||||
public LocalChunk<char[]> getLocalChunk(int x, int z) {
|
||||
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];
|
||||
}
|
||||
|
||||
@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);
|
||||
World world = chunk.getWorld();
|
||||
try {
|
||||
boolean flag = world.getEnvironment() == Environment.NORMAL;
|
||||
boolean flag = world.getEnvironment() == World.Environment.NORMAL;
|
||||
|
||||
// Sections
|
||||
Method getHandle = chunk.getClass().getDeclaredMethod("getHandle");
|
||||
@ -109,10 +264,10 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
Method zm = null;
|
||||
// Trim tiles
|
||||
boolean removed = false;
|
||||
Set<Entry<?, ?>> entrySet = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet();
|
||||
Iterator<Entry<?, ?>> iterator = entrySet.iterator();
|
||||
Set<Map.Entry<?, ?>> entrySet = (Set<Map.Entry<?, ?>>) (Set<?>) tiles.entrySet();
|
||||
Iterator<Map.Entry<?, ?>> iterator = entrySet.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Entry<?, ?> tile = iterator.next();
|
||||
Map.Entry<?, ?> tile = iterator.next();
|
||||
Object pos = tile.getKey();
|
||||
if (xm == null) {
|
||||
Class<?> clazz2 = pos.getClass().getSuperclass();
|
||||
@ -125,7 +280,7 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
int lz = (int) zm.invoke(pos) & 15;
|
||||
int j = MainUtil.CACHE_I[ly][lx][lz];
|
||||
int k = MainUtil.CACHE_J[ly][lx][lz];
|
||||
int[] array = fs.getIdArray(j);
|
||||
char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
@ -150,32 +305,25 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
if (fs.getCount(j) == 0) {
|
||||
continue;
|
||||
}
|
||||
int[] newArray = fs.getIdArray(j);
|
||||
char[] newArray = fs.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
Object section = sections[j];
|
||||
if (section == null || fs.getCount(j) >= 4096) {
|
||||
char[] array = new char[4096];
|
||||
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);
|
||||
section = sections[j] = newChunkSection(j << 4, flag, fs.getIdArray(j));
|
||||
continue;
|
||||
}
|
||||
Object currentArray = getBlocks(section);
|
||||
RefExecutor setType = this.methodSetType.of(section);
|
||||
ReflectionUtils.RefMethod.RefExecutor setType = this.methodSetType.of(section);
|
||||
boolean fill = true;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
int n = newArray[k];
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case -1: {
|
||||
case 1: {
|
||||
fill = false;
|
||||
int x = MainUtil.x_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 y = MainUtil.y_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);
|
||||
}
|
||||
}
|
||||
@ -199,24 +349,8 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
} catch (IllegalArgumentException | SecurityException | ReflectiveOperationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int[][] biomes = fs.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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
world.refreshChunk(fs.getX(), fs.getZ());
|
||||
fixLighting(chunk, fs, true);
|
||||
refreshChunk(fs.getX(), fs.getZ());
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues
|
||||
* @param wrap
|
||||
*/
|
||||
@Override
|
||||
public PlotChunk<Chunk> getChunk(ChunkWrapper wrap) {
|
||||
return new FastChunk_1_9(wrap);
|
||||
public void fixChunkLighting(int x, int z) {
|
||||
Object c = this.methodGetHandleChunk.of(getChunk(x, z)).call();
|
||||
this.methodInitLighting.of(c).call();
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues
|
||||
* @param pc
|
||||
*/
|
||||
@Override
|
||||
public boolean fixLighting(PlotChunk<Chunk> pc, boolean fixAll) {
|
||||
public boolean fixLighting(Chunk chunk, CharLocalChunk_1_8_3 bc, boolean fixAll) {
|
||||
try {
|
||||
FastChunk_1_9 bc = (FastChunk_1_9) pc;
|
||||
Chunk chunk = bc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
chunk.load(false);
|
||||
} else {
|
||||
chunk.unload(true, true);
|
||||
chunk.unload(true, false);
|
||||
chunk.load(false);
|
||||
}
|
||||
|
||||
// Initialize lighting
|
||||
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)) {
|
||||
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 z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
|
||||
if (x != 0 && z != 0) {
|
||||
@ -266,7 +389,7 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
while (!other.isLoaded()) {
|
||||
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 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++) {
|
||||
Object section = sections[j];
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
int[] array = bc.getIdArray(j);
|
||||
char[] array = bc.getIdArray(j);
|
||||
if (array != null) {
|
||||
int l = PseudoRandom.random.random(2);
|
||||
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 y = MainUtil.y_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;
|
||||
}
|
||||
Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
|
||||
@ -345,7 +468,12 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
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))
|
||||
&& isSolid(getId(sections, x + 1, y - 1, z))
|
||||
&& isSolid(getId(sections, x - 1, y, z))
|
||||
@ -361,29 +489,15 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getId(int[][] 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];
|
||||
int[] section = sections[i];
|
||||
public int getId(char[] section, int x, int y, int z) {
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
public int getId(char[][] sections, int x, int y, int z) {
|
||||
if (x < 0 || x > 15 || z < 0 || z > 15) {
|
||||
return 1;
|
||||
}
|
||||
@ -391,23 +505,10 @@ public class FastQueue_1_9 extends SlowQueue {
|
||||
return 1;
|
||||
}
|
||||
int i = MainUtil.CACHE_I[y][x][z];
|
||||
Object section = sections[i];
|
||||
char[] section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -1,62 +1,109 @@
|
||||
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.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
|
||||
import com.plotsquared.bukkit.util.BukkitUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
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 Chunk chunk;
|
||||
public short[][] result;
|
||||
public byte[][] result_data;
|
||||
public ChunkData cd;
|
||||
public BiomeGrid grid;
|
||||
|
||||
public Chunk chunk;
|
||||
public String world;
|
||||
public int cx;
|
||||
public int cz;
|
||||
|
||||
public GenChunk(Chunk chunk, ChunkWrapper wrap) {
|
||||
super(wrap);
|
||||
if ((this.chunk = chunk) == null && wrap != null) {
|
||||
super(null, new Location(null, 0, 0, 0), new Location(null, 15, 255, 15));
|
||||
if ((this.chunk = chunk) == null && (wrap) != null) {
|
||||
World world = BukkitUtil.getWorld(wrap.world);
|
||||
if (world != null) {
|
||||
chunk = world.getChunkAt(wrap.x, wrap.z);
|
||||
this.chunk = world.getChunkAt(wrap.x, wrap.z);
|
||||
}
|
||||
}
|
||||
this.biomes = Biome.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAbs() {
|
||||
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(Chunk chunk) {
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
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) {
|
||||
this.grid.setBiome(x, z, biome);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.cd.setBlock(x, y, z, id, data);
|
||||
return;
|
||||
this.cd.setBlock(x, y, z, id, (byte) data);
|
||||
return true;
|
||||
}
|
||||
int i = MainUtil.CACHE_I[y][x][z];
|
||||
short[] v = this.result[i];
|
||||
@ -70,13 +117,61 @@ public class GenChunk extends PlotChunk<Chunk> {
|
||||
if (vd == null) {
|
||||
this.result_data[i] = vd = new byte[4096];
|
||||
}
|
||||
vd[j] = data;
|
||||
vd[j] = (byte) data;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk clone() {
|
||||
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper());
|
||||
public PlotBlock getBlock(int x, int y, int z) {
|
||||
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) {
|
||||
for (int i = 0; i < this.result.length; i++) {
|
||||
short[] matrix = this.result[i];
|
||||
@ -97,9 +192,8 @@ public class GenChunk extends PlotChunk<Chunk> {
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk shallowClone() {
|
||||
GenChunk toReturn = new GenChunk(getChunkAbs(), getChunkWrapper());
|
||||
public GenChunk shallowClone() {
|
||||
GenChunk toReturn = new GenChunk(chunk, new ChunkWrapper(getWorld(), chunk.getX(), chunk.getZ()));
|
||||
toReturn.result = this.result;
|
||||
toReturn.result_data = this.result_data;
|
||||
toReturn.cd = this.cd;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -11,13 +11,12 @@ import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.EconHandler;
|
||||
import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.InventoryUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotQueue;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
|
||||
import com.intellectualcrafters.plot.util.block.QueueProvider;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@ -135,10 +134,10 @@ public interface IPlotMain extends ILogger {
|
||||
EconHandler getEconomyHandler();
|
||||
|
||||
/**
|
||||
* Get the {@link PlotQueue} class.
|
||||
* Get the {@link com.intellectualcrafters.plot.util.block.QueueProvider} class.
|
||||
* @return
|
||||
*/
|
||||
PlotQueue initPlotQueue();
|
||||
QueueProvider initBlockQueue();
|
||||
|
||||
/**
|
||||
* Get the {@link WorldUtil} class.
|
||||
|
@ -39,18 +39,17 @@ import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.ReflectionUtils;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
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.ExpiryTask;
|
||||
import com.plotsquared.listener.WESubscriber;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -112,7 +111,6 @@ public class PS {
|
||||
public YamlConfiguration worlds;
|
||||
public YamlConfiguration storage;
|
||||
public YamlConfiguration commands;
|
||||
public TaskManager TASK;
|
||||
public WorldEdit worldedit;
|
||||
public URL update;
|
||||
private ILogger logger;
|
||||
@ -153,7 +151,7 @@ public class PS {
|
||||
if (getJavaVersion() < 1.8) {
|
||||
PS.log(C.CONSOLE_JAVA_OUTDATED_1_8);
|
||||
}
|
||||
this.TASK = this.IMP.getTaskManager();
|
||||
TaskManager.IMP = this.IMP.getTaskManager();
|
||||
setupConfigs();
|
||||
this.translationFile =
|
||||
MainUtil.getFile(this.IMP.getDirectory(), Settings.Paths.TRANSLATIONS + File.separator + "PlotSquared.use_THIS.yml");
|
||||
@ -219,7 +217,8 @@ public class PS {
|
||||
// World Util
|
||||
WorldUtil.IMP = this.IMP.initWorldUtil();
|
||||
// Set block
|
||||
SetQueue.IMP.queue = this.IMP.initPlotQueue();
|
||||
GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1);
|
||||
GlobalBlockQueue.IMP.runTask();
|
||||
// Set chunk
|
||||
ChunkManager.manager = this.IMP.initChunkManager();
|
||||
// Schematic handler
|
||||
@ -1802,7 +1801,7 @@ public class PS {
|
||||
*/
|
||||
public void disable() {
|
||||
try {
|
||||
this.TASK = null;
|
||||
TaskManager.IMP = null;
|
||||
this.database = null;
|
||||
// Validate that all data in the db is correct
|
||||
final HashSet<Plot> plots = new HashSet<>();
|
||||
|
@ -10,7 +10,7 @@ import com.intellectualcrafters.plot.object.RunnableVal2;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal3;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
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.CommandDeclaration;
|
||||
|
||||
@ -45,7 +45,7 @@ public class Clear extends Command {
|
||||
@Override
|
||||
public void run() {
|
||||
plot.unlink();
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plot.removeRunning();
|
||||
|
@ -27,18 +27,17 @@ import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
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.PlotAnalysis;
|
||||
import com.plotsquared.general.commands.Command;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
import com.plotsquared.listener.WEManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
@ -48,7 +47,6 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.script.Bindings;
|
||||
import javax.script.ScriptContext;
|
||||
import javax.script.ScriptEngine;
|
||||
@ -119,12 +117,12 @@ public class DebugExec extends SubCommand {
|
||||
|
||||
// Instances
|
||||
this.scope.put("PS", PS.get());
|
||||
this.scope.put("SetQueue", SetQueue.IMP);
|
||||
this.scope.put("GlobalBlockQueue", GlobalBlockQueue.IMP);
|
||||
this.scope.put("ExpireManager", ExpireManager.IMP);
|
||||
if (PS.get().worldedit != null) {
|
||||
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("ConsolePlayer", ConsolePlayer.getConsole());
|
||||
this.scope.put("SchematicHandler", SchematicHandler.manager);
|
||||
|
@ -8,8 +8,7 @@ import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal2;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal3;
|
||||
import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
|
||||
import com.plotsquared.general.commands.Command;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
import java.util.HashSet;
|
||||
@ -28,12 +27,11 @@ public class Relight extends Command {
|
||||
return;
|
||||
}
|
||||
HashSet<RegionWrapper> regions = plot.getRegions();
|
||||
final LocalBlockQueue queue = plot.getArea().getQueue(false);
|
||||
ChunkManager.chunkTask(plot, new RunnableVal<int[]>() {
|
||||
@Override
|
||||
public void run(int[] value) {
|
||||
SetQueue.ChunkWrapper cw = SetQueue.IMP.new ChunkWrapper(plot.getArea().worldname, value[0], value[1]);
|
||||
PlotChunk<?> pc = SetQueue.IMP.queue.getChunk(cw);
|
||||
pc.fixLighting();
|
||||
queue.fixChunkLighting(value[0], value[1]);
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
|
@ -12,10 +12,10 @@ import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.StringComparison;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.plotsquared.general.commands.Command;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
|
||||
@ -114,7 +114,7 @@ public class Set extends SubCommand {
|
||||
current.setComponent(component, blocks);
|
||||
}
|
||||
MainUtil.sendMessage(player, C.GENERATING_COMPONENT);
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plot.removeRunning();
|
||||
|
@ -13,12 +13,11 @@ import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.SetupObject;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.plotsquared.general.commands.CommandDeclaration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -156,7 +155,7 @@ public class Template extends SubCommand {
|
||||
setup.step = new ConfigurationNode[0];
|
||||
setup.world = world;
|
||||
SetupUtils.manager.setupWorld(setup);
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
MainUtil.sendMessage(player, "Done!");
|
||||
|
@ -13,6 +13,8 @@ import com.intellectualcrafters.plot.util.ChunkManager;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
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 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>() {
|
||||
@Override
|
||||
public void run(ChunkLoc value) {
|
||||
ChunkManager.manager.regenerateChunk(world, value);
|
||||
queue.regenChunk(value.x, value.z);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
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.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
|
||||
|
||||
import com.intellectualcrafters.plot.util.block.DelegateLocalBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
|
||||
import java.util.Set;
|
||||
|
||||
public class AugmentedUtils {
|
||||
@ -23,18 +23,10 @@ public class AugmentedUtils {
|
||||
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) {
|
||||
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 bz = cz << 4;
|
||||
RegionWrapper region = new RegionWrapper(bx, bx + 15, bz, bz + 15);
|
||||
@ -44,7 +36,6 @@ public class AugmentedUtils {
|
||||
}
|
||||
PseudoRandom r = new PseudoRandom();
|
||||
r.state = (cx << 16) | (cz & 0xFFFF);
|
||||
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, cx, cz);
|
||||
boolean toReturn = false;
|
||||
for (final PlotArea area : areas) {
|
||||
if (area.TYPE == 0) {
|
||||
@ -57,8 +48,11 @@ public class AugmentedUtils {
|
||||
if (generator == null) {
|
||||
continue;
|
||||
}
|
||||
final PlotChunk<?> result = lazyChunk.getOrCreate();
|
||||
final PlotChunk<?> primaryMask;
|
||||
// Mask
|
||||
if (queue == null) {
|
||||
queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
|
||||
}
|
||||
LocalBlockQueue primaryMask;
|
||||
// coords
|
||||
int bxx;
|
||||
int bzz;
|
||||
@ -70,42 +64,29 @@ public class AugmentedUtils {
|
||||
bzz = Math.max(0, area.getRegion().minZ - bz);
|
||||
txx = Math.min(15, area.getRegion().maxX - bx);
|
||||
tzz = Math.min(15, area.getRegion().maxZ - bz);
|
||||
primaryMask = new PlotChunk<Object>(wrap) {
|
||||
primaryMask = new DelegateLocalBlockQueue(queue) {
|
||||
@Override
|
||||
public Object getChunkAbs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
if (area.contains(x, z)) {
|
||||
return super.setBlock(x, y, z, id, data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, int biome) {
|
||||
if (area.contains(bx + x, bz + z)) {
|
||||
result.setBiome(x, z, biome);
|
||||
public boolean setBiome(int x, int z, String biome) {
|
||||
if (area.contains(x, z)) {
|
||||
return super.setBiome(x, z, biome);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk clone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk shallowClone() {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
bxx = bzz = 0;
|
||||
txx = tzz = 15;
|
||||
primaryMask = result;
|
||||
primaryMask = queue;
|
||||
}
|
||||
PlotChunk<?> secondaryMask;
|
||||
LocalBlockQueue secondaryMask;
|
||||
PlotBlock air = PlotBlock.get((short) 0, (byte) 0);
|
||||
if (area.TERRAIN == 2) {
|
||||
PlotManager manager = area.getPlotManager();
|
||||
@ -118,7 +99,7 @@ public class AugmentedUtils {
|
||||
boolean can = manager.getPlotId(area, rx, 0, rz) == null;
|
||||
if (can) {
|
||||
for (int y = 1; y < 128; y++) {
|
||||
result.setBlock(x, y, z, air);
|
||||
queue.setBlock(x, y, z, air);
|
||||
}
|
||||
canPlace[x][z] = can;
|
||||
has = true;
|
||||
@ -129,30 +110,18 @@ public class AugmentedUtils {
|
||||
continue;
|
||||
}
|
||||
toReturn = true;
|
||||
secondaryMask = new PlotChunk<Object>(wrap) {
|
||||
secondaryMask = new DelegateLocalBlockQueue(primaryMask) {
|
||||
@Override
|
||||
public Object getChunkAbs() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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 (canPlace[x][z]) {
|
||||
primaryMask.setBlock(x, y, z, id, data);
|
||||
return super.setBlock(x, y, z, id, data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, int biome) {}
|
||||
|
||||
@Override
|
||||
public PlotChunk clone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk shallowClone() {
|
||||
return null;
|
||||
public boolean setBiome(int x, int y, String biome) {
|
||||
return super.setBiome(x, y, biome);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@ -160,19 +129,17 @@ public class AugmentedUtils {
|
||||
for (int x = bxx; x <= txx; x++) {
|
||||
for (int z = bzz; z <= tzz; z++) {
|
||||
for (int y = 1; y < 128; y++) {
|
||||
result.setBlock(x, y, z, air);
|
||||
queue.setBlock(x, y, z, air);
|
||||
}
|
||||
}
|
||||
}
|
||||
toReturn = true;
|
||||
}
|
||||
generator.generateChunk(secondaryMask, area, r);
|
||||
generator.populateChunk(secondaryMask, area, r);
|
||||
}
|
||||
if (lazyChunk.get() != null) {
|
||||
lazyChunk.get().addToQueue();
|
||||
lazyChunk.get().flush(false);
|
||||
ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(secondaryMask, new Location(area.worldname, bx, 0, bz), new Location(area.worldname, bx + 15, 255, bz + 15));
|
||||
generator.generateChunk(scoped, area, r);
|
||||
generator.populateChunk(scoped, area, r);
|
||||
}
|
||||
queue.flush();
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
|
||||
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)) {
|
||||
setWall(dpw, plot.getId(), new PlotBlock[]{dpw.WALL_BLOCK});
|
||||
}
|
||||
SetQueue.IMP.addTask(whenDone);
|
||||
GlobalBlockQueue.IMP.addTask(whenDone);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setFloor(PlotArea plotArea, PlotId plotId, PlotBlock[] blocks) {
|
||||
Plot plot = plotArea.getPlotAbs(plotId);
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
if (plot.isBasePlot()) {
|
||||
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
|
||||
for (RegionWrapper region : plot.getRegions()) {
|
||||
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);
|
||||
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks);
|
||||
queue.setCuboid(pos1, pos2, blocks);
|
||||
}
|
||||
}
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -77,11 +78,13 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
if (!plot.isBasePlot()) {
|
||||
return false;
|
||||
}
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
for (RegionWrapper region : plot.getRegions()) {
|
||||
Location pos1 = new Location(plotArea.worldname, region.minX, 1, region.minZ);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -91,11 +94,13 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
return false;
|
||||
}
|
||||
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
for (RegionWrapper region : plot.getRegions()) {
|
||||
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);
|
||||
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks);
|
||||
queue.setCuboid(pos1, pos2, blocks);
|
||||
}
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -105,11 +110,13 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
return false;
|
||||
}
|
||||
ClassicPlotWorld dpw = (ClassicPlotWorld) plotArea;
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
for (RegionWrapper region : plot.getRegions()) {
|
||||
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);
|
||||
MainUtil.setCuboidAsync(plotArea.worldname, pos1, pos2, blocks);
|
||||
queue.setCuboid(pos1, pos2, blocks);
|
||||
}
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -120,8 +127,10 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
}
|
||||
Location[] corners = plot.getCorners();
|
||||
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]);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -134,11 +143,12 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
Location bottom = plot.getBottomAbs();
|
||||
Location top = plot.getExtendedTopAbs();
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
if (!plot.getMerged(0)) {
|
||||
int z = bottom.getZ();
|
||||
for (int x = bottom.getX(); x <= top.getX(); x++) {
|
||||
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();
|
||||
for (int z = bottom.getZ(); z <= top.getZ(); z++) {
|
||||
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();
|
||||
for (int x = bottom.getX(); x <= top.getX(); x++) {
|
||||
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();
|
||||
for (int z = bottom.getZ(); z <= top.getZ(); z++) {
|
||||
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()) {
|
||||
Location pos1 = new Location(plotArea.worldname, region.minX, 255, region.minZ);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 top = plot.getExtendedTopAbs().add(1, 0, 1);
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
if (!plot.getMerged(0)) {
|
||||
int z = bot.getZ();
|
||||
for (int x = bot.getX(); x < top.getX(); x++) {
|
||||
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();
|
||||
for (int z = bot.getZ(); z < top.getZ(); z++) {
|
||||
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();
|
||||
for (int x = bot.getX(); x < top.getX() + (plot.getMerged(1) ? 0 : 1); x++) {
|
||||
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();
|
||||
for (int z = bot.getZ(); z < top.getZ() + (plot.getMerged(2) ? 0 : 1); z++) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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 top = plot.getExtendedTopAbs().add(1, 0, 1);
|
||||
PseudoRandom random = new PseudoRandom();
|
||||
LocalBlockQueue queue = plotArea.getQueue(false);
|
||||
int y = dpw.WALL_HEIGHT + 1;
|
||||
if (!plot.getMerged(0)) {
|
||||
int z = bot.getZ();
|
||||
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)) {
|
||||
int x = bot.getX();
|
||||
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)) {
|
||||
int z = top.getZ();
|
||||
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)) {
|
||||
int x = top.getX();
|
||||
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;
|
||||
}
|
||||
|
||||
@ -270,24 +285,26 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ex = sx + dpw.ROAD_WIDTH - 1;
|
||||
int sz = pos1.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, 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,
|
||||
(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);
|
||||
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),
|
||||
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);
|
||||
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),
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -300,23 +317,25 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ez = sz + dpw.ROAD_WIDTH - 1;
|
||||
int sx = pos1.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, 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));
|
||||
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);
|
||||
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),
|
||||
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);
|
||||
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),
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -328,13 +347,15 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ex = sx + dpw.ROAD_WIDTH - 1;
|
||||
int sz = pos2.getZ() + 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(
|
||||
(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));
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -347,12 +368,14 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ex = sx + dpw.ROAD_WIDTH - 1;
|
||||
int sz = pos1.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));
|
||||
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);
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -365,12 +388,14 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ez = sz + dpw.ROAD_WIDTH - 1;
|
||||
int sx = pos1.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));
|
||||
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);
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -382,12 +407,14 @@ public class ClassicPlotManager extends SquarePlotManager {
|
||||
int ex = sx + dpw.ROAD_WIDTH - 1;
|
||||
int sz = location.getZ() + 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));
|
||||
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);
|
||||
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);
|
||||
queue.enqueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
package com.intellectualcrafters.plot.generator;
|
||||
|
||||
import com.intellectualcrafters.jnbt.CompoundTag;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.block.ScopedLocalBlockQueue;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@ -20,12 +21,12 @@ public class HybridGen extends IndependentPlotGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random) {
|
||||
public void generateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
|
||||
HybridPlotWorld hpw = (HybridPlotWorld) settings;
|
||||
// Biome
|
||||
for (short x = 0; x < 16; x++) {
|
||||
for (short z = 0; z < 16; z++) {
|
||||
result.setBiome(x, z, hpw.PLOT_BIOME);
|
||||
result.fillBiome(hpw.PLOT_BIOME);
|
||||
}
|
||||
}
|
||||
// Bedrock
|
||||
@ -37,10 +38,11 @@ public class HybridGen extends IndependentPlotGenerator {
|
||||
}
|
||||
}
|
||||
// Coords
|
||||
int cx = result.getX();
|
||||
int cz = result.getZ();
|
||||
int bx = (cx << 4) - hpw.ROAD_OFFSET_X;
|
||||
int bz = (cz << 4) - hpw.ROAD_OFFSET_Z;
|
||||
Location min = result.getMin();
|
||||
int cx = min.getX() >> 4;
|
||||
int cz = min.getZ() >> 4;
|
||||
int bx = (min.getX()) - hpw.ROAD_OFFSET_X;
|
||||
int bz = (min.getZ()) - hpw.ROAD_OFFSET_Z;
|
||||
short rbx;
|
||||
if (bx < 0) {
|
||||
rbx = (short) (hpw.SIZE + (bx % hpw.SIZE));
|
||||
@ -183,11 +185,12 @@ public class HybridGen extends IndependentPlotGenerator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean populateChunk(PlotChunk<?> result, PlotArea settings, PseudoRandom random) {
|
||||
public boolean populateChunk(ScopedLocalBlockQueue result, PlotArea settings, PseudoRandom random) {
|
||||
HybridPlotWorld hpw = (HybridPlotWorld) settings;
|
||||
if (hpw.G_SCH_STATE != null) {
|
||||
int cx = result.getX();
|
||||
int cz = result.getZ();
|
||||
Location min = result.getMin();
|
||||
int cx = min.getX() >> 4;
|
||||
int cz = min.getZ() >> 4;
|
||||
int p1x = cx << 4;
|
||||
int p1z = cz << 4;
|
||||
int bx = p1x - hpw.ROAD_OFFSET_X;
|
||||
|
@ -3,7 +3,6 @@ package com.intellectualcrafters.plot.generator;
|
||||
import com.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.commands.Template;
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.FileBytes;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
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.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.MathMan;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
|
||||
import com.intellectualcrafters.plot.util.block.GlobalBlockQueue;
|
||||
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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) {
|
||||
int size = hpw.SIZE;
|
||||
LocalBlockQueue queue = hpw.getQueue(false);
|
||||
for (int x = pos1.getX(); x <= pos2.getX(); x++) {
|
||||
short absX = (short) ((x - hpw.ROAD_OFFSET_X) % size);
|
||||
if (absX < 0) {
|
||||
@ -85,16 +84,17 @@ public class HybridPlotManager extends ClassicPlotManager {
|
||||
HashMap<Integer, PlotBlock> blocks = hpw.G_SCH.get(MathMan.pair(absX, absZ));
|
||||
if (clear) {
|
||||
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) {
|
||||
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
|
||||
@ -157,13 +157,14 @@ public class HybridPlotManager extends ClassicPlotManager {
|
||||
bedrock = 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[]>() {
|
||||
@Override
|
||||
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 (canRegen && (value[6] == 0)) {
|
||||
ChunkManager.manager.regenerateChunk(world, new ChunkLoc(value[0], value[1]));
|
||||
queue.regenChunk(value[0], value[1]);
|
||||
return;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -174,25 +175,26 @@ public class HybridPlotManager extends ClassicPlotManager {
|
||||
// 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 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
|
||||
bot.setY(1);
|
||||
top.setY(dpw.PLOT_HEIGHT);
|
||||
MainUtil.setCuboidAsync(world, bot, top, filling);
|
||||
queue.setCuboid(bot, top, filling);
|
||||
bot.setY(dpw.PLOT_HEIGHT);
|
||||
top.setY(dpw.PLOT_HEIGHT + 1);
|
||||
MainUtil.setCuboidAsync(world, bot, top, plotfloor);
|
||||
queue.setCuboid(bot, top, plotfloor);
|
||||
bot.setY(dpw.PLOT_HEIGHT + 1);
|
||||
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
|
||||
pastePlotSchematic(dpw, bot, top);
|
||||
}
|
||||
}, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
queue.enqueue();
|
||||
// And notify whatever called this when plot clearing is done
|
||||
SetQueue.IMP.addTask(whenDone);
|
||||
GlobalBlockQueue.IMP.addTask(whenDone);
|
||||
}
|
||||
}, 10);
|
||||
return true;
|
||||
|
@ -8,7 +8,6 @@ import com.intellectualcrafters.plot.flag.Flags;
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.Location;
|
||||
import com.intellectualcrafters.plot.object.Plot;
|
||||
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
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.MathMan;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
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.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
@ -107,7 +107,27 @@ public abstract class HybridUtils {
|
||||
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) {
|
||||
ArrayList<ChunkLoc> chunks = new ArrayList<>();
|
||||
@ -139,6 +159,7 @@ public abstract class HybridUtils {
|
||||
whenDone.value = 0;
|
||||
final ClassicPlotWorld cpw = (ClassicPlotWorld) plotArea;
|
||||
final ArrayDeque<RegionWrapper> zones = new ArrayDeque<>(plot.getRegions());
|
||||
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(cpw.worldname, false);
|
||||
Runnable run = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -159,11 +180,10 @@ public abstract class HybridUtils {
|
||||
int bz = value[3];
|
||||
int ex = value[4];
|
||||
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(plot.getArea().worldname, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK);
|
||||
whenDone.value += checkModified(queue, bx, ex, 1, cpw.PLOT_HEIGHT - 1, bz, ez, cpw.MAIN_BLOCK);
|
||||
whenDone.value += checkModified(queue, bx, ex, cpw.PLOT_HEIGHT, cpw.PLOT_HEIGHT, bz, ez, cpw.TOP_BLOCK);
|
||||
whenDone.value += checkModified(
|
||||
plot.getArea().worldname, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez,
|
||||
new PlotBlock[]{PlotBlock.get((short) 0, (byte) 0)});
|
||||
queue, bx, ex, cpw.PLOT_HEIGHT + 1, 255, bz, ez, new PlotBlock[]{PlotBlock.get((short) 0, (byte) 0)});
|
||||
}
|
||||
}, this, 5);
|
||||
|
||||
@ -281,7 +301,7 @@ public abstract class HybridUtils {
|
||||
PS.debug("&d - Potentially skipping 1024 chunks");
|
||||
PS.debug("&d - TODO: recommend chunkster if corrupt");
|
||||
}
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
GlobalBlockQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TaskManager.runTaskLater(task, 20);
|
||||
@ -297,6 +317,7 @@ public abstract class HybridUtils {
|
||||
|
||||
public boolean setupRoadSchematic(Plot plot) {
|
||||
final String world = plot.getArea().worldname;
|
||||
final LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false);
|
||||
Location bot = plot.getBottomAbs().subtract(1, 0, 1);
|
||||
Location top = plot.getTopAbs();
|
||||
final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea();
|
||||
@ -305,10 +326,10 @@ public abstract class HybridUtils {
|
||||
int sy = plotworld.ROAD_HEIGHT;
|
||||
int ex = bot.getX();
|
||||
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 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)));
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
int x = chunk.x << 4;
|
||||
@ -359,6 +395,7 @@ public abstract class HybridUtils {
|
||||
PlotId id2 = manager.getPlotId(plotWorld, ex, 0, ez);
|
||||
x -= plotWorld.ROAD_OFFSET_X;
|
||||
z -= plotWorld.ROAD_OFFSET_Z;
|
||||
LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(plotWorld.worldname, false);
|
||||
if (id1 == null || id2 == null || id1 != id2) {
|
||||
boolean result = ChunkManager.manager.loadChunk(area.worldname, chunk, false);
|
||||
if (result) {
|
||||
@ -399,26 +436,20 @@ public abstract class HybridUtils {
|
||||
if (condition) {
|
||||
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++) {
|
||||
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) {
|
||||
for (Entry<Integer, PlotBlock> entry : blocks.entrySet()) {
|
||||
SetQueue.IMP.setBlock(area.worldname, x + X + plotWorld.ROAD_OFFSET_X, entry.getKey(),
|
||||
z + Z + plotWorld.ROAD_OFFSET_Z, entry.getValue());
|
||||
queue.setBlock(x + X + plotWorld.ROAD_OFFSET_X, entry.getKey(), 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;
|
||||
}
|
||||
}
|
||||
queue.enqueue();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import com.intellectualcrafters.plot.object.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotManager;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
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.
|
||||
@ -28,9 +28,9 @@ public abstract class IndependentPlotGenerator {
|
||||
* @param settings
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -17,14 +17,14 @@ import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.Permissions;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.TaskManager;
|
||||
import com.intellectualcrafters.plot.util.UUIDHandler;
|
||||
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.plotsquared.listener.PlotListener;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.PathIterator;
|
||||
@ -782,7 +782,7 @@ public class Plot {
|
||||
manager.claimPlot(Plot.this.area, current);
|
||||
}
|
||||
}
|
||||
SetQueue.IMP.addTask(run);
|
||||
GlobalBlockQueue.IMP.addTask(run);
|
||||
return;
|
||||
}
|
||||
Plot current = queue.poll();
|
||||
@ -794,10 +794,11 @@ public class Plot {
|
||||
}
|
||||
};
|
||||
if (!isMerged() && this.area.getRegion().equals(getLargestRegion())) {
|
||||
final LocalBlockQueue blockQueue = area.getQueue(false);
|
||||
ChunkManager.largeRegionTask(this.area.worldname, this.area.getRegion(), new RunnableVal<ChunkLoc>() {
|
||||
@Override
|
||||
public void run(ChunkLoc value) {
|
||||
ChunkManager.manager.regenerateChunk(Plot.this.area.worldname, value);
|
||||
blockQueue.regenChunk(value.x, value.z);
|
||||
}
|
||||
}, whenDone);
|
||||
} else {
|
||||
@ -1246,20 +1247,17 @@ public class Plot {
|
||||
* This should not need to be called
|
||||
*/
|
||||
public void refreshChunks() {
|
||||
TaskManager.runTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
HashSet<ChunkLoc> chunks = new HashSet<>();
|
||||
for (RegionWrapper region : Plot.this.getRegions()) {
|
||||
for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) {
|
||||
for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) {
|
||||
chunks.add(new ChunkLoc(x, z));
|
||||
}
|
||||
LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(area.worldname, false);
|
||||
HashSet<ChunkLoc> chunks = new HashSet<>();
|
||||
for (RegionWrapper region : Plot.this.getRegions()) {
|
||||
for (int x = region.minX >> 4; x <= region.maxX >> 4; x++) {
|
||||
for (int z = region.minZ >> 4; z <= region.maxZ >> 4; z++) {
|
||||
if (chunks.add(new ChunkLoc(x, z))) {
|
||||
queue.refreshChunk(x, z);
|
||||
}
|
||||
}
|
||||
SetQueue.IMP.queue.sendChunk(Plot.this.area.worldname, chunks);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove the plot sign if it is set. */
|
||||
@ -1269,7 +1267,9 @@ public class Plot {
|
||||
return;
|
||||
}
|
||||
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. */
|
||||
|
@ -15,9 +15,9 @@ import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotGameMode;
|
||||
import com.intellectualcrafters.plot.util.StringMan;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
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.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -48,7 +48,7 @@ public abstract class PlotArea {
|
||||
public boolean ALLOW_SIGNS = true;
|
||||
public boolean MOB_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 SCHEMATIC_CLAIM_SPECIFY = false;
|
||||
public boolean SCHEMATIC_ON_CLAIM = false;
|
||||
@ -91,6 +91,10 @@ public abstract class PlotArea {
|
||||
this.worldhash = worldName.hashCode();
|
||||
}
|
||||
|
||||
public LocalBlockQueue getQueue(boolean autoQueue) {
|
||||
return GlobalBlockQueue.IMP.getNewQueue(worldname, autoQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PlotArea object with no functionality/information.
|
||||
* - 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.MAX_PLOT_MEMBERS = config.getInt("limits.max-members");
|
||||
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_FILE = config.getString("schematic.file");
|
||||
this.SCHEMATIC_CLAIM_SPECIFY = config.getBoolean("schematic.specify_on_claim");
|
||||
|
@ -4,24 +4,23 @@ 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.object.RegionWrapper;
|
||||
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.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class ChunkManager {
|
||||
|
||||
public static ChunkManager manager = null;
|
||||
private static RunnableVal<PlotChunk<?>> CURRENT_FORCE_CHUNK;
|
||||
private static RunnableVal<PlotChunk<?>> CURRENT_ADD_CHUNK;
|
||||
private static RunnableVal<ScopedLocalBlockQueue> CURRENT_FORCE_CHUNK;
|
||||
private static RunnableVal<ScopedLocalBlockQueue> CURRENT_ADD_CHUNK;
|
||||
|
||||
public static ChunkLoc getChunkChunk(Location location) {
|
||||
int x = location.getX() >> 9;
|
||||
@ -29,40 +28,41 @@ public abstract class ChunkManager {
|
||||
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)) {
|
||||
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world, loc.x, loc.z);
|
||||
PlotChunk<?> chunk = SetQueue.IMP.queue.getChunk(wrap);
|
||||
OffsetLocalBlockQueue offset = new OffsetLocalBlockQueue(queue, loc.x >> 4, 0, loc.z >> 4);
|
||||
ScopedLocalBlockQueue scoped = new ScopedLocalBlockQueue(offset, new Location(world, 0, 0, 0), new Location(world, 15, 255, 15));
|
||||
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);
|
||||
if (add != null) {
|
||||
add.run(chunk);
|
||||
}
|
||||
chunk.addToQueue();
|
||||
chunk.flush(true);
|
||||
queue.flush();
|
||||
} else {
|
||||
CURRENT_FORCE_CHUNK = force;
|
||||
CURRENT_ADD_CHUNK = add;
|
||||
manager.regenerateChunk(world, loc);
|
||||
queue.regenChunk(loc.x, loc.z);
|
||||
CURRENT_FORCE_CHUNK = null;
|
||||
CURRENT_ADD_CHUNK = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean preProcessChunk(PlotChunk<?> chunk) {
|
||||
public static boolean preProcessChunk(ScopedLocalBlockQueue queue) {
|
||||
if (CURRENT_FORCE_CHUNK != null) {
|
||||
CURRENT_FORCE_CHUNK.run(chunk);
|
||||
CURRENT_FORCE_CHUNK.run(queue);
|
||||
CURRENT_FORCE_CHUNK = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean postProcessChunk(PlotChunk<?> chunk) {
|
||||
public static boolean postProcessChunk(ScopedLocalBlockQueue queue) {
|
||||
if (CURRENT_ADD_CHUNK != null) {
|
||||
CURRENT_ADD_CHUNK.run(chunk);
|
||||
CURRENT_ADD_CHUNK.run(queue);
|
||||
CURRENT_ADD_CHUNK = null;
|
||||
return true;
|
||||
}
|
||||
@ -228,20 +228,6 @@ public abstract class ChunkManager {
|
||||
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) {
|
||||
deleteRegionFiles(world, chunks, null);
|
||||
}
|
||||
|
@ -8,18 +8,14 @@ import com.intellectualcrafters.plot.database.DBFunc;
|
||||
import com.intellectualcrafters.plot.flag.Flag;
|
||||
import com.intellectualcrafters.plot.flag.FlagManager;
|
||||
import com.intellectualcrafters.plot.flag.Flags;
|
||||
import com.intellectualcrafters.plot.object.ChunkLoc;
|
||||
import com.intellectualcrafters.plot.object.ConsolePlayer;
|
||||
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.PlotId;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@ -202,7 +198,7 @@ public class MainUtil {
|
||||
* @return true if any changes were made
|
||||
*/
|
||||
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)) {
|
||||
MainUtil.setBiome(area.worldname, pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome);
|
||||
return true;
|
||||
@ -491,15 +487,6 @@ public class MainUtil {
|
||||
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) {
|
||||
if (Paths.get(path).isAbsolute()) {
|
||||
return new File(path);
|
||||
@ -507,46 +494,6 @@ public class MainUtil {
|
||||
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.
|
||||
* @param world
|
||||
|
@ -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) {
|
||||
double count = 0;
|
||||
for (int i : array) {
|
||||
@ -115,7 +229,7 @@ public class MathMan {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.object.RegionWrapper;
|
||||
import com.intellectualcrafters.plot.object.RunnableVal;
|
||||
|
||||
import com.intellectualcrafters.plot.util.block.LocalBlockQueue;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -136,8 +136,7 @@ public abstract class SchematicHandler {
|
||||
*
|
||||
* @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,
|
||||
final RunnableVal<Boolean> whenDone) {
|
||||
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) {
|
||||
TaskManager.runTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -160,7 +159,7 @@ public abstract class SchematicHandler {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
final LocalBlockQueue queue = plot.getArea().getQueue(false);
|
||||
Dimension dimension = schematic.getSchematicDimension();
|
||||
final int WIDTH = dimension.getX();
|
||||
final int LENGTH = dimension.getZ();
|
||||
@ -322,10 +321,10 @@ public abstract class SchematicHandler {
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
SetQueue.IMP.setBlock(plot.getArea().worldname, xx, yy, zz, id);
|
||||
queue.setBlock(xx, yy, zz, id);
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -333,31 +332,17 @@ public abstract class SchematicHandler {
|
||||
}
|
||||
}
|
||||
if (!chunks.isEmpty()) {
|
||||
final Runnable task = this;
|
||||
// Run when the queue is free
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
System.gc();
|
||||
TaskManager.runTaskLaterAsync(task, 80);
|
||||
}
|
||||
});
|
||||
this.run();
|
||||
} else {
|
||||
System.gc();
|
||||
// Finished
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Map.Entry<BlockLoc, CompoundTag> entry : schematic.getTiles().entrySet()) {
|
||||
BlockLoc loc = entry.getKey();
|
||||
restoreTile(plot.getArea().worldname, entry.getValue(), p1x + xOffset + loc.x, loc.y + y_offset_actual, p1z + zOffset + loc.z);
|
||||
}
|
||||
if (whenDone != null) {
|
||||
whenDone.value = true;
|
||||
whenDone.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
queue.flush();
|
||||
for (Map.Entry<BlockLoc, CompoundTag> entry : schematic.getTiles().entrySet()) {
|
||||
BlockLoc loc = entry.getKey();
|
||||
restoreTile(plot.getArea().worldname, entry.getValue(), p1x + xOffset + loc.x, loc.y + y_offset_actual, p1z + zOffset + loc.z);
|
||||
}
|
||||
if (whenDone != null) {
|
||||
whenDone.value = true;
|
||||
whenDone.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,51 +7,97 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class TaskManager {
|
||||
|
||||
public static TaskManager IMP;
|
||||
|
||||
public static final HashSet<String> TELEPORT_QUEUE = new HashSet<>();
|
||||
public static final HashMap<Integer, Integer> tasks = new HashMap<>();
|
||||
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) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
throw new IllegalArgumentException("disabled");
|
||||
}
|
||||
return PS.get().TASK.taskRepeat(runnable, interval);
|
||||
return IMP.taskRepeat(runnable, interval);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int runTaskRepeatAsync(Runnable runnable, int interval) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
throw new IllegalArgumentException("disabled");
|
||||
}
|
||||
return PS.get().TASK.taskRepeat(runnable, interval);
|
||||
return IMP.taskRepeat(runnable, interval);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void runTaskAsync(Runnable runnable) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
runnable.run();
|
||||
return;
|
||||
}
|
||||
PS.get().TASK.taskAsync(runnable);
|
||||
IMP.taskAsync(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runTask(Runnable runnable) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
runnable.run();
|
||||
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) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
runnable.run();
|
||||
return;
|
||||
}
|
||||
PS.get().TASK.taskLater(runnable, delay);
|
||||
IMP.taskLater(runnable, delay);
|
||||
}
|
||||
}
|
||||
|
||||
public static void runTaskLaterAsync(Runnable runnable, int delay) {
|
||||
if (runnable != null) {
|
||||
if (PS.get().TASK == null) {
|
||||
if (IMP == null) {
|
||||
runnable.run();
|
||||
return;
|
||||
}
|
||||
PS.get().TASK.taskLaterAsync(runnable, delay);
|
||||
IMP.taskLaterAsync(runnable, delay);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -215,17 +215,11 @@ public class ProcessedWEExtent extends AbstractDelegateExtent {
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
// if (Settings.EXPERIMENTAL_FAST_ASYNC_WORLDEDIT) {
|
||||
// SetQueue.IMP.setBlock(this.world, x, y, z, id);
|
||||
// } else
|
||||
{
|
||||
super.setBlock(location, block);
|
||||
}
|
||||
break;
|
||||
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);
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ apply plugin: 'com.github.johnrengelman.shadow'
|
||||
dependencies {
|
||||
compile project(':Core')
|
||||
compile 'org.spongepowered:spongeapi:5.0.0-SNAPSHOT'
|
||||
//compile 'org.mcstats.sponge:metrics:R8-SNAPSHOT'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
@ -20,7 +20,6 @@ import com.intellectualcrafters.plot.util.EconHandler;
|
||||
import com.intellectualcrafters.plot.util.EventUtil;
|
||||
import com.intellectualcrafters.plot.util.InventoryUtil;
|
||||
import com.intellectualcrafters.plot.util.MainUtil;
|
||||
import com.intellectualcrafters.plot.util.PlotQueue;
|
||||
import com.intellectualcrafters.plot.util.SchematicHandler;
|
||||
import com.intellectualcrafters.plot.util.SetupUtils;
|
||||
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.UUIDHandlerImplementation;
|
||||
import com.intellectualcrafters.plot.util.WorldUtil;
|
||||
import com.intellectualcrafters.plot.util.block.QueueProvider;
|
||||
import com.intellectualcrafters.plot.uuid.UUIDWrapper;
|
||||
import com.plotsquared.sponge.generator.SpongePlotGenerator;
|
||||
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.SpongeTitleManager;
|
||||
import com.plotsquared.sponge.util.SpongeUtil;
|
||||
import com.plotsquared.sponge.util.block.FastQueue;
|
||||
import com.plotsquared.sponge.util.block.SlowQueue;
|
||||
import com.plotsquared.sponge.util.block.SpongeLocalQueue;
|
||||
import com.plotsquared.sponge.uuid.SpongeLowerOfflineUUIDWrapper;
|
||||
import com.plotsquared.sponge.uuid.SpongeOnlineUUIDWrapper;
|
||||
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.spongepowered.api.Game;
|
||||
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.PluginContainer;
|
||||
import org.spongepowered.api.profile.GameProfileManager;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.world.gen.GenerationPopulator;
|
||||
import org.spongepowered.api.world.gen.WorldGenerator;
|
||||
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.",
|
||||
url = "https://github.com/IntellectualSites/PlotSquared", version = "3.3.3")
|
||||
public class SpongeMain implements IPlotMain {
|
||||
@ -364,14 +361,9 @@ public class SpongeMain implements IPlotMain {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotQueue<Chunk> initPlotQueue() {
|
||||
try {
|
||||
MainUtil.canSendChunk = true;
|
||||
return new FastQueue();
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new SlowQueue();
|
||||
public QueueProvider initBlockQueue() {
|
||||
MainUtil.canSendChunk = true;
|
||||
return QueueProvider.of(SpongeLocalQueue.class, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,19 +2,17 @@ package com.plotsquared.sponge.generator;
|
||||
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import com.intellectualcrafters.plot.generator.AugmentedUtils;
|
||||
import com.intellectualcrafters.plot.object.LazyResult;
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue;
|
||||
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.object.PlotBlock;
|
||||
import com.intellectualcrafters.plot.util.block.DelegateLocalBlockQueue;
|
||||
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.extent.ImmutableBiomeArea;
|
||||
import org.spongepowered.api.world.extent.MutableBlockVolume;
|
||||
import org.spongepowered.api.world.gen.GenerationPopulator;
|
||||
import org.spongepowered.api.world.gen.WorldGenerator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SpongeAugmentedGenerator implements GenerationPopulator {
|
||||
|
||||
private static SpongeAugmentedGenerator generator;
|
||||
@ -43,38 +41,28 @@ public class SpongeAugmentedGenerator implements GenerationPopulator {
|
||||
int bz = min.getZ();
|
||||
int cx = bx >> 4;
|
||||
int cz = bz >> 4;
|
||||
AugmentedUtils.generate(world.getName(), cx, cz, new LazyResult<PlotChunk<?>>() {
|
||||
AugmentedUtils.generate(world.getName(), cx, cz, new DelegateLocalBlockQueue(null) {
|
||||
@Override
|
||||
public PlotChunk<?> create() {
|
||||
ChunkWrapper wrap = SetQueue.IMP.new ChunkWrapper(world.getName(), cx, cz);
|
||||
return new PlotChunk<ChunkWrapper>(wrap) {
|
||||
@Override
|
||||
public ChunkWrapper getChunkAbs() {
|
||||
return getChunkWrapper();
|
||||
}
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
terrain.setBlock(bx + x, y, bz + z, SpongeUtil.getBlockState(id, data));
|
||||
}
|
||||
@Override
|
||||
public void setBiome(int x, int z, int biome) {
|
||||
// TODO FIXME
|
||||
}
|
||||
@Override
|
||||
public PlotChunk clone() {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
|
||||
}
|
||||
@Override
|
||||
public PlotChunk shallowClone() {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
|
||||
}
|
||||
@Override
|
||||
public void addToQueue() {}
|
||||
@Override
|
||||
public void flush(boolean fixLighting) {}
|
||||
};
|
||||
public boolean setBlock(int x, int y, int z, int id, int data) {
|
||||
terrain.setBlock(bx + x, y, bz + z, SpongeUtil.getBlockState(id, data));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotBlock getBlock(int x, int y, int z) {
|
||||
BlockState block = terrain.getBlock(bx + x, y, bz + z);
|
||||
return block == null ? PlotBlock.get(0, 0) : SpongeUtil.getPlotBlock(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, String biome) {
|
||||
return false; // TODO ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorld() {
|
||||
return world.getName();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,19 +1,17 @@
|
||||
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.intellectualcrafters.plot.PS;
|
||||
import com.intellectualcrafters.plot.generator.IndependentPlotGenerator;
|
||||
import com.intellectualcrafters.plot.object.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.object.PlotArea;
|
||||
import com.intellectualcrafters.plot.object.PseudoRandom;
|
||||
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 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 {
|
||||
|
||||
@ -36,7 +34,7 @@ public class SpongeTerrainGen implements GenerationPopulator {
|
||||
Vector3i min = terrain.getBlockMin();
|
||||
int cx = min.getX() >> 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
|
||||
GenChunk result = new GenChunk(terrain, null, wrap);
|
||||
// Catch any exceptions
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.plotsquared.sponge.util;
|
||||
|
||||
import com.intellectualcrafters.plot.config.Settings;
|
||||
import com.intellectualcrafters.plot.object.ConsolePlayer;
|
||||
import com.intellectualcrafters.plot.object.PlotMessage;
|
||||
import com.intellectualcrafters.plot.object.PlotPlayer;
|
||||
@ -139,7 +140,7 @@ public class SpongeChatManager extends ChatManager<Text.Builder> {
|
||||
|
||||
@Override
|
||||
public void send(PlotMessage plotMessage, PlotPlayer player) {
|
||||
if (player instanceof ConsolePlayer) {
|
||||
if (player instanceof ConsolePlayer || !Settings.Chat.INTERACTIVE) {
|
||||
player.sendMessage(plotMessage.$(this).build().toPlain());
|
||||
} else {
|
||||
((SpongePlayer) player).player.sendMessage(plotMessage.$(this).build());
|
||||
|
@ -1,60 +1,12 @@
|
||||
package com.plotsquared.sponge.util;
|
||||
|
||||
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.RunnableVal;
|
||||
import org.spongepowered.api.block.BlockState;
|
||||
import org.spongepowered.api.block.BlockTypes;
|
||||
import org.spongepowered.api.world.World;
|
||||
import com.intellectualcrafters.plot.util.expiry.PlotAnalysis;
|
||||
|
||||
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
|
||||
public void analyzeRegion(String world, RegionWrapper region, RunnableVal<PlotAnalysis> whenDone) {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,58 +1,88 @@
|
||||
package com.plotsquared.sponge.util.block;
|
||||
|
||||
import com.intellectualcrafters.plot.util.PlotChunk;
|
||||
import com.intellectualcrafters.plot.util.SetQueue.ChunkWrapper;
|
||||
import com.intellectualcrafters.plot.object.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 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.MutableBlockVolume;
|
||||
|
||||
public class GenChunk extends PlotChunk<Chunk> {
|
||||
public class GenChunk extends ScopedLocalBlockQueue {
|
||||
|
||||
private final MutableBlockVolume terrain;
|
||||
private final MutableBiomeArea biome;
|
||||
private final int bz;
|
||||
private final int bx;
|
||||
private final String world;
|
||||
|
||||
public boolean modified = false;
|
||||
|
||||
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.bz = wrap.z << 4;
|
||||
this.terrain = terrain;
|
||||
this.biome = biome;
|
||||
this.world = wrap.world;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunkAbs() {
|
||||
ChunkWrapper wrap = getChunkWrapper();
|
||||
return SpongeUtil.getWorld(wrap.world).getChunk(wrap.x << 4, 0, wrap.z << 4).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, int biome) {
|
||||
if (this.biome != null) {
|
||||
this.biome.setBiome(this.bx + x, this.bz + z, SpongeUtil.getBiome(biome));
|
||||
public void fillBiome(String biomeName) {
|
||||
if (this.biome == null) {
|
||||
return;
|
||||
}
|
||||
BiomeType biome = SpongeUtil.getBiome(biomeName.toUpperCase());
|
||||
for (int x = 0; x <= 15; x++) {
|
||||
for (int z = 0; z < 15; z++) {
|
||||
this.biome.setBiome(this.bx + x, this.bz + z, biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunkWrapper(ChunkWrapper loc) {
|
||||
super.setChunkWrapper(loc);
|
||||
public PlotBlock getBlock(int x, int y, int z) {
|
||||
return SpongeUtil.getPlotBlock(this.terrain.getBlock(this.bx + x, y, this.bz + z));
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlotChunk shallowClone() {
|
||||
public GenChunk shallowClone() {
|
||||
throw new UnsupportedOperationException("NOT IMPLEMENTED YET");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
BIN
fanciful-master.zip
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user