Merge remote-tracking branch 'refs/remotes/sk89q/master'

# Conflicts:

#	worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java
#	worldedit-core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java
#	worldedit-core/src/main/java/com/sk89q/worldedit/world/NullWorld.java
This commit is contained in:
Jesse Boyd 2018-08-15 14:02:51 +10:00
commit a67441bbff
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
24 changed files with 943 additions and 230 deletions

View File

@ -36,6 +36,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.function.Function;
import javax.annotation.Nullable;
@ -50,8 +51,7 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
if (type == null) {
type = Material.AIR;
}
return materialMap.computeIfAbsent(type,
material -> new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), material));
return materialMap.computeIfAbsent(type, m -> new BukkitBlockMaterial(BukkitBlockRegistry.super.getMaterial(blockType), m));
}
@Nullable
@ -72,6 +72,18 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
this.material = bukkitMaterial;
}
@Override
public boolean isAir() {
switch (material) {
case AIR:
case CAVE_AIR:
case VOID_AIR:
return true;
default:
return false;
}
}
@Override
public boolean isSolid() {
return material.isSolid();

View File

@ -179,7 +179,10 @@ public class Fawe {
}
public static void debugPlain(String s) {
if (INSTANCE != null) {
Actor actor = Request.request().getActor();
if (actor != null) {
actor.print(BBC.color(s));
} else if (INSTANCE != null) {
INSTANCE.IMP.debug(s);
} else {
System.out.println(BBC.stripColor(BBC.color(s)));

View File

@ -404,9 +404,9 @@ public abstract class TaskManager {
MainUtil.handleError(neverHappens);
} finally {
running.set(false);
}
synchronized (function) {
function.notifyAll();
synchronized (function) {
function.notifyAll();
}
}
}
};

View File

@ -10,6 +10,8 @@ import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
@ -533,6 +535,36 @@ public class TextureUtil implements TextureHolder{
return colorDistance(red1, green1, blue1, c2);
}
public static void main(String[] args) throws IOException {
File tf = new File("1.13.jar");
ZipFile zipFile = new ZipFile(tf);
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
System.out.println(entries.nextElement().getName());
}
// TextureUtil tu = new TextureUtil(new File("."));
// tu.loadModTextures();
}
private BufferedImage readImage(ZipFile zipFile, String name) throws IOException {
ZipEntry entry = getEntry(zipFile, name);
if (entry != null) {
try (InputStream is = zipFile.getInputStream(entry)) {
return ImageIO.read(is);
}
}
return null;
}
private ZipEntry getEntry(ZipFile file, String path) {
ZipEntry entry = file.getEntry(path);
if (entry == null) {
path = path.replace("/", File.separator);
entry = file.getEntry(path);
}
return entry;
}
public void loadModTextures() throws IOException {
Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>();
Int2ObjectOpenHashMap<Long> distanceMap = new Int2ObjectOpenHashMap<>();
@ -545,224 +577,188 @@ public class TextureUtil implements TextureHolder{
return name.endsWith(".jar");
}
});
if (files.length == 0) {
throw new FileNotFoundException("Please create a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar or mods in it." +
"If the file exists, please make sure the server has read access to the directory");
}
for (File file : files) {
ZipFile zipFile = new ZipFile(file);
// Get all the groups in the current jar
// The vanilla textures are in `assets/minecraft`
// A jar may contain textures for multiple mods
Set<String> mods = new HashSet<String>();
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
Path path = Paths.get(name);
if (path.startsWith("assets" + File.separator)) {
String[] split = path.toString().split(Pattern.quote(File.separator));
if (split.length > 1) {
String modId = split[1];
mods.add(modId);
}
}
continue;
}
for (BlockType blockType : BlockTypes.values) {
BlockMaterial material = blockType.getMaterial();
if (!material.isSolid() || !material.isFullCube()) continue;
int color = material.getMapColor();
if (color != 0) {
colorMap.put((int) blockType.getInternalId(), (Integer) color);
}
String modelsDir = "assets" + File.separator + "%1$s" + File.separator + "models" + File.separator + "block" + File.separator + "%2$s.json";
String texturesDir = "assets" + File.separator + "%1$s" + File.separator + "textures" + File.separator + "blocks" + File.separator + "%2$s.json";
}
if (files.length == 0) {
Fawe.debug("Please create a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions/1.13.jar` jar or mods in it. If the file exists, please make sure the server has read access to the directory");
} else {
for (File file : files) {
ZipFile zipFile = new ZipFile(file);
Type typeToken = new TypeToken<Map<String, Object>>() {}.getType();
for (BlockType blockType : BlockTypes.values) {
if (!blockType.getMaterial().isFullCube()) continue;
String id = blockType.getId();
String[] split = id.split(":", 2);
String name = split.length == 1 ? id : split[1];
String nameSpace = split.length == 1 ? "minecraft" : split[0];
Map<String, String> texturesMap = new ConcurrentHashMap<>();
{ // Read models
String modelFileName = String.format(modelsDir, nameSpace, name);
ZipEntry entry = zipFile.getEntry(modelFileName);
if (entry == null) continue;
try (InputStream is = zipFile.getInputStream(entry)) { //Read from a file, or a HttpRequest, or whatever.
JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
Map<String, Object> root = gson.fromJson(reader, typeToken);
Map<String, Object> textures = (Map) root.get("textures");
if (textures == null) continue;
Set<String> models = new HashSet<>();
// Get models
for (Map.Entry<String, Object> stringObjectEntry : textures.entrySet()) {
Object value = stringObjectEntry.getValue();
if (value instanceof String) {
models.add((String) value);
} else if (value instanceof Map) {
value = ((Map) value).get("model");
if (value != null) models.add((String) value);
// Get all the groups in the current jar
// The vanilla textures are in `assets/minecraft`
// A jar may contain textures for multiple mods
Set<String> mods = new HashSet<String>();
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
Path path = Paths.get(name);
if (path.startsWith("assets" + File.separator)) {
String[] split = path.toString().split(Pattern.quote(File.separator));
if (split.length > 1) {
String modId = split[1];
mods.add(modId);
}
}
if (models.size() == 1) {
// get textures
}
// If texturs size == 1
// Put texture in map
continue;
}
}
// // Try to match the textures to a block
// Int2ObjectOpenHashMap<String> idMap = new Int2ObjectOpenHashMap<>();
// HashSet<Integer> map2 = new HashSet<>();
// for (String id : bundled.stateMap.keySet()) {
// if (id.startsWith(modId)) {
// BlockType block = bundled.findByState(id);
// BundledBlockData.BlockEntry state = bundled.findById(block.getId());
// if (FaweCache.hasNBT(block.getId())) {
// continue;
// }
// // Ignore non blocks
// if (!state.material.isFullCube() && !state.material.isRenderedAsNormalBlock()) {
// switch (block.getId()) {
// case 20:
// case 95:
// break;
// default:
// continue;
// }
// } else if (!state.material.isFullCube() || !state.material.isRenderedAsNormalBlock()) {
// switch (block.getId()) {
// case 165:
// case 52:
// continue;
// }
// }
// if (state.material.getLightValue() != 0) {
// continue;
// }
// id = id.substring(modId.length() + 1).replaceAll(":", "_");
// String texture = texturesMap.remove(id);
// if (texture == null) {
// texture = texturesMap.remove(alphabetize(id));
// }
// if (texture != null) {
// int combined = block.getCombined();
// switch (block.getId()) {
// case 17:
// case 162:
// combined += 12;
// break;
// case 43:
// combined += 8;
// break;
// }
// idMap.putIfAbsent(combined, texture);
// }
// }
// }
// { // Calculate the colors for each block
// for (Int2ObjectMap.Entry<String> entry : idMap.int2ObjectEntrySet()) {
// int combined = entry.getIntKey();
// String path = texturesDir + "/" + entry.getValue() + ".png";
// ZipEntry textureEntry = zipFile.getEntry(path);
// try (InputStream is = zipFile.getInputStream(textureEntry)) {
// BufferedImage image = ImageIO.read(is);
// int color = ImageUtil.getColor(image);
// long distance = getDistance(image, color);
// if (combined == BlockTypesMYCELIUM << 4) distance = Long.MAX_VALUE;
// distanceMap.put((int) combined, (Long) distance);
// colorMap.put((int) combined, (Integer) color);
// }
// }
// }
String modelsDir = "assets/%1$s/models/block/%2$s.json";
String texturesDir = "assets/%1$s/textures/%2$s.png";
Type typeToken = new TypeToken<Map<String, Object>>() {
}.getType();
for (BlockType blockType : BlockTypes.values) {
if (!blockType.getMaterial().isFullCube()) continue;
int combined = blockType.getInternalId();
String id = blockType.getId();
String[] split = id.split(":", 2);
String name = split.length == 1 ? id : split[1];
String nameSpace = split.length == 1 ? "minecraft" : split[0];
Map<String, String> texturesMap = new ConcurrentHashMap<>();
{ // Read models
String modelFileName = String.format(modelsDir, nameSpace, name);
ZipEntry entry = getEntry(zipFile, modelFileName);
if (entry == null) {
System.out.println("Cannot find " + modelFileName + " in " + file);
continue;
}
String textureFileName;
try (InputStream is = zipFile.getInputStream(entry)) {
JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
Map<String, Object> root = gson.fromJson(reader, typeToken);
Map<String, Object> textures = (Map) root.get("textures");
if (textures == null) continue;
Set<String> models = new HashSet<>();
// Get models
for (Map.Entry<String, Object> stringObjectEntry : textures.entrySet()) {
Object value = stringObjectEntry.getValue();
if (value instanceof String) {
models.add((String) value);
} else if (value instanceof Map) {
value = ((Map) value).get("model");
if (value != null) models.add((String) value);
}
}
if (models.size() != 1) continue;
textureFileName = String.format(texturesDir, nameSpace, models.iterator().next());
}
BufferedImage image = readImage(zipFile, textureFileName);
if (image == null) {
System.out.println("Cannot find " + textureFileName);
continue;
}
int color = ImageUtil.getColor(image);
long distance = getDistance(image, color);
distanceMap.put((int) combined, (Long) distance);
colorMap.put((int) combined, (Integer) color);
}
}
{
Integer grass = null;
{
String grassFileName = String.format(texturesDir, "minecraft", "grass_block_top");
BufferedImage image = readImage(zipFile, grassFileName);
if (image != null) {
grass = ImageUtil.getColor(image);
}
}
if (grass != null) {
// assets\minecraft\textures\colormap
ZipEntry grassEntry = getEntry(zipFile, "assets/minecraft/textures/colormap/grass_block.png");
if (grassEntry != null) {
try (InputStream is = zipFile.getInputStream(grassEntry)) {
BufferedImage image = ImageIO.read(is);
// Update biome colors
for (int i = 0; i < biomes.length; i++) {
BiomeColor biome = biomes[i];
float adjTemp = MathMan.clamp(biome.temperature, 0.0f, 1.0f);
float adjRainfall = MathMan.clamp(biome.rainfall, 0.0f, 1.0f) * adjTemp;
int x = (int) (255 - adjTemp * 255);
int z = (int) (255 - adjRainfall * 255);
biome.grass = image.getRGB(x, z);
}
}
// swampland: perlin - avoid
biomes[6].grass = 0;
biomes[134].grass = 0;
// roofed forest: averaged w/ 0x28340A
biomes[29].grass = multiplyColor(biomes[29].grass, 0x28340A + (255 << 24));
biomes[157].grass = multiplyColor(biomes[157].grass, 0x28340A + (255 << 24));
// mesa : 0x90814D
biomes[37].grass = 0x90814D + (255 << 24);
biomes[38].grass = 0x90814D + (255 << 24);
biomes[39].grass = 0x90814D + (255 << 24);
biomes[165].grass = 0x90814D + (255 << 24);
biomes[166].grass = 0x90814D + (255 << 24);
biomes[167].grass = 0x90814D + (255 << 24);
List<BiomeColor> valid = new ArrayList<>();
for (int i = 0; i < biomes.length; i++) {
BiomeColor biome = biomes[i];
// biome.grass = multiplyColor(biome.grass, grass);
if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
valid.add(biome);
}
biome.grassCombined = multiplyColor(grass, biome.grass);
}
this.validBiomes = valid.toArray(new BiomeColor[valid.size()]);
{
ArrayList<BiomeColor> uniqueColors = new ArrayList<>();
Set<Integer> uniqueBiomesColors = new IntArraySet();
for (BiomeColor color : validBiomes) {
if (uniqueBiomesColors.add(color.grass)) {
uniqueColors.add(color);
}
}
int count = 0;
int count2 = 0;
uniqueBiomesColors.clear();
LongArrayList layerIds = new LongArrayList();
LongArrayList layerColors = new LongArrayList();
for (int i = 0; i < uniqueColors.size(); i++) {
for (int j = i; j < uniqueColors.size(); j++) {
for (int k = j; k < uniqueColors.size(); k++) {
BiomeColor c1 = uniqueColors.get(i);
BiomeColor c2 = uniqueColors.get(j);
BiomeColor c3 = uniqueColors.get(k);
int average = averageColor(c1.grass, c2.grass, c3.grass);
if (uniqueBiomesColors.add(average)) {
count++;
layerColors.add((long) average);
layerIds.add((long) ((c1.id) + (c2.id << 8) + (c3.id << 16)));
}
}
}
}
validMixBiomeColors = new int[layerColors.size()];
for (int i = 0; i < layerColors.size(); i++)
validMixBiomeColors[i] = (int) layerColors.getLong(i);
validMixBiomeIds = layerIds.toLongArray();
}
}
}
}
// Close the file
zipFile.close();
}
// {
// Integer grass = colorMap.remove(FaweCache.getCombined(BlockTypesGRASS, 0));
// if (grass != null) {
// blockColors[FaweCache.getCombined(BlockTypesGRASS, 0)] = grass;
// // assets\minecraft\textures\colormap
// ZipEntry grassEntry = zipFile.getEntry("assets/minecraft/textures/colormap/grass.png");
// if (grassEntry != null) {
// try (InputStream is = zipFile.getInputStream(grassEntry)) {
// BufferedImage image = ImageIO.read(is);
// for (int i = 0; i < biomes.length; i++) {
// BiomeColor biome = biomes[i];
// float adjTemp = MathMan.clamp(biome.temperature, 0.0f, 1.0f);
// float adjRainfall = MathMan.clamp(biome.rainfall, 0.0f, 1.0f) * adjTemp;
// int x = (int) (255 - adjTemp * 255);
// int z = (int) (255 - adjRainfall * 255);
// int color = image.getRGB(x, z);
// biome.grass = color;
// }
// }
// // swampland: perlin - avoid
// biomes[6].grass = 0;
// biomes[134].grass = 0;
// // roofed forest: averaged w/ 0x28340A
// biomes[29].grass = multiplyColor(biomes[29].grass, 0x28340A + (255 << 24));
// biomes[157].grass = multiplyColor(biomes[157].grass, 0x28340A + (255 << 24));
// // mesa : 0x90814D
// biomes[37].grass = 0x90814D + (255 << 24);
// biomes[38].grass = 0x90814D + (255 << 24);
// biomes[39].grass = 0x90814D + (255 << 24);
// biomes[165].grass = 0x90814D + (255 << 24);
// biomes[166].grass = 0x90814D + (255 << 24);
// biomes[167].grass = 0x90814D + (255 << 24);
// List<BiomeColor> valid = new ArrayList<>();
// for (int i = 0; i < biomes.length; i++) {
// BiomeColor biome = biomes[i];
//// biome.grass = multiplyColor(biome.grass, grass);
// if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
// valid.add(biome);
// }
// biome.grassCombined = multiplyColor(grass, biome.grass);
// }
// this.validBiomes = valid.toArray(new BiomeColor[valid.size()]);
//
// {
// ArrayList<BiomeColor> uniqueColors = new ArrayList<>();
// Set<Integer> uniqueBiomesColors = new IntArraySet();
// for (BiomeColor color : validBiomes) {
// if (uniqueBiomesColors.add(color.grass)) {
// uniqueColors.add(color);
// }
// }
// int count = 0;
// int count2 = 0;
// uniqueBiomesColors.clear();
//
// LongArrayList layerIds = new LongArrayList();
// LongArrayList layerColors = new LongArrayList();
// for (int i = 0; i < uniqueColors.size(); i++) {
// for (int j = i; j < uniqueColors.size(); j++) {
// for (int k = j; k < uniqueColors.size(); k++) {
// BiomeColor c1 = uniqueColors.get(i);
// BiomeColor c2 = uniqueColors.get(j);
// BiomeColor c3 = uniqueColors.get(k);
// int average = averageColor(c1.grass, c2.grass, c3.grass);
// if (uniqueBiomesColors.add(average)) {
// count++;
// layerColors.add((long) average);
// layerIds.add((long) ((c1.id) + (c2.id << 8) + (c3.id << 16)));
// }
// }
// }
// }
//
// validMixBiomeColors = new int[layerColors.size()];
// for (int i = 0; i < layerColors.size(); i++) validMixBiomeColors[i] = (int) layerColors.getLong(i);
// validMixBiomeIds = layerIds.toLongArray();
// }
// }
//
// }
// }
// Close the file
zipFile.close();
}
}
// Convert the color map to a simple array

View File

@ -1026,7 +1026,7 @@ public class LocalSession implements TextureHolder {
public void setTool(BaseItem item, @Nullable Tool tool, Player player) throws InvalidToolBindException {
ItemTypes type = item.getType();
if (!type.hasBlockType() && type.getBlockType().getMaterial().isAir()) {
if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) {
throw new InvalidToolBindException(type, "Blocks can't be used");
} else if (type == config.wandItem) {
throw new InvalidToolBindException(type, "Already used for the wand");

View File

@ -39,18 +39,13 @@ import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents a mutable "snapshot" of a block.
* Represents a "snapshot" of a block with NBT Data.
*
* <p>An instance of this block contains all the information needed to
* accurately reproduce the block, provided that the instance was
* made correctly. In some implementations, it may not be possible to get a
* snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p>
*
* <p>A peculiar detail of this class is that it accepts {@code -1} as a
* valid data value. This is due to legacy reasons: WorldEdit uses -1
* as a "wildcard" block value, even though a {@link Mask} would be
* more appropriate.</p>
*/
public class BaseBlock extends BlockState {
private BlockState blockState;

View File

@ -163,4 +163,10 @@ public interface BlockMaterial {
* @return If it has a container
*/
boolean hasContainer();
/**
* Get the map color
* @return or 0
*/
int getMapColor();
}

View File

@ -19,11 +19,15 @@
package com.sk89q.worldedit.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.util.*;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator;
/**
* Plants a tree.

View File

@ -224,7 +224,8 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
state = item.getType().getBlockType().getDefaultState();
nbt = item.getNbtData();
} else {
state = BlockTypes.parse(typeString.toLowerCase()).getDefaultState();
BlockTypes type = BlockTypes.parse(typeString.toLowerCase());
state = type.getDefaultState();
if (state == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");

View File

@ -406,6 +406,7 @@ public final class CommandManager {
// exceptions without writing a hook into every dispatcher, we need to unwrap these
// exceptions and rethrow their converted form, if their is one.
try {
Request.request().setActor(finalActor);
Object result = dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
} catch (Throwable t) {
// Use the exception converter to convert the exception if any of its causes

View File

@ -21,6 +21,8 @@ package com.sk89q.worldedit.session.request;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
@ -37,6 +39,9 @@ public final class Request {
World world;
private
@Nullable
Actor actor;
private
@Nullable
LocalSession session;
private
@Nullable
@ -81,6 +86,15 @@ public final class Request {
return null;
}
@Nullable
public Actor getActor() {
return actor;
}
public void setActor(@Nullable Actor actor) {
this.actor = actor;
}
/**
* Get the request session.
*

View File

@ -0,0 +1,177 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.*;
import static com.google.common.base.Preconditions.checkNotNull;
public class DataReport implements Report {
private final String title;
private final List<Line> lines = Lists.newArrayList();
public DataReport(String title) {
checkNotNull(title, "title");
this.title = title;
}
public void append(String key, String message) {
checkNotNull(key, "key");
lines.add(new Line(key, message));
}
public void append(String key, String message, Object... values) {
checkNotNull(message, "values");
checkNotNull(values, "values");
append(key, String.format(message, values));
}
public void append(String key, byte value) {
append(key, String.valueOf(value));
}
public void append(String key, short value) {
append(key, String.valueOf(value));
}
public void append(String key, int value) {
append(key, String.valueOf(value));
}
public void append(String key, long value) {
append(key, String.valueOf(value));
}
public void append(String key, float value) {
append(key, String.valueOf(value));
}
public void append(String key, double value) {
append(key, String.valueOf(value));
}
public void append(String key, boolean value) {
append(key, String.valueOf(value));
}
public void append(String key, char value) {
append(key, String.valueOf(value));
}
public void append(String key, Object value) {
append(key, getStringValue(value, Sets.newHashSet()));
}
private static String getStringValue(Object value, Set<Object> seen) {
if (seen.contains(value)) {
return "<Recursive>";
} else {
seen.add(value);
}
if (value instanceof Object[]) {
value = Arrays.asList(value);
}
if (value instanceof Collection<?>) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Object entry : (Collection<?>) value) {
if (first) {
first = false;
} else {
builder.append("\n");
}
builder.append(getStringValue(entry, Sets.newHashSet(seen)));
}
return builder.toString();
} else if (value instanceof Map<?, ?>) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
if (first) {
first = false;
} else {
builder.append("\n");
}
String key = getStringValue(entry.getKey(), Sets.newHashSet(seen)).replaceAll("[\r\n]", "");
if (key.length() > 60) {
key = key.substring(0, 60) + "...";
}
builder
.append(key)
.append(": ")
.append(getStringValue(entry.getValue(), Sets.newHashSet(seen)));
}
return builder.toString();
} else {
return String.valueOf(value);
}
}
@Override
public String getTitle() {
return title;
}
@Override
public String toString() {
if (!lines.isEmpty()) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Line line : lines) {
if (first) {
first = false;
} else {
builder.append("\n");
}
builder.append(line.key).append(": ");
if (line.value == null) {
builder.append("null");
} else if (line.value.contains("\n")) {
builder.append("\n");
builder.append(line.value.replaceAll("(?m)^", "\t"));
} else {
builder.append(line.value);
}
}
return builder.toString();
} else {
return "No data.";
}
}
private static class Line {
private final String key;
private final String value;
public Line(String key, String value) {
this.key = key;
this.value = value;
}
}
}

View File

@ -0,0 +1,26 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
public interface Report {
String getTitle();
}

View File

@ -0,0 +1,186 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class ReportList implements Report, List<Report> {
private final String title;
private final List<Report> reports = Lists.newArrayList();
public ReportList(String title) {
this.title = title;
}
@Override
public String getTitle() {
return title;
}
@Override
public int size() {
return reports.size();
}
@Override
public boolean isEmpty() {
return reports.isEmpty();
}
@Override
public boolean contains(Object o) {
return reports.contains(o);
}
@Override
public Iterator<Report> iterator() {
return reports.iterator();
}
@Override
public Object[] toArray() {
return reports.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return reports.toArray(a);
}
@Override
public boolean add(Report report) {
return reports.add(report);
}
@Override
public boolean remove(Object o) {
return reports.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return reports.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends Report> c) {
return reports.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends Report> c) {
return reports.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
return reports.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return reports.retainAll(c);
}
@Override
public void clear() {
reports.clear();
}
@Override
public boolean equals(Object o) {
return reports.equals(o);
}
@Override
public int hashCode() {
return reports.hashCode();
}
@Override
public Report get(int index) {
return reports.get(index);
}
@Override
public Report set(int index, Report element) {
return reports.set(index, element);
}
@Override
public void add(int index, Report element) {
reports.add(index, element);
}
@Override
public Report remove(int index) {
return reports.remove(index);
}
@Override
public int indexOf(Object o) {
return reports.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return reports.lastIndexOf(o);
}
@Override
public ListIterator<Report> listIterator() {
return reports.listIterator();
}
@Override
public ListIterator<Report> listIterator(int index) {
return reports.listIterator(index);
}
@Override
public List<Report> subList(int fromIndex, int toIndex) {
return reports.subList(fromIndex, toIndex);
}
@Override
public String toString() {
if (!reports.isEmpty()) {
StringBuilder builder = new StringBuilder();
for (Report report : reports) {
builder.append("================================\n")
.append(report.getTitle())
.append("\n================================")
.append("\n\n")
.append(report.toString())
.append("\n\n");
}
return builder.toString();
} else {
return "No reports.";
}
}
}

View File

@ -0,0 +1,58 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.google.common.base.Preconditions.checkNotNull;
public class ShallowObjectReport extends DataReport {
private static final Logger log = Logger.getLogger(ShallowObjectReport.class.getCanonicalName());
public ShallowObjectReport(String title, Object object) {
super(title);
checkNotNull(object, "object");
Class<?> type = object.getClass();
for (Field field : type.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) {
continue;
}
if (field.getAnnotation(Unreported.class) != null) {
continue;
}
field.setAccessible(true);
try {
Object value = field.get(object);
append(field.getName(), String.valueOf(value));
} catch (IllegalAccessException e) {
log.log(Level.WARNING, "Failed to get value of '" + field.getName() + "' on " + type);
}
}
}
}

View File

@ -0,0 +1,64 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import static com.google.common.base.Preconditions.checkNotNull;
public class StackTraceReport implements Report {
private final StackTraceElement[] stackTrace;
public StackTraceReport(StackTraceElement[] stackTrace) {
checkNotNull(stackTrace, "stackTrace");
this.stackTrace = stackTrace;
}
@Override
public String getTitle() {
return "Stack Trace";
}
@Override
public String toString() {
if (stackTrace.length > 0) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (StackTraceElement element : stackTrace) {
if (first) {
first = false;
} else {
builder.append("\n");
}
builder.append(element.getClassName())
.append(".")
.append(element.getMethodName())
.append("() (")
.append(element.getFileName())
.append(":")
.append(element.getLineNumber())
.append(")");
}
return builder.toString();
} else {
return "No stack trace available.";
}
}
}

View File

@ -0,0 +1,91 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import java.lang.management.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class SystemInfoReport extends DataReport {
public SystemInfoReport() {
super("System Information");
Runtime runtime = Runtime.getRuntime();
RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
ClassLoadingMXBean classLoadingBean = ManagementFactory.getClassLoadingMXBean();
List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
append("Java", "%s %s (%s)",
System.getProperty("java.vendor"),
System.getProperty("java.version"),
System.getProperty("java.vendor.url"));
append("Operating System", "%s %s (%s)",
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch"));
append("Available Processors", runtime.availableProcessors());
append("Free Memory", runtime.freeMemory() / 1024 / 1024 + " MB");
append("Max Memory", runtime.maxMemory() / 1024 / 1024 + " MB");
append("Total Memory", runtime.totalMemory() / 1024 / 1024 + " MB");
append("System Load Average", osBean.getSystemLoadAverage());
append("Java Uptime", TimeUnit.MINUTES.convert(runtimeBean.getUptime(), TimeUnit.MILLISECONDS) + " minutes");
DataReport startup = new DataReport("Startup");
startup.append("Input Arguments", runtimeBean.getInputArguments());
append(startup.getTitle(), startup);
DataReport vm = new DataReport("Virtual Machine");
vm.append("Name", runtimeBean.getVmName());
vm.append("Vendor", runtimeBean.getVmVendor());
vm.append("Version", runtimeBean.getVmVendor());
append(vm.getTitle(), vm);
DataReport spec = new DataReport("Specification");
spec.append("Name", runtimeBean.getSpecName());
spec.append("Vendor", runtimeBean.getSpecVendor());
spec.append("Version", runtimeBean.getSpecVersion());
append(spec.getTitle(), spec);
DataReport classLoader = new DataReport("Class Loader");
classLoader.append("Loaded Class Count", classLoadingBean.getLoadedClassCount());
classLoader.append("Total Loaded Class Count", classLoadingBean.getTotalLoadedClassCount());
classLoader.append("Unloaded Class Count", classLoadingBean.getUnloadedClassCount());
append(classLoader.getTitle(), classLoader);
DataReport gc = new DataReport("Garbage Collectors");
for (GarbageCollectorMXBean bean : gcBeans) {
DataReport thisGC = new DataReport(bean.getName());
thisGC.append("Collection Count", bean.getCollectionCount());
thisGC.append("Collection Time", bean.getCollectionTime() + "ms");
gc.append(thisGC.getTitle(), thisGC);
}
append(gc.getTitle(), gc);
DataReport threads = new DataReport("Threads");
for (ThreadInfo threadInfo : threadBean.dumpAllThreads(false, false)) {
threads.append("#" + threadInfo.getThreadId() + " " + threadInfo.getThreadName(), threadInfo.getThreadState());
}
append(threads.getTitle(), threads);
}
}

View File

@ -0,0 +1,33 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.util.report;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotates properties that should not be exposed in the report.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Unreported {
}

View File

@ -24,8 +24,11 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
<<<<<<< HEAD
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
=======
>>>>>>> refs/remotes/sk89q/master
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -37,6 +40,13 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.biome.BaseBiome;
<<<<<<< HEAD
=======
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
>>>>>>> refs/remotes/sk89q/master
import com.sk89q.worldedit.world.weather.WeatherType;
import java.util.Collections;

View File

@ -20,14 +20,14 @@
package com.sk89q.worldedit.world.registry;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.util.gson.VectorAdapter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
@ -75,6 +75,18 @@ public class BundledBlockData {
private void loadFromResource() throws IOException {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Vector.class, new VectorAdapter());
gsonBuilder.registerTypeAdapter(int.class, new JsonDeserializer<Integer>() {
@Override
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonPrimitive primitive = (JsonPrimitive) json;
if (primitive.isString()) {
String value = primitive.getAsString();
if (value.charAt(0) == '#') return Integer.parseInt(value.substring(1), 16);
return Integer.parseInt(value);
}
return primitive.getAsInt();
}
});
Gson gson = gsonBuilder.create();
URL url = BundledBlockData.class.getResource("blocks.json");
if (url == null) {

View File

@ -178,7 +178,11 @@ public class LegacyMapper {
private BlockState getBlock(int combinedId) {
if (combinedId < blockArr.length) {
return BlockState.get(blockArr[combinedId]);
try {
return BlockState.get(blockArr[combinedId]);
} catch (IndexOutOfBoundsException ignore) {
return null;
}
}
Integer extra = extraId4DataToStateId.get(combinedId);
if (extra == null) {

View File

@ -40,6 +40,15 @@ public class PassthroughBlockMaterial implements BlockMaterial {
}
}
@Override
public int getMapColor() {
if (blockMaterial == null) {
return 0;
} else {
return blockMaterial.getMapColor();
}
}
@Override
public boolean isFullCube() {
if (blockMaterial == null) {

View File

@ -43,6 +43,7 @@ class SimpleBlockMaterial implements BlockMaterial {
private boolean hasContainer;
private int lightOpacity;
private boolean isAir;
private int mapColor;
@Override
public boolean isAir() {
@ -53,6 +54,15 @@ class SimpleBlockMaterial implements BlockMaterial {
isAir = air;
}
@Override
public int getMapColor() {
return mapColor;
}
public void setMapColor(int mapColor) {
this.mapColor = mapColor;
}
@Override
public int getLightOpacity() {
return lightOpacity;

View File

@ -93,6 +93,7 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import javax.annotation.Nullable;