mirror of
https://github.com/Brettflan/WorldBorder.git
synced 2025-02-01 04:01:24 +01:00
Misc 1.14 updates:
* using "force loaded" chunk flag instead of canceling ChunkUnloadEvents, which is no longer possible as of Spigot 1.14 * replaced UUID lookup code with newer and slightly improved implementation * added new 1.14 wooden sign variations to safe open blocks list * fix for error if Fill was canceled or finished without actually loading any chunks * added notice to end of Trim recommending server restart
This commit is contained in:
parent
179d1cfda3
commit
e14d526541
@ -327,8 +327,6 @@ public class BorderData
|
|||||||
safeOpenBlocks.add(Material.WALL_TORCH);
|
safeOpenBlocks.add(Material.WALL_TORCH);
|
||||||
safeOpenBlocks.add(Material.REDSTONE_WIRE);
|
safeOpenBlocks.add(Material.REDSTONE_WIRE);
|
||||||
safeOpenBlocks.add(Material.WHEAT);
|
safeOpenBlocks.add(Material.WHEAT);
|
||||||
safeOpenBlocks.add(Material.SIGN);
|
|
||||||
safeOpenBlocks.add(Material.WALL_SIGN);
|
|
||||||
safeOpenBlocks.add(Material.LADDER);
|
safeOpenBlocks.add(Material.LADDER);
|
||||||
safeOpenBlocks.add(Material.LEVER);
|
safeOpenBlocks.add(Material.LEVER);
|
||||||
safeOpenBlocks.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE);
|
safeOpenBlocks.add(Material.LIGHT_WEIGHTED_PRESSURE_PLATE);
|
||||||
@ -376,6 +374,22 @@ public class BorderData
|
|||||||
safeOpenBlocks.add(Material.TALL_GRASS);
|
safeOpenBlocks.add(Material.TALL_GRASS);
|
||||||
safeOpenBlocks.add(Material.LARGE_FERN);
|
safeOpenBlocks.add(Material.LARGE_FERN);
|
||||||
safeOpenBlocks.add(Material.BEETROOTS);
|
safeOpenBlocks.add(Material.BEETROOTS);
|
||||||
|
try
|
||||||
|
{ // signs in 1.14 can be different wood types
|
||||||
|
safeOpenBlocks.add(Material.ACACIA_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.ACACIA_WALL_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.BIRCH_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.BIRCH_WALL_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.DARK_OAK_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.DARK_OAK_WALL_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.JUNGLE_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.JUNGLE_WALL_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.OAK_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.OAK_WALL_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.SPRUCE_SIGN);
|
||||||
|
safeOpenBlocks.add(Material.SPRUCE_WALL_SIGN);
|
||||||
|
}
|
||||||
|
catch (NoSuchFieldError ex) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
//these material IDs are ones we don't want to drop the player onto, like cactus or lava or fire or activated Ender portal
|
//these material IDs are ones we don't want to drop the player onto, like cactus or lava or fire or activated Ender portal
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
package com.wimbli.WorldBorder.UUID;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
import org.json.simple.parser.JSONParser;
|
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* code by evilmidget38
|
|
||||||
* from http://forums.bukkit.org/threads/player-name-uuid-fetcher.250926/
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class NameFetcher implements Callable<Map<UUID, String>>
|
|
||||||
{
|
|
||||||
private static final String PROFILE_URL = "https://sessionserver.mojang.com/session/minecraft/profile/";
|
|
||||||
private final JSONParser jsonParser = new JSONParser();
|
|
||||||
private final List<UUID> uuids;
|
|
||||||
public NameFetcher(List<UUID> uuids)
|
|
||||||
{
|
|
||||||
this.uuids = ImmutableList.copyOf(uuids);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<UUID, String> call() throws Exception
|
|
||||||
{
|
|
||||||
Map<UUID, String> uuidStringMap = new HashMap<UUID, String>();
|
|
||||||
for (UUID uuid: uuids)
|
|
||||||
{
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(PROFILE_URL+uuid.toString().replace("-", "")).openConnection();
|
|
||||||
JSONObject response = (JSONObject) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
|
|
||||||
String name = (String) response.get("name");
|
|
||||||
if (name == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String cause = (String) response.get("cause");
|
|
||||||
String errorMessage = (String) response.get("errorMessage");
|
|
||||||
if (cause != null && cause.length() > 0)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException(errorMessage);
|
|
||||||
}
|
|
||||||
uuidStringMap.put(uuid, name);
|
|
||||||
}
|
|
||||||
return uuidStringMap;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +1,149 @@
|
|||||||
package com.wimbli.WorldBorder.UUID;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.json.simple.JSONArray;
|
|
||||||
import org.json.simple.JSONObject;
|
|
||||||
import org.json.simple.parser.JSONParser;
|
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* code by evilmidget38
|
* This code mostly taken from https://gist.github.com/Jofkos/d0c469528b032d820f42
|
||||||
* from http://forums.bukkit.org/threads/player-name-uuid-fetcher.250926/
|
|
||||||
* slightly modified to fix name case mismatches for single name lookup
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class UUIDFetcher implements Callable<Map<String, UUID>>
|
package com.wimbli.WorldBorder.UUID;
|
||||||
{
|
|
||||||
private static final double PROFILES_PER_REQUEST = 100;
|
|
||||||
private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft";
|
|
||||||
private final JSONParser jsonParser = new JSONParser();
|
|
||||||
private final List<String> names;
|
|
||||||
private final boolean rateLimiting;
|
|
||||||
|
|
||||||
public UUIDFetcher(List<String> names, boolean rateLimiting)
|
import java.io.BufferedReader;
|
||||||
{
|
import java.io.InputStreamReader;
|
||||||
this.names = ImmutableList.copyOf(names);
|
import java.net.HttpURLConnection;
|
||||||
this.rateLimiting = rateLimiting;
|
import java.net.URL;
|
||||||
}
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public UUIDFetcher(List<String> names)
|
import com.google.gson.Gson;
|
||||||
{
|
import com.google.gson.GsonBuilder;
|
||||||
this(names, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, UUID> call() throws Exception
|
|
||||||
{
|
|
||||||
Map<String, UUID> uuidMap = new HashMap<String, UUID>();
|
|
||||||
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
|
|
||||||
for (int i = 0; i < requests; i++)
|
|
||||||
{
|
|
||||||
HttpURLConnection connection = createConnection();
|
|
||||||
String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
|
|
||||||
writeBody(connection, body);
|
|
||||||
JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream()));
|
|
||||||
for (Object profile : array)
|
|
||||||
{
|
|
||||||
JSONObject jsonProfile = (JSONObject) profile;
|
|
||||||
String id = (String) jsonProfile.get("id");
|
|
||||||
String name = (String) jsonProfile.get("name");
|
|
||||||
UUID uuid = UUIDFetcher.getUUID(id);
|
|
||||||
uuidMap.put(name.toLowerCase(), uuid);
|
|
||||||
}
|
|
||||||
if (rateLimiting && i != requests - 1)
|
|
||||||
{
|
|
||||||
Thread.sleep(100L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uuidMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeBody(HttpURLConnection connection, String body) throws Exception
|
public class UUIDFetcher {
|
||||||
{
|
|
||||||
OutputStream stream = connection.getOutputStream();
|
/**
|
||||||
stream.write(body.getBytes());
|
* Date when name changes were introduced
|
||||||
stream.flush();
|
* @see UUIDFetcher#getUUIDAt(String, long)
|
||||||
stream.close();
|
*/
|
||||||
}
|
public static final long FEBRUARY_2015 = 1422748800000L;
|
||||||
|
|
||||||
|
|
||||||
|
private static Gson gson = new GsonBuilder().registerTypeAdapter(UUID.class, new UUIDTypeAdapter()).create();
|
||||||
|
|
||||||
|
private static final String UUID_URL = "https://api.mojang.com/users/profiles/minecraft/%s?at=%d";
|
||||||
|
private static final String NAME_URL = "https://api.mojang.com/user/profiles/%s/names";
|
||||||
|
|
||||||
private static HttpURLConnection createConnection() throws Exception
|
private static Map<String, UUID> uuidCache = new HashMap<String, UUID>();
|
||||||
{
|
private static Map<UUID, String> nameCache = new HashMap<UUID, String>();
|
||||||
URL url = new URL(PROFILE_URL);
|
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json");
|
|
||||||
connection.setUseCaches(false);
|
|
||||||
connection.setDoInput(true);
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
return connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UUID getUUID(String id)
|
private static ExecutorService pool = Executors.newCachedThreadPool();
|
||||||
{
|
|
||||||
return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" +id.substring(20, 32));
|
private String name;
|
||||||
}
|
private UUID id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the uuid asynchronously and passes it to the consumer
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @param action Do what you want to do with the uuid her
|
||||||
|
*/
|
||||||
|
public static void getUUID(String name, Consumer<UUID> action) {
|
||||||
|
pool.execute(() -> action.accept(getUUID(name)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the uuid synchronously and returns it
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @return The uuid
|
||||||
|
*/
|
||||||
|
public static UUID getUUID(String name) {
|
||||||
|
return getUUIDAt(name, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the uuid synchronously for a specified name and time and passes the result to the consumer
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @param timestamp Time when the player had this name in milliseconds
|
||||||
|
* @param action Do what you want to do with the uuid her
|
||||||
|
*/
|
||||||
|
public static void getUUIDAt(String name, long timestamp, Consumer<UUID> action) {
|
||||||
|
pool.execute(() -> action.accept(getUUIDAt(name, timestamp)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the uuid synchronously for a specified name and time
|
||||||
|
*
|
||||||
|
* @param name The name
|
||||||
|
* @param timestamp Time when the player had this name in milliseconds
|
||||||
|
* @see UUIDFetcher#FEBRUARY_2015
|
||||||
|
*/
|
||||||
|
public static UUID getUUIDAt(String name, long timestamp) {
|
||||||
|
name = name.toLowerCase();
|
||||||
|
if (uuidCache.containsKey(name)) {
|
||||||
|
return uuidCache.get(name);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(String.format(UUID_URL, name, timestamp/1000)).openConnection();
|
||||||
|
connection.setReadTimeout(5000);
|
||||||
|
UUIDFetcher data = gson.fromJson(new BufferedReader(new InputStreamReader(connection.getInputStream())), UUIDFetcher.class);
|
||||||
|
|
||||||
|
uuidCache.put(name, data.id);
|
||||||
|
nameCache.put(data.id, data.name);
|
||||||
|
|
||||||
public static byte[] toBytes(UUID uuid)
|
return data.id;
|
||||||
{
|
} catch (Exception e) {
|
||||||
ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]);
|
e.printStackTrace();
|
||||||
byteBuffer.putLong(uuid.getMostSignificantBits());
|
}
|
||||||
byteBuffer.putLong(uuid.getLeastSignificantBits());
|
|
||||||
return byteBuffer.array();
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the name asynchronously and passes it to the consumer
|
||||||
|
*
|
||||||
|
* @param uuid The uuid
|
||||||
|
* @param action Do what you want to do with the name her
|
||||||
|
*/
|
||||||
|
public static void getName(UUID uuid, Consumer<String> action) {
|
||||||
|
pool.execute(() -> action.accept(getName(uuid)));
|
||||||
|
}
|
||||||
|
|
||||||
public static UUID fromBytes(byte[] array)
|
/**
|
||||||
{
|
* Fetches the name synchronously and returns it
|
||||||
if (array.length != 16) {
|
*
|
||||||
throw new IllegalArgumentException("Illegal byte array length: " + array.length);
|
* @param uuid The uuid
|
||||||
}
|
* @return The name
|
||||||
ByteBuffer byteBuffer = ByteBuffer.wrap(array);
|
*/
|
||||||
long mostSignificant = byteBuffer.getLong();
|
public static String getName(UUID uuid) {
|
||||||
long leastSignificant = byteBuffer.getLong();
|
if (nameCache.containsKey(uuid)) {
|
||||||
return new UUID(mostSignificant, leastSignificant);
|
return nameCache.get(uuid);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) new URL(String.format(NAME_URL, UUIDTypeAdapter.fromUUID(uuid))).openConnection();
|
||||||
|
connection.setReadTimeout(5000);
|
||||||
|
UUIDFetcher[] nameHistory = gson.fromJson(new BufferedReader(new InputStreamReader(connection.getInputStream())), UUIDFetcher[].class);
|
||||||
|
UUIDFetcher currentNameData = nameHistory[nameHistory.length - 1];
|
||||||
|
|
||||||
public static UUID getUUIDOf(String name) throws Exception
|
uuidCache.put(currentNameData.name.toLowerCase(), uuid);
|
||||||
{
|
nameCache.put(uuid, currentNameData.name);
|
||||||
return new UUIDFetcher(Arrays.asList(name)).call().get(name.toLowerCase());
|
|
||||||
}
|
return currentNameData.name;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<UUID, String> getNameList(ArrayList<UUID> uuids) {
|
||||||
|
Map<UUID, String> uuidStringMap = new HashMap<>();
|
||||||
|
for (UUID uuid: uuids)
|
||||||
|
{
|
||||||
|
uuidStringMap.put(uuid, getName(uuid));
|
||||||
|
}
|
||||||
|
return uuidStringMap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* This code from: https://github.com/eitetu/minecraft-server/blob/master/src/main/java/com/eitetu/minecraft/server/util/UUIDTypeAdapter.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.wimbli.WorldBorder.UUID;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
|
|
||||||
|
public class UUIDTypeAdapter extends TypeAdapter<UUID> {
|
||||||
|
public void write(JsonWriter out, UUID value) throws IOException {
|
||||||
|
out.value(fromUUID(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID read(JsonReader in) throws IOException {
|
||||||
|
return fromString(in.nextString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String fromUUID(UUID value) {
|
||||||
|
return value.toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UUID fromString(String input) {
|
||||||
|
return UUID.fromString(input.replaceFirst(
|
||||||
|
"(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"));
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,8 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.event.player.PlayerPortalEvent;
|
import org.bukkit.event.player.PlayerPortalEvent;
|
||||||
import org.bukkit.event.world.ChunkLoadEvent;
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
|
||||||
public class WBListener implements Listener
|
public class WBListener implements Listener
|
||||||
@ -73,21 +73,21 @@ public class WBListener implements Listener
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if there is a fill task running, and if yes, if it's for the
|
* Check if there is a fill task running, and if yes, if it's for the
|
||||||
* world that the unload event refers to and if the chunk should be
|
* world that the unload event refers to, set "force loaded" flag off
|
||||||
* kept in memory because generation still needs it.
|
* and track if chunk was somehow on unload prevention list
|
||||||
*/
|
*/
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onChunkUnload(ChunkUnloadEvent e)
|
public void onChunkUnload(ChunkUnloadEvent e)
|
||||||
{
|
{
|
||||||
if (Config.fillTask!=null)
|
if (Config.fillTask == null)
|
||||||
{
|
return;
|
||||||
Chunk chunk=e.getChunk();
|
|
||||||
if (e.getWorld() == Config.fillTask.getWorld()
|
Chunk chunk = e.getChunk();
|
||||||
&& Config.fillTask.chunkOnUnloadPreventionList(chunk.getX(), chunk.getZ()))
|
if (e.getWorld() != Config.fillTask.getWorld())
|
||||||
{
|
return;
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
// just to be on the safe side, in case it's still set at this point somehow
|
||||||
}
|
chunk.setForceLoaded(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,10 @@ public class WorldFillTask implements Runnable
|
|||||||
for (CoordXZ unload: chunksToUnload)
|
for (CoordXZ unload: chunksToUnload)
|
||||||
{
|
{
|
||||||
if (!chunkOnUnloadPreventionList(unload.x, unload.z))
|
if (!chunkOnUnloadPreventionList(unload.x, unload.z))
|
||||||
|
{
|
||||||
|
world.setChunkForceLoaded(unload.x, unload.z, false);
|
||||||
world.unloadChunkRequest(unload.x, unload.z);
|
world.unloadChunkRequest(unload.x, unload.z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put some damper on chunksPerRun. We don't want the queue to be too
|
// Put some damper on chunksPerRun. We don't want the queue to be too
|
||||||
@ -312,6 +315,7 @@ public class WorldFillTask implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
world.setChunkForceLoaded(x, z, true); // toggle "force loaded" flag on for chunk to prevent it from being unloaded while we need it
|
||||||
pendingChunks.put(PaperLib.getChunkAtAsync(world, x, z, true), new CoordXZ(x, z));
|
pendingChunks.put(PaperLib.getChunkAtAsync(world, x, z, true), new CoordXZ(x, z));
|
||||||
|
|
||||||
// There need to be enough nearby chunks loaded to make the server populate a chunk with trees, snow, etc.
|
// There need to be enough nearby chunks loaded to make the server populate a chunk with trees, snow, etc.
|
||||||
@ -319,10 +323,12 @@ public class WorldFillTask implements Runnable
|
|||||||
int popX = !isZLeg ? x : (x + (isNeg ? -1 : 1));
|
int popX = !isZLeg ? x : (x + (isNeg ? -1 : 1));
|
||||||
int popZ = isZLeg ? z : (z + (!isNeg ? -1 : 1));
|
int popZ = isZLeg ? z : (z + (!isNeg ? -1 : 1));
|
||||||
|
|
||||||
|
world.setChunkForceLoaded(popX, popZ, true);
|
||||||
pendingChunks.put(PaperLib.getChunkAtAsync(world, popX, popZ, false), new CoordXZ(popX, popZ));
|
pendingChunks.put(PaperLib.getChunkAtAsync(world, popX, popZ, false), new CoordXZ(popX, popZ));
|
||||||
preventUnload.add(new UnloadDependency(popX, popZ, x, z));
|
preventUnload.add(new UnloadDependency(popX, popZ, x, z));
|
||||||
|
|
||||||
// make sure the previous chunk in our spiral is loaded as well (might have already existed and been skipped over)
|
// make sure the previous chunk in our spiral is loaded as well (might have already existed and been skipped over)
|
||||||
|
world.setChunkForceLoaded(lastChunk.x, lastChunk.z, true);
|
||||||
pendingChunks.put(PaperLib.getChunkAtAsync(world, lastChunk.x, lastChunk.z, false), new CoordXZ(lastChunk.x, lastChunk.z)); // <-- new CoordXZ as lastChunk isn't immutable
|
pendingChunks.put(PaperLib.getChunkAtAsync(world, lastChunk.x, lastChunk.z, false), new CoordXZ(lastChunk.x, lastChunk.z)); // <-- new CoordXZ as lastChunk isn't immutable
|
||||||
preventUnload.add(new UnloadDependency(lastChunk.x, lastChunk.z, x, z));
|
preventUnload.add(new UnloadDependency(lastChunk.x, lastChunk.z, x, z));
|
||||||
|
|
||||||
@ -437,13 +443,17 @@ public class WorldFillTask implements Runnable
|
|||||||
server = null;
|
server = null;
|
||||||
|
|
||||||
// go ahead and unload any chunks we still have loaded
|
// go ahead and unload any chunks we still have loaded
|
||||||
// Set preventUnload to emptry first so the ChunkUnloadEvent Listener
|
// Set preventUnload to empty first so the ChunkUnloadEvent Listener
|
||||||
// doesn't get in our way
|
// doesn't get in our way
|
||||||
Set<UnloadDependency> tempPreventUnload = preventUnload;
|
if (preventUnload != null)
|
||||||
preventUnload = null;
|
|
||||||
for (UnloadDependency entry: tempPreventUnload)
|
|
||||||
{
|
{
|
||||||
world.unloadChunkRequest(entry.neededX, entry.neededZ);
|
Set<UnloadDependency> tempPreventUnload = preventUnload;
|
||||||
|
preventUnload = null;
|
||||||
|
for (UnloadDependency entry: tempPreventUnload)
|
||||||
|
{
|
||||||
|
world.setChunkForceLoaded(entry.neededX, entry.neededZ, false);
|
||||||
|
world.unloadChunkRequest(entry.neededX, entry.neededZ);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +363,10 @@ public class WorldTrimTask implements Runnable
|
|||||||
if (taskID != -1)
|
if (taskID != -1)
|
||||||
server.getScheduler().cancelTask(taskID);
|
server.getScheduler().cancelTask(taskID);
|
||||||
server = null;
|
server = null;
|
||||||
|
|
||||||
|
sendMessage("NOTICE: it is recommended that you restart your server after a Trim, to be on the safe side.");
|
||||||
|
if (DynMapFeatures.renderEnabled())
|
||||||
|
sendMessage("This especially true with DynMap. You should also run a fullrender in DynMap for the trimmed world after restarting, so trimmed chunks are updated on the map.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this task still valid/workable?
|
// is this task still valid/workable?
|
||||||
|
@ -65,7 +65,7 @@ public class CmdBypass extends WBCmd
|
|||||||
// only do UUID lookup using Mojang server if specified player isn't online
|
// only do UUID lookup using Mojang server if specified player isn't online
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uPlayer = UUIDFetcher.getUUIDOf(sPlayer);
|
uPlayer = UUIDFetcher.getUUID(sPlayer);
|
||||||
}
|
}
|
||||||
catch(Exception ex)
|
catch(Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -10,7 +10,7 @@ import org.bukkit.command.*;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import com.wimbli.WorldBorder.*;
|
import com.wimbli.WorldBorder.*;
|
||||||
import com.wimbli.WorldBorder.UUID.NameFetcher;
|
import com.wimbli.WorldBorder.UUID.UUIDFetcher;
|
||||||
|
|
||||||
|
|
||||||
public class CmdBypasslist extends WBCmd
|
public class CmdBypasslist extends WBCmd
|
||||||
@ -42,8 +42,7 @@ public class CmdBypasslist extends WBCmd
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NameFetcher fetcher = new NameFetcher(uuids);
|
Map<UUID, String> names = UUIDFetcher.getNameList(uuids);
|
||||||
Map<UUID, String> names = fetcher.call();
|
|
||||||
String nameString = names.values().toString();
|
String nameString = names.values().toString();
|
||||||
|
|
||||||
sender.sendMessage("Players with border bypass enabled: " + nameString.substring(1, nameString.length() - 1));
|
sender.sendMessage("Players with border bypass enabled: " + nameString.substring(1, nameString.length() - 1));
|
||||||
|
Loading…
Reference in New Issue
Block a user