Update to Minecraft 1.14-pre5

By: md_5 <git@md-5.net>
This commit is contained in:
CraftBukkit/Spigot
2019-04-23 12:00:00 +10:00
parent 0e98365784
commit a0f2b74c8d
560 changed files with 10642 additions and 10867 deletions

View File

@@ -1,354 +0,0 @@
package org.bukkit.craftbukkit.util;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import org.apache.commons.lang.Validate;
/**
* Executes tasks using a multi-stage process executor. Synchronous executions are via {@link AsynchronousExecutor#finishActive()} or the {@link AsynchronousExecutor#get(Object)} methods.
* <li \> Stage 1 creates the object from a parameter, and is usually called asynchronously.
* <li \> Stage 2 takes the parameter and object from stage 1 and does any synchronous processing to prepare it.
* <li \> Stage 3 takes the parameter and object from stage 1, as well as a callback that was registered, and performs any synchronous calculations.
*
* @param <P> The type of parameter you provide to make the object that will be created. It should implement {@link Object#hashCode()} and {@link Object#equals(Object)} if you want to get the value early.
* @param <T> The type of object you provide. This is created in stage 1, and passed to stage 2, 3, and returned if get() is called.
* @param <C> The type of callback you provide. You may register many of these to be passed to the provider in stage 3, one at a time.
* @param <E> A type of exception you may throw and expect to be handled by the main thread
* @author Wesley Wolfe (c) 2012, 2014
*/
public final class AsynchronousExecutor<P, T, C, E extends Throwable> {
public static interface CallBackProvider<P, T, C, E extends Throwable> extends ThreadFactory {
/**
* Normally an asynchronous call, but can be synchronous
*
* @param parameter parameter object provided
* @return the created object
*/
T callStage1(P parameter) throws E;
/**
* Synchronous call
*
* @param parameter parameter object provided
* @param object the previously created object
*/
void callStage2(P parameter, T object) throws E;
/**
* Synchronous call, called multiple times, once per registered callback
*
* @param parameter parameter object provided
* @param object the previously created object
* @param callback the current callback to execute
*/
void callStage3(P parameter, T object, C callback) throws E;
}
@SuppressWarnings("rawtypes")
static final AtomicIntegerFieldUpdater STATE_FIELD = AtomicIntegerFieldUpdater.newUpdater(AsynchronousExecutor.Task.class, "state");
@SuppressWarnings({ "unchecked", "rawtypes" })
private static boolean set(AsynchronousExecutor.Task $this, int expected, int value) {
return STATE_FIELD.compareAndSet($this, expected, value);
}
class Task implements Runnable {
static final int PENDING = 0x0;
static final int STAGE_1_ASYNC = PENDING + 1;
static final int STAGE_1_SYNC = STAGE_1_ASYNC + 1;
static final int STAGE_1_COMPLETE = STAGE_1_SYNC + 1;
static final int FINISHED = STAGE_1_COMPLETE + 1;
volatile int state = PENDING;
final P parameter;
T object;
final List<C> callbacks = new LinkedList<C>();
E t = null;
Task(final P parameter) {
this.parameter = parameter;
}
public void run() {
if (initAsync()) {
finished.add(this);
}
}
boolean initAsync() {
if (set(this, PENDING, STAGE_1_ASYNC)) {
boolean ret = true;
try {
init();
} finally {
if (set(this, STAGE_1_ASYNC, STAGE_1_COMPLETE)) {
// No one is/will be waiting
} else {
// We know that the sync thread will be waiting
synchronized (this) {
if (state != STAGE_1_SYNC) {
// They beat us to the synchronized block
this.notifyAll();
} else {
// We beat them to the synchronized block
}
state = STAGE_1_COMPLETE; // They're already synchronized, atomic locks are not needed
}
// We want to return false, because we know a synchronous task already handled the finish()
ret = false; // Don't return inside finally; VERY bad practice.
}
}
return ret;
} else {
return false;
}
}
void initSync() {
if (set(this, PENDING, STAGE_1_COMPLETE)) {
// If we succeed that variable switch, good as done
init();
} else if (set(this, STAGE_1_ASYNC, STAGE_1_SYNC)) {
// Async thread is running, but this shouldn't be likely; we need to sync to wait on them because of it.
synchronized (this) {
if (set(this, STAGE_1_SYNC, PENDING)) { // They might NOT synchronized yet, atomic lock IS needed
// We are the first into the lock
while (state != STAGE_1_COMPLETE) {
try {
this.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Unable to handle interruption on " + parameter, e);
}
}
} else {
// They beat us to the synchronized block
}
}
} else {
// Async thread is not pending, the more likely situation for a task not pending
}
}
@SuppressWarnings("unchecked")
void init() {
try {
object = provider.callStage1(parameter);
} catch (final Throwable t) {
this.t = (E) t;
}
}
@SuppressWarnings("unchecked")
T get() throws E {
initSync();
if (callbacks.isEmpty()) {
// 'this' is a placeholder to prevent callbacks from being empty during finish call
// See get method below
callbacks.add((C) this);
}
finish();
return object;
}
void finish() throws E {
switch (state) {
default:
case PENDING:
case STAGE_1_ASYNC:
case STAGE_1_SYNC:
throw new IllegalStateException("Attempting to finish unprepared(" + state + ") task(" + parameter + ")");
case STAGE_1_COMPLETE:
try {
if (t != null) {
throw t;
}
if (callbacks.isEmpty()) {
return;
}
final CallBackProvider<P, T, C, E> provider = AsynchronousExecutor.this.provider;
final P parameter = this.parameter;
final T object = this.object;
provider.callStage2(parameter, object);
for (C callback : callbacks) {
if (callback == this) {
// 'this' is a placeholder to prevent callbacks from being empty on a get() call
// See get method above
continue;
}
provider.callStage3(parameter, object, callback);
}
} finally {
tasks.remove(parameter);
state = FINISHED;
}
case FINISHED:
}
}
boolean drop() {
if (set(this, PENDING, FINISHED)) {
// If we succeed that variable switch, good as forgotten
tasks.remove(parameter);
return true;
} else {
// We need the async thread to finish normally to properly dispose of the task
return false;
}
}
}
final CallBackProvider<P, T, C, E> provider;
final Queue<Task> finished = new ConcurrentLinkedQueue<Task>();
final Map<P, Task> tasks = new HashMap<P, Task>();
final ThreadPoolExecutor pool;
/**
* Uses a thread pool to pass executions to the provider.
* @see AsynchronousExecutor
*/
public AsynchronousExecutor(final CallBackProvider<P, T, C, E> provider, final int coreSize) {
Validate.notNull(provider, "Provider cannot be null");
this.provider = provider;
// We have an unbound queue size so do not need a max thread size
pool = new ThreadPoolExecutor(coreSize, Integer.MAX_VALUE, 60l, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), provider);
}
/**
* Adds a callback to the parameter provided, adding parameter to the queue if needed.
* <p>
* This should always be synchronous.
*/
public void add(P parameter, C callback) {
Task task = tasks.get(parameter);
if (task == null) {
tasks.put(parameter, task = new Task(parameter));
pool.execute(task);
}
task.callbacks.add(callback);
}
/**
* This removes a particular callback from the specified parameter.
* <p>
* If no callbacks remain for a given parameter, then the {@link CallBackProvider CallBackProvider's} stages may be omitted from execution.
* Stage 3 will have no callbacks, stage 2 will be skipped unless a {@link #get(Object)} is used, and stage 1 will be avoided on a best-effort basis.
* <p>
* Subsequent calls to {@link #getSkipQueue(Object)} will always work.
* <p>
* Subsequent calls to {@link #get(Object)} might work.
* <p>
* This should always be synchronous
* @return true if no further execution for the parameter is possible, such that, no exceptions will be thrown in {@link #finishActive()} for the parameter, and {@link #get(Object)} will throw an {@link IllegalStateException}, false otherwise
* @throws IllegalStateException if parameter is not in the queue anymore
* @throws IllegalStateException if the callback was not specified for given parameter
*/
public boolean drop(P parameter, C callback) throws IllegalStateException {
final Task task = tasks.get(parameter);
if (task == null) {
return true;
}
if (!task.callbacks.remove(callback)) {
throw new IllegalStateException("Unknown " + callback + " for " + parameter);
}
if (task.callbacks.isEmpty()) {
return task.drop();
}
return false;
}
/**
* This method attempts to skip the waiting period for said parameter.
* <p>
* This should always be synchronous.
* @throws IllegalStateException if the parameter is not in the queue anymore, or sometimes if called from asynchronous thread
*/
public T get(P parameter) throws E, IllegalStateException {
final Task task = tasks.get(parameter);
if (task == null) {
throw new IllegalStateException("Unknown " + parameter);
}
return task.get();
}
/**
* Processes a parameter as if it was in the queue, without ever passing to another thread.
*/
public T getSkipQueue(P parameter) throws E {
return skipQueue(parameter);
}
/**
* Processes a parameter as if it was in the queue, without ever passing to another thread.
*/
public T getSkipQueue(P parameter, C callback) throws E {
final T object = skipQueue(parameter);
provider.callStage3(parameter, object, callback);
return object;
}
/**
* Processes a parameter as if it was in the queue, without ever passing to another thread.
*/
public T getSkipQueue(P parameter, C...callbacks) throws E {
final CallBackProvider<P, T, C, E> provider = this.provider;
final T object = skipQueue(parameter);
for (C callback : callbacks) {
provider.callStage3(parameter, object, callback);
}
return object;
}
/**
* Processes a parameter as if it was in the queue, without ever passing to another thread.
*/
public T getSkipQueue(P parameter, Iterable<C> callbacks) throws E {
final CallBackProvider<P, T, C, E> provider = this.provider;
final T object = skipQueue(parameter);
for (C callback : callbacks) {
provider.callStage3(parameter, object, callback);
}
return object;
}
private T skipQueue(P parameter) throws E {
Task task = tasks.get(parameter);
if (task != null) {
return task.get();
}
T object = provider.callStage1(parameter);
provider.callStage2(parameter, object);
return object;
}
/**
* This is the 'heartbeat' that should be called synchronously to finish any pending tasks
*/
public void finishActive() throws E {
final Queue<Task> finished = this.finished;
while (!finished.isEmpty()) {
finished.poll().finish();
}
}
public void setActiveThreads(final int coreSize) {
pool.setCorePoolSize(coreSize);
}
}

View File

@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.util;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.IBlockData;
@@ -38,6 +39,10 @@ public class BlockStateListPopulator extends DummyGeneratorAccess {
}
}
public Set<BlockPosition> getBlocks() {
return list.keySet();
}
public List<CraftBlockState> getList() {
return new ArrayList<>(list.values());
}

View File

@@ -140,6 +140,28 @@ public class Commodore
{
if ( modern )
{
if ( owner.equals( "org/bukkit/Material" ) )
{
switch ( name )
{
case "CACTUS_GREEN":
name = "GREEN_DYE";
break;
case "DANDELION_YELLOW":
name = "YELLOW_DYE";
break;
case "ROSE_RED":
name = "RED_DYE";
break;
case "SIGN":
name = "OAK_SIGN";
break;
case "WALL_SIGN":
name = "OAK_WALL_SIGN";
break;
}
}
super.visitFieldInsn( opcode, owner, name, desc );
return;
}

View File

@@ -43,7 +43,7 @@ import org.bukkit.material.MaterialData;
public class CraftLegacy {
private static final Map<Byte, Material> SPAWN_EGGS = new HashMap<>();
private static final Set<String> whitelistedStates = new HashSet<>(Arrays.asList("explode", "check_decay", "decayable"));
private static final Set<String> whitelistedStates = new HashSet<>(Arrays.asList("explode", "check_decay", "decayable", "facing"));
private static final Map<MaterialData, Item> materialToItem = new HashMap<>(16384);
private static final Map<Item, MaterialData> itemToMaterial = new HashMap<>(1024);
private static final Map<MaterialData, IBlockData> materialToData = new HashMap<>(4096);
@@ -311,7 +311,7 @@ public class CraftLegacy {
SPAWN_EGGS.put((byte) EntityType.PIG_ZOMBIE.getTypeId(), Material.ZOMBIE_PIGMAN_SPAWN_EGG);
SPAWN_EGGS.put((byte) EntityType.ZOMBIE_VILLAGER.getTypeId(), Material.ZOMBIE_VILLAGER_SPAWN_EGG);
DispenserRegistry.c();
DispenserRegistry.init();
for (Material material : Material.values()) {
if (!material.isLegacy()) {
@@ -324,11 +324,11 @@ public class CraftLegacy {
MaterialData matData = new MaterialData(material, data);
Dynamic blockTag = DataConverterFlattenData.b(material.getId() << 4 | data);
// TODO: better skull conversion, chests
if (blockTag.getString("Name").contains("%%FILTER_ME%%")) {
if (blockTag.get("Name").asString("").contains("%%FILTER_ME%%")) {
continue;
}
String name = blockTag.getString("Name");
String name = blockTag.get("Name").asString("");
// TODO: need to fix
if (name.equals("minecraft:portal")) {
name = "minecraft:nether_portal";
@@ -341,9 +341,9 @@ public class CraftLegacy {
IBlockData blockData = block.getBlockData();
BlockStateList states = block.getStates();
Optional<Dynamic> propMap = blockTag.get("Properties");
Optional<NBTTagCompound> propMap = blockTag.getElement("Properties");
if (propMap.isPresent()) {
NBTTagCompound properties = (NBTTagCompound) propMap.get().getValue();
NBTTagCompound properties = propMap.get();
for (String dataKey : properties.getKeys()) {
IBlockState state = states.a(dataKey);
@@ -402,7 +402,7 @@ public class CraftLegacy {
Dynamic<NBTBase> converted = DataConverterRegistry.a().update(DataConverterTypes.ITEM_STACK, new Dynamic<NBTBase>(DynamicOpsNBT.a, stack), -1, CraftMagicNumbers.INSTANCE.getDataVersion());
String newId = converted.getString("id");
String newId = converted.get("id").asString("");
// Recover spawn eggs with invalid data
if (newId.equals("minecraft:spawn_egg")) {
newId = "minecraft:pig_spawn_egg";

View File

@@ -1,9 +1,11 @@
package org.bukkit.craftbukkit.util;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.Dynamic;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
@@ -16,13 +18,18 @@ import java.util.logging.Logger;
import net.minecraft.server.AdvancementDataWorld;
import net.minecraft.server.Block;
import net.minecraft.server.ChatDeserializer;
import net.minecraft.server.DataConverterRegistry;
import net.minecraft.server.DataConverterTypes;
import net.minecraft.server.DynamicOpsNBT;
import net.minecraft.server.IBlockData;
import net.minecraft.server.IRegistry;
import net.minecraft.server.Item;
import net.minecraft.server.MinecraftKey;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.MojangsonParser;
import net.minecraft.server.NBTBase;
import net.minecraft.server.NBTTagCompound;
import net.minecraft.server.SharedConstants;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -74,19 +81,22 @@ public final class CraftMagicNumbers implements UnsafeValues {
private static final Map<Material, Block> MATERIAL_BLOCK = new HashMap<>();
static {
for (Block block : (Iterable<Block>) IRegistry.BLOCK) { // Eclipse fail
for (Block block : IRegistry.BLOCK) {
BLOCK_MATERIAL.put(block, Material.getMaterial(IRegistry.BLOCK.getKey(block).getKey().toUpperCase(Locale.ROOT)));
}
for (Item item : (Iterable<Item>) IRegistry.ITEM) { // Eclipse fail
for (Item item : IRegistry.ITEM) {
ITEM_MATERIAL.put(item, Material.getMaterial(IRegistry.ITEM.getKey(item).getKey().toUpperCase(Locale.ROOT)));
}
for (Material material : Material.values()) {
MinecraftKey key = key(material);
// TODO: only register if block/item?
MATERIAL_ITEM.put(material, IRegistry.ITEM.get(key));
MATERIAL_BLOCK.put(material, IRegistry.BLOCK.get(key));
IRegistry.ITEM.getOptional(key).ifPresent((item) -> {
MATERIAL_ITEM.put(material, item);
});
IRegistry.BLOCK.getOptional(key).ifPresent((block) -> {
MATERIAL_BLOCK.put(material, block);
});
}
}
@@ -144,6 +154,24 @@ public final class CraftMagicNumbers implements UnsafeValues {
return CraftBlockData.fromData(getBlock(material, data));
}
@Override
public Material getMaterial(String material, int version) {
Preconditions.checkArgument(version <= this.getDataVersion(), "Newer version! Server downgrades are not supported!");
// Fastpath up to date materials
if (version == this.getDataVersion()) {
return Material.getMaterial(material);
}
NBTTagCompound stack = new NBTTagCompound();
stack.setString("id", "minecraft:" + material.toLowerCase(Locale.ROOT));
Dynamic<NBTBase> converted = DataConverterRegistry.a().update(DataConverterTypes.ITEM_STACK, new Dynamic<>(DynamicOpsNBT.a, stack), version, this.getDataVersion());
String newId = converted.get("id").asString("");
return Material.matchMaterial(newId);
}
/**
* This string should be changed if the NMS mappings do.
*
@@ -160,12 +188,12 @@ public final class CraftMagicNumbers implements UnsafeValues {
* @return string
*/
public String getMappingsVersion() {
return "7dd4b3ec31629620c41553e5c142e454";
return "8b7fe9012a93b36df04844a6c990de27";
}
@Override
public int getDataVersion() {
return 1631;
return SharedConstants.a().getWorldVersion();
}
@Override
@@ -222,9 +250,11 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override
public void checkSupported(PluginDescriptionFile pdf) throws InvalidPluginException {
if (pdf.getAPIVersion() != null) {
if (!pdf.getAPIVersion().equals("1.13")) {
if (!pdf.getAPIVersion().equals("1.13") && !pdf.getAPIVersion().equals("1.14")) {
throw new InvalidPluginException("Unsupported API version " + pdf.getAPIVersion());
}
} else {
Bukkit.getLogger().log(Level.WARNING, "Plugin " + pdf.getFullName() + " does not specify an api-version.");
}
}

View File

@@ -34,7 +34,7 @@ public class CraftNBTTagConfigSerializer {
} else if (base instanceof NBTTagList) {
List<Object> baseList = new ArrayList<>();
for (int i = 0; i < ((NBTList) base).size(); i++) {
baseList.add(serialize(((NBTList) base).get(i)));
baseList.add(serialize((NBTBase) ((NBTList) base).get(i)));
}
return baseList;

View File

@@ -10,6 +10,8 @@ import org.bukkit.util.Vector;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.MovingObjectPosition;
import net.minecraft.server.MovingObjectPosition.EnumMovingObjectType;
import net.minecraft.server.MovingObjectPositionBlock;
import net.minecraft.server.MovingObjectPositionEntity;
import net.minecraft.server.Vec3D;
public class CraftRayTraceResult {
@@ -17,23 +19,24 @@ public class CraftRayTraceResult {
private CraftRayTraceResult() {}
public static RayTraceResult fromNMS(World world, MovingObjectPosition nmsHitResult) {
if (nmsHitResult == null || nmsHitResult.type == EnumMovingObjectType.MISS) return null;
if (nmsHitResult == null || nmsHitResult.getType() == EnumMovingObjectType.MISS) return null;
Vec3D nmsHitPos = nmsHitResult.pos;
Vec3D nmsHitPos = nmsHitResult.getPos();
Vector hitPosition = new Vector(nmsHitPos.x, nmsHitPos.y, nmsHitPos.z);
BlockFace hitBlockFace = null;
if (nmsHitResult.direction != null) {
hitBlockFace = CraftBlock.notchToBlockFace(nmsHitResult.direction);
}
if (nmsHitResult.entity != null) {
Entity hitEntity = nmsHitResult.entity.getBukkitEntity();
return new RayTraceResult(hitPosition, hitEntity, hitBlockFace);
if (nmsHitResult.getType() == EnumMovingObjectType.ENTITY) {
Entity hitEntity = ((MovingObjectPositionEntity) nmsHitResult).getEntity().getBukkitEntity();
return new RayTraceResult(hitPosition, hitEntity, null);
}
Block hitBlock = null;
BlockPosition nmsBlockPos = nmsHitResult.getBlockPosition();
BlockPosition nmsBlockPos = null;
if (nmsHitResult.getType() == EnumMovingObjectType.BLOCK) {
MovingObjectPositionBlock blockHitResult = (MovingObjectPositionBlock) nmsHitResult;
hitBlockFace = CraftBlock.notchToBlockFace(blockHitResult.getDirection());
nmsBlockPos = blockHitResult.getBlockPosition();
}
if (nmsBlockPos != null && world != null) {
hitBlock = world.getBlockAt(nmsBlockPos.getX(), nmsBlockPos.getY(), nmsBlockPos.getZ());
}

View File

@@ -0,0 +1,15 @@
package org.bukkit.craftbukkit.util;
public final class CraftVector {
private CraftVector() {
}
public static org.bukkit.util.Vector toBukkit(net.minecraft.server.Vec3D nms) {
return new org.bukkit.util.Vector(nms.x, nms.y, nms.z);
}
public static net.minecraft.server.Vec3D toNMS(org.bukkit.util.Vector bukkit) {
return new net.minecraft.server.Vec3D(bukkit.getX(), bukkit.getY(), bukkit.getZ());
}
}

View File

@@ -1,10 +1,13 @@
package org.bukkit.craftbukkit.util;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.BiomeBase;
import net.minecraft.server.Block;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.ChunkStatus;
import net.minecraft.server.DifficultyDamageScaler;
import net.minecraft.server.Entity;
import net.minecraft.server.EntityHuman;
@@ -17,19 +20,15 @@ import net.minecraft.server.HeightMap;
import net.minecraft.server.IBlockData;
import net.minecraft.server.IChunkAccess;
import net.minecraft.server.IChunkProvider;
import net.minecraft.server.IDataManager;
import net.minecraft.server.ParticleParam;
import net.minecraft.server.PersistentCollection;
import net.minecraft.server.SoundCategory;
import net.minecraft.server.SoundEffect;
import net.minecraft.server.TickList;
import net.minecraft.server.TileEntity;
import net.minecraft.server.VoxelShape;
import net.minecraft.server.World;
import net.minecraft.server.WorldBorder;
import net.minecraft.server.WorldData;
import net.minecraft.server.WorldProvider;
import org.bukkit.event.entity.CreatureSpawnEvent;
public class DummyGeneratorAccess implements GeneratorAccess {
@@ -53,11 +52,6 @@ public class DummyGeneratorAccess implements GeneratorAccess {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public IChunkAccess getChunkAt(int i, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public World getMinecraftWorld() {
throw new UnsupportedOperationException("Not supported yet.");
@@ -79,12 +73,7 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public IDataManager getDataManager() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Random m() {
public Random getRandom() {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -93,11 +82,6 @@ public class DummyGeneratorAccess implements GeneratorAccess {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public BlockPosition getSpawn() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void a(EntityHuman eh, BlockPosition bp, SoundEffect se, SoundCategory sc, float f, float f1) {
throw new UnsupportedOperationException("Not supported yet.");
@@ -109,17 +93,22 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public boolean isEmpty(BlockPosition bp) {
public void a(EntityHuman eh, int i, BlockPosition bp, int i1) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public BiomeBase getBiome(BlockPosition bp) {
public List<Entity> getEntities(Entity entity, AxisAlignedBB aabb, Predicate<? super Entity> prdct) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getBrightness(EnumSkyBlock esb, BlockPosition bp) {
public <T extends Entity> List<T> a(Class<? extends T> type, AxisAlignedBB aabb, Predicate<? super T> prdct) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<? extends EntityHuman> getPlayers() {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -129,12 +118,12 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public boolean isChunkLoaded(int i, int i1, boolean bln) {
public IChunkAccess getChunkAt(int i, int i1, ChunkStatus cs, boolean bln) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean e(BlockPosition bp) {
public BlockPosition getHighestBlockYAt(HeightMap.Type type, BlockPosition bp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -143,11 +132,6 @@ public class DummyGeneratorAccess implements GeneratorAccess {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public EntityHuman a(double d, double d1, double d2, double d3, Predicate<Entity> prdct) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int c() {
throw new UnsupportedOperationException("Not supported yet.");
@@ -158,11 +142,6 @@ public class DummyGeneratorAccess implements GeneratorAccess {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean a(Entity entity, VoxelShape vs) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int a(BlockPosition bp, EnumDirection ed) {
throw new UnsupportedOperationException("Not supported yet.");
@@ -179,7 +158,17 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public WorldProvider o() {
public WorldProvider getWorldProvider() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public BiomeBase getBiome(BlockPosition bp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getBrightness(EnumSkyBlock esb, BlockPosition bp) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -199,7 +188,7 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public PersistentCollection h() {
public boolean a(BlockPosition bp, Predicate<IBlockData> prdct) {
throw new UnsupportedOperationException("Not supported yet.");
}
@@ -209,27 +198,12 @@ public class DummyGeneratorAccess implements GeneratorAccess {
}
@Override
public boolean addEntity(Entity entity) {
public boolean a(BlockPosition blockposition, boolean flag) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason reason) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean setAir(BlockPosition blockposition) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean setAir(BlockPosition blockposition, boolean flag) {
public boolean b(BlockPosition blockposition, boolean flag) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

View File

@@ -1,15 +0,0 @@
package org.bukkit.craftbukkit.util;
public class LongHash {
public static long toLong(int msw, int lsw) {
return ((long) msw << 32) + lsw - Integer.MIN_VALUE;
}
public static int msw(long l) {
return (int) (l >> 32);
}
public static int lsw(long l) {
return (int) (l & 0xFFFFFFFF) + Integer.MIN_VALUE;
}
}

View File

@@ -1,302 +0,0 @@
/*
Based on CompactHashSet Copyright 2011 Ontopia Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.bukkit.craftbukkit.util;
import java.util.Arrays;
import java.util.Iterator;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
public class LongHashSet {
private final static int INITIAL_SIZE = 3;
private final static double LOAD_FACTOR = 0.75;
private final static long FREE = 0;
private final static long REMOVED = Long.MIN_VALUE;
private int freeEntries;
private int elements;
private long[] values;
private int modCount;
public LongHashSet() {
this(INITIAL_SIZE);
}
public LongHashSet(int size) {
values = new long[(size==0 ? 1 : size)];
elements = 0;
freeEntries = values.length;
modCount = 0;
}
public Iterator iterator() {
return new Itr();
}
public int size() {
return elements;
}
public boolean isEmpty() {
return elements == 0;
}
public boolean contains(int msw, int lsw) {
return contains(LongHash.toLong(msw, lsw));
}
public boolean contains(long value) {
int hash = hash(value);
int index = (hash & 0x7FFFFFFF) % values.length;
int offset = 1;
// search for the object (continue while !null and !this object)
while(values[index] != FREE && !(hash(values[index]) == hash && values[index] == value)) {
index = ((index + offset) & 0x7FFFFFFF) % values.length;
offset = offset * 2 + 1;
if (offset == -1) {
offset = 2;
}
}
return values[index] != FREE;
}
public boolean add(int msw, int lsw) {
return add(LongHash.toLong(msw, lsw));
}
public boolean add(long value) {
int hash = hash(value);
int index = (hash & 0x7FFFFFFF) % values.length;
int offset = 1;
int deletedix = -1;
// search for the object (continue while !null and !this object)
while(values[index] != FREE && !(hash(values[index]) == hash && values[index] == value)) {
// if there's a deleted object here we can put this object here,
// provided it's not in here somewhere else already
if (values[index] == REMOVED) {
deletedix = index;
}
index = ((index + offset) & 0x7FFFFFFF) % values.length;
offset = offset * 2 + 1;
if (offset == -1) {
offset = 2;
}
}
if (values[index] == FREE) {
if (deletedix != -1) { // reusing a deleted cell
index = deletedix;
} else {
freeEntries--;
}
modCount++;
elements++;
values[index] = value;
if (1 - (freeEntries / (double) values.length) > LOAD_FACTOR) {
rehash();
}
return true;
} else {
return false;
}
}
public void remove(int msw, int lsw) {
remove(LongHash.toLong(msw, lsw));
}
public boolean remove(long value) {
int hash = hash(value);
int index = (hash & 0x7FFFFFFF) % values.length;
int offset = 1;
// search for the object (continue while !null and !this object)
while(values[index] != FREE && !(hash(values[index]) == hash && values[index] == value)) {
index = ((index + offset) & 0x7FFFFFFF) % values.length;
offset = offset * 2 + 1;
if (offset == -1) {
offset = 2;
}
}
if (values[index] != FREE) {
values[index] = REMOVED;
modCount++;
elements--;
return true;
} else {
return false;
}
}
public void clear() {
elements = 0;
for (int ix = 0; ix < values.length; ix++) {
values[ix] = FREE;
}
freeEntries = values.length;
modCount++;
}
public long[] toArray() {
long[] result = new long[elements];
long[] values = Arrays.copyOf(this.values, this.values.length);
int pos = 0;
for (long value : values) {
if (value != FREE && value != REMOVED) {
result[pos++] = value;
}
}
return result;
}
public long popFirst() {
for (long value : values) {
if (value != FREE && value != REMOVED) {
remove(value);
return value;
}
}
return 0;
}
public long[] popAll() {
long[] ret = toArray();
clear();
return ret;
}
// This method copied from Murmur3, written by Austin Appleby released under Public Domain
private int hash(long value) {
value ^= value >>> 33;
value *= 0xff51afd7ed558ccdL;
value ^= value >>> 33;
value *= 0xc4ceb9fe1a85ec53L;
value ^= value >>> 33;
return (int) value;
}
private void rehash() {
int gargagecells = values.length - (elements + freeEntries);
if (gargagecells / (double) values.length > 0.05) {
rehash(values.length);
} else {
rehash(values.length * 2 + 1);
}
}
private void rehash(int newCapacity) {
long[] newValues = new long[newCapacity];
for (long value : values) {
if (value == FREE || value == REMOVED) {
continue;
}
int hash = hash(value);
int index = (hash & 0x7FFFFFFF) % newCapacity;
int offset = 1;
// search for the object
while (newValues[index] != FREE) {
index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
offset = offset * 2 + 1;
if (offset == -1) {
offset = 2;
}
}
newValues[index] = value;
}
values = newValues;
freeEntries = values.length - elements;
}
private class Itr implements Iterator {
private int index;
private int lastReturned = -1;
private int expectedModCount;
public Itr() {
for (index = 0; index < values.length && (values[index] == FREE || values[index] == REMOVED); index++) {
// This is just to drive the index forward to the first valid entry
}
expectedModCount = modCount;
}
public boolean hasNext() {
return index != values.length;
}
public Long next() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
int length = values.length;
if (index >= length) {
lastReturned = -2;
throw new NoSuchElementException();
}
lastReturned = index;
for (index += 1; index < length && (values[index] == FREE || values[index] == REMOVED); index++) {
// This is just to drive the index forward to the next valid entry
}
if (values[lastReturned] == FREE) {
return FREE;
} else {
return values[lastReturned];
}
}
public void remove() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (lastReturned == -1 || lastReturned == -2) {
throw new IllegalStateException();
}
if (values[lastReturned] != FREE && values[lastReturned] != REMOVED) {
values[lastReturned] = REMOVED;
elements--;
modCount++;
expectedModCount = modCount;
}
}
}
}

View File

@@ -1,422 +0,0 @@
package org.bukkit.craftbukkit.util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
@SuppressWarnings("unchecked")
public class LongObjectHashMap<V> implements Cloneable, Serializable {
static final long serialVersionUID = 2841537710170573815L;
private static final long EMPTY_KEY = Long.MIN_VALUE;
private static final int BUCKET_SIZE = 4096;
private transient long[][] keys;
private transient V[][] values;
private transient int modCount;
private transient int size;
public LongObjectHashMap() {
initialize();
}
public LongObjectHashMap(Map<? extends Long, ? extends V> map) {
this();
putAll(map);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean containsKey(long key) {
return get(key) != null;
}
public boolean containsValue(V value) {
for (V val : values()) {
if (val == value || val.equals(value)) {
return true;
}
}
return false;
}
public V get(long key) {
int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
long[] inner = keys[index];
if (inner == null) return null;
for (int i = 0; i < inner.length; i++) {
long innerKey = inner[i];
if (innerKey == EMPTY_KEY) {
return null;
} else if (innerKey == key) {
return values[index][i];
}
}
return null;
}
public V put(long key, V value) {
int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
long[] innerKeys = keys[index];
V[] innerValues = values[index];
modCount++;
if (innerKeys == null) {
// need to make a new chain
keys[index] = innerKeys = new long[8];
Arrays.fill(innerKeys, EMPTY_KEY);
values[index] = innerValues = (V[]) new Object[8];
innerKeys[0] = key;
innerValues[0] = value;
size++;
} else {
int i;
for (i = 0; i < innerKeys.length; i++) {
// found an empty spot in the chain to put this
if (innerKeys[i] == EMPTY_KEY) {
size++;
innerKeys[i] = key;
innerValues[i] = value;
return null;
}
// found an existing entry in the chain with this key, replace it
if (innerKeys[i] == key) {
V oldValue = innerValues[i];
innerKeys[i] = key;
innerValues[i] = value;
return oldValue;
}
}
// chain is full, resize it and add our new entry
keys[index] = innerKeys = Arrays.copyOf(innerKeys, i << 1);
Arrays.fill(innerKeys, i, innerKeys.length, EMPTY_KEY);
values[index] = innerValues = Arrays.copyOf(innerValues, i << 1);
innerKeys[i] = key;
innerValues[i] = value;
size++;
}
return null;
}
public V remove(long key) {
int index = (int) (keyIndex(key) & (BUCKET_SIZE - 1));
long[] inner = keys[index];
if (inner == null) {
return null;
}
for (int i = 0; i < inner.length; i++) {
// hit the end of the chain, didn't find this entry
if (inner[i] == EMPTY_KEY) {
break;
}
if (inner[i] == key) {
V value = values[index][i];
for (i++; i < inner.length; i++) {
if (inner[i] == EMPTY_KEY) {
break;
}
inner[i - 1] = inner[i];
values[index][i - 1] = values[index][i];
}
inner[i - 1] = EMPTY_KEY;
values[index][i - 1] = null;
size--;
modCount++;
return value;
}
}
return null;
}
public void putAll(Map<? extends Long, ? extends V> map) {
for (Map.Entry entry : map.entrySet()) {
put((Long) entry.getKey(), (V) entry.getValue());
}
}
public void clear() {
if (size == 0) {
return;
}
modCount++;
size = 0;
Arrays.fill(keys, null);
Arrays.fill(values, null);
}
public Set<Long> keySet() {
return new KeySet();
}
public Collection<V> values() {
return new ValueCollection();
}
/**
* Returns a Set of Entry objects for the HashMap. This is not how the internal
* implementation is laid out so this constructs the entire Set when called. For
* this reason it should be avoided if at all possible.
*
* @return Set of Entry objects
* @deprecated
*/
@Deprecated
public Set<Map.Entry<Long, V>> entrySet() {
HashSet<Map.Entry<Long, V>> set = new HashSet<Map.Entry<Long, V>>();
for (long key : keySet()) {
set.add(new Entry(key, get(key)));
}
return set;
}
public Object clone() throws CloneNotSupportedException {
LongObjectHashMap clone = (LongObjectHashMap) super.clone();
// Make sure we clear any existing information from the clone
clone.clear();
// Make sure the clone is properly setup for new entries
clone.initialize();
// Iterate through the data normally to do a safe clone
for (long key : keySet()) {
final V value = get(key);
clone.put(key, value);
}
return clone;
}
private void initialize() {
keys = new long[BUCKET_SIZE][];
values = (V[][]) new Object[BUCKET_SIZE][];
}
private long keyIndex(long key) {
key ^= key >>> 33;
key *= 0xff51afd7ed558ccdL;
key ^= key >>> 33;
key *= 0xc4ceb9fe1a85ec53L;
key ^= key >>> 33;
return key;
}
private void writeObject(ObjectOutputStream outputStream) throws IOException {
outputStream.defaultWriteObject();
for (long key : keySet()) {
V value = get(key);
outputStream.writeLong(key);
outputStream.writeObject(value);
}
outputStream.writeLong(EMPTY_KEY);
outputStream.writeObject(null);
}
private void readObject(ObjectInputStream inputStream) throws ClassNotFoundException, IOException {
inputStream.defaultReadObject();
initialize();
while (true) {
long key = inputStream.readLong();
V value = (V) inputStream.readObject();
if (key == EMPTY_KEY && value == null) {
break;
}
put(key, value);
}
}
private class ValueIterator implements Iterator<V> {
private int count;
private int index;
private int innerIndex;
private int expectedModCount;
private long lastReturned = EMPTY_KEY;
long prevKey = EMPTY_KEY;
V prevValue;
ValueIterator() {
expectedModCount = LongObjectHashMap.this.modCount;
}
public boolean hasNext() {
return count < LongObjectHashMap.this.size;
}
public void remove() {
if (LongObjectHashMap.this.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (lastReturned == EMPTY_KEY) {
throw new IllegalStateException();
}
count--;
LongObjectHashMap.this.remove(lastReturned);
lastReturned = EMPTY_KEY;
expectedModCount = LongObjectHashMap.this.modCount;
}
public V next() {
if (LongObjectHashMap.this.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (!hasNext()) {
throw new NoSuchElementException();
}
long[][] keys = LongObjectHashMap.this.keys;
count++;
if (prevKey != EMPTY_KEY) {
innerIndex++;
}
for (; index < keys.length; index++) {
if (keys[index] != null) {
for (; innerIndex < keys[index].length; innerIndex++) {
long key = keys[index][innerIndex];
V value = values[index][innerIndex];
if (key == EMPTY_KEY) {
break;
}
lastReturned = key;
prevKey = key;
prevValue = value;
return prevValue;
}
innerIndex = 0;
}
}
throw new NoSuchElementException();
}
}
private class KeyIterator implements Iterator<Long> {
final ValueIterator iterator;
public KeyIterator() {
iterator = new ValueIterator();
}
public void remove() {
iterator.remove();
}
public boolean hasNext() {
return iterator.hasNext();
}
public Long next() {
iterator.next();
return iterator.prevKey;
}
}
private class KeySet extends AbstractSet<Long> {
public void clear() {
LongObjectHashMap.this.clear();
}
public int size() {
return LongObjectHashMap.this.size();
}
public boolean contains(Object key) {
return key instanceof Long && LongObjectHashMap.this.containsKey((Long) key);
}
public boolean remove(Object key) {
return LongObjectHashMap.this.remove((Long) key) != null;
}
public Iterator<Long> iterator() {
return new KeyIterator();
}
}
private class ValueCollection extends AbstractCollection<V> {
public void clear() {
LongObjectHashMap.this.clear();
}
public int size() {
return LongObjectHashMap.this.size();
}
public boolean contains(Object value) {
return LongObjectHashMap.this.containsValue((V) value);
}
public Iterator<V> iterator() {
return new ValueIterator();
}
}
private class Entry implements Map.Entry<Long, V> {
private final Long key;
private V value;
Entry(long k, V v) {
key = k;
value = v;
}
public Long getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V v) {
V old = value;
value = v;
put(key, v);
return old;
}
}
}

View File

@@ -1,63 +0,0 @@
package org.bukkit.craftbukkit.util;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
public class MojangNameLookup {
private static final Logger logger = LogManager.getFormatterLogger(MojangNameLookup.class);
public static String lookupName(UUID id) {
if (id == null) {
return null;
}
InputStream inputStream = null;
try {
URL url = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + id.toString().replace("-", ""));
URLConnection connection = url.openConnection();
connection.setConnectTimeout(15000);
connection.setReadTimeout(15000);
connection.setUseCaches(false);
inputStream = connection.getInputStream();
String result = IOUtils.toString(inputStream, Charsets.UTF_8);
Gson gson = new Gson();
Response response = gson.fromJson(result, Response.class);
if (response == null || response.name == null) {
logger.warn("Failed to lookup name from UUID");
return null;
}
if (response.cause != null && response.cause.length() > 0) {
logger.warn("Failed to lookup name from UUID: %s", response.errorMessage);
return null;
}
return response.name;
} catch (MalformedURLException ex) {
logger.warn("Malformed URL in UUID lookup");
return null;
} catch (IOException ex) {
IOUtils.closeQuietly(inputStream);
} finally {
IOUtils.closeQuietly(inputStream);
}
return null;
}
private class Response {
String errorMessage;
String cause;
String name;
}
}

View File

@@ -1,6 +1,5 @@
package org.bukkit.craftbukkit.util;
import net.minecraft.server.ExceptionWorldConflict;
import net.minecraft.server.MinecraftServer;
public class ServerShutdownThread extends Thread {
@@ -13,9 +12,7 @@ public class ServerShutdownThread extends Thread {
@Override
public void run() {
try {
server.stop();
} catch (ExceptionWorldConflict ex) {
ex.printStackTrace();
server.close();
} finally {
try {
server.reader.getTerminal().restore();

View File

@@ -1,61 +0,0 @@
package org.bukkit.craftbukkit.util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import joptsimple.OptionException;
import joptsimple.OptionSet;
import net.minecraft.server.MinecraftServer;
public class ShortConsoleLogFormatter extends Formatter {
private final SimpleDateFormat date;
public ShortConsoleLogFormatter(MinecraftServer server) {
OptionSet options = server.options;
SimpleDateFormat date = null;
if (options.has("date-format")) {
try {
Object object = options.valueOf("date-format");
if ((object != null) && (object instanceof SimpleDateFormat)) {
date = (SimpleDateFormat) object;
}
} catch (OptionException ex) {
System.err.println("Given date format is not valid. Falling back to default.");
}
} else if (options.has("nojline")) {
date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
if (date == null) {
date = new SimpleDateFormat("HH:mm:ss");
}
this.date = date;
}
@Override
public String format(LogRecord record) {
StringBuilder builder = new StringBuilder();
Throwable ex = record.getThrown();
builder.append(date.format(record.getMillis()));
builder.append(" [");
builder.append(record.getLevel().getLocalizedName().toUpperCase());
builder.append("] ");
builder.append(formatMessage(record));
builder.append('\n');
if (ex != null) {
StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
builder.append(writer);
}
return builder.toString();
}
}

View File

@@ -10,13 +10,15 @@ import org.bukkit.craftbukkit.Main;
import org.fusesource.jansi.Ansi;
import org.fusesource.jansi.Ansi.Erase;
public class TerminalConsoleWriterThread implements Runnable {
public class TerminalConsoleWriterThread extends Thread {
final private ConsoleReader reader;
final private OutputStream output;
public TerminalConsoleWriterThread(OutputStream output, ConsoleReader reader) {
this.output = output;
this.reader = reader;
this.setDaemon(true);
}
public void run() {