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

View File

@ -179,7 +179,10 @@ public class Fawe {
} }
public static void debugPlain(String s) { 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); INSTANCE.IMP.debug(s);
} else { } else {
System.out.println(BBC.stripColor(BBC.color(s))); System.out.println(BBC.stripColor(BBC.color(s)));

View File

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

View File

@ -10,6 +10,8 @@ import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock; 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.world.block.BlockState;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
@ -533,6 +535,36 @@ public class TextureUtil implements TextureHolder{
return colorDistance(red1, green1, blue1, c2); 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 { public void loadModTextures() throws IOException {
Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<Integer> colorMap = new Int2ObjectOpenHashMap<>();
Int2ObjectOpenHashMap<Long> distanceMap = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<Long> distanceMap = new Int2ObjectOpenHashMap<>();
@ -545,224 +577,188 @@ public class TextureUtil implements TextureHolder{
return name.endsWith(".jar"); return name.endsWith(".jar");
} }
}); });
if (files.length == 0) { for (BlockType blockType : BlockTypes.values) {
throw new FileNotFoundException("Please create a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar or mods in it." + BlockMaterial material = blockType.getMaterial();
"If the file exists, please make sure the server has read access to the directory"); if (!material.isSolid() || !material.isFullCube()) continue;
} int color = material.getMapColor();
for (File file : files) { if (color != 0) {
ZipFile zipFile = new ZipFile(file); colorMap.put((int) blockType.getInternalId(), (Integer) color);
// 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;
}
} }
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(); // Get all the groups in the current jar
// The vanilla textures are in `assets/minecraft`
for (BlockType blockType : BlockTypes.values) { // A jar may contain textures for multiple mods
if (!blockType.getMaterial().isFullCube()) continue; Set<String> mods = new HashSet<String>();
{
String id = blockType.getId(); Enumeration<? extends ZipEntry> entries = zipFile.entries();
String[] split = id.split(":", 2); while (entries.hasMoreElements()) {
String name = split.length == 1 ? id : split[1]; ZipEntry entry = entries.nextElement();
String nameSpace = split.length == 1 ? "minecraft" : split[0]; String name = entry.getName();
Path path = Paths.get(name);
Map<String, String> texturesMap = new ConcurrentHashMap<>(); if (path.startsWith("assets" + File.separator)) {
{ // Read models String[] split = path.toString().split(Pattern.quote(File.separator));
String modelFileName = String.format(modelsDir, nameSpace, name); if (split.length > 1) {
ZipEntry entry = zipFile.getEntry(modelFileName); String modId = split[1];
if (entry == null) continue; mods.add(modId);
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);
} }
} }
if (models.size() == 1) { continue;
// get textures
}
// If texturs size == 1
// Put texture in map
} }
} }
// // Try to match the textures to a block String modelsDir = "assets/%1$s/models/block/%2$s.json";
// Int2ObjectOpenHashMap<String> idMap = new Int2ObjectOpenHashMap<>(); String texturesDir = "assets/%1$s/textures/%2$s.png";
// HashSet<Integer> map2 = new HashSet<>();
// for (String id : bundled.stateMap.keySet()) { Type typeToken = new TypeToken<Map<String, Object>>() {
// if (id.startsWith(modId)) { }.getType();
// BlockType block = bundled.findByState(id);
// BundledBlockData.BlockEntry state = bundled.findById(block.getId()); for (BlockType blockType : BlockTypes.values) {
// if (FaweCache.hasNBT(block.getId())) { if (!blockType.getMaterial().isFullCube()) continue;
// continue; int combined = blockType.getInternalId();
// } String id = blockType.getId();
// // Ignore non blocks String[] split = id.split(":", 2);
// if (!state.material.isFullCube() && !state.material.isRenderedAsNormalBlock()) { String name = split.length == 1 ? id : split[1];
// switch (block.getId()) { String nameSpace = split.length == 1 ? "minecraft" : split[0];
// case 20:
// case 95: Map<String, String> texturesMap = new ConcurrentHashMap<>();
// break; { // Read models
// default: String modelFileName = String.format(modelsDir, nameSpace, name);
// continue; ZipEntry entry = getEntry(zipFile, modelFileName);
// } if (entry == null) {
// } else if (!state.material.isFullCube() || !state.material.isRenderedAsNormalBlock()) { System.out.println("Cannot find " + modelFileName + " in " + file);
// switch (block.getId()) { continue;
// case 165: }
// case 52:
// continue; String textureFileName;
// } try (InputStream is = zipFile.getInputStream(entry)) {
// } JsonReader reader = new JsonReader(new InputStreamReader(is, "UTF-8"));
// if (state.material.getLightValue() != 0) { Map<String, Object> root = gson.fromJson(reader, typeToken);
// continue; Map<String, Object> textures = (Map) root.get("textures");
// }
// id = id.substring(modId.length() + 1).replaceAll(":", "_"); if (textures == null) continue;
// String texture = texturesMap.remove(id); Set<String> models = new HashSet<>();
// if (texture == null) { // Get models
// texture = texturesMap.remove(alphabetize(id)); for (Map.Entry<String, Object> stringObjectEntry : textures.entrySet()) {
// } Object value = stringObjectEntry.getValue();
// if (texture != null) { if (value instanceof String) {
// int combined = block.getCombined(); models.add((String) value);
// switch (block.getId()) { } else if (value instanceof Map) {
// case 17: value = ((Map) value).get("model");
// case 162: if (value != null) models.add((String) value);
// combined += 12; }
// break; }
// case 43: if (models.size() != 1) continue;
// combined += 8;
// break; textureFileName = String.format(texturesDir, nameSpace, models.iterator().next());
// } }
// idMap.putIfAbsent(combined, texture);
// } BufferedImage image = readImage(zipFile, textureFileName);
// } if (image == null) {
// } System.out.println("Cannot find " + textureFileName);
// { // Calculate the colors for each block continue;
// for (Int2ObjectMap.Entry<String> entry : idMap.int2ObjectEntrySet()) { }
// int combined = entry.getIntKey(); int color = ImageUtil.getColor(image);
// String path = texturesDir + "/" + entry.getValue() + ".png"; long distance = getDistance(image, color);
// ZipEntry textureEntry = zipFile.getEntry(path); distanceMap.put((int) combined, (Long) distance);
// try (InputStream is = zipFile.getInputStream(textureEntry)) { colorMap.put((int) combined, (Integer) color);
// BufferedImage image = ImageIO.read(is); }
// int color = ImageUtil.getColor(image); }
// long distance = getDistance(image, color); {
// if (combined == BlockTypesMYCELIUM << 4) distance = Long.MAX_VALUE; Integer grass = null;
// distanceMap.put((int) combined, (Long) distance); {
// colorMap.put((int) combined, (Integer) color); 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 // 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 { public void setTool(BaseItem item, @Nullable Tool tool, Player player) throws InvalidToolBindException {
ItemTypes type = item.getType(); 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"); throw new InvalidToolBindException(type, "Blocks can't be used");
} else if (type == config.wandItem) { } else if (type == config.wandItem) {
throw new InvalidToolBindException(type, "Already used for the wand"); throw new InvalidToolBindException(type, "Already used for the wand");

View File

@ -39,18 +39,13 @@ import java.util.Objects;
import javax.annotation.Nullable; 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 * <p>An instance of this block contains all the information needed to
* accurately reproduce the block, provided that the instance was * accurately reproduce the block, provided that the instance was
* made correctly. In some implementations, it may not be possible to get a * 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 * snapshot of blocks correctly, so, for example, the NBT data for a block
* may be missing.</p> * 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 { public class BaseBlock extends BlockState {
private BlockState blockState; private BlockState blockState;

View File

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

View File

@ -19,11 +19,15 @@
package com.sk89q.worldedit.command.tool; 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.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform; 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. * Plants a tree.

View File

@ -224,7 +224,8 @@ public class DefaultBlockParser extends InputParser<BlockStateHolder> {
state = item.getType().getBlockType().getDefaultState(); state = item.getType().getBlockType().getDefaultState();
nbt = item.getNbtData(); nbt = item.getNbtData();
} else { } else {
state = BlockTypes.parse(typeString.toLowerCase()).getDefaultState(); BlockTypes type = BlockTypes.parse(typeString.toLowerCase());
state = type.getDefaultState();
if (state == null) { if (state == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'"); 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 without writing a hook into every dispatcher, we need to unwrap these
// exceptions and rethrow their converted form, if their is one. // exceptions and rethrow their converted form, if their is one.
try { try {
Request.request().setActor(finalActor);
Object result = dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]); Object result = dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]);
} catch (Throwable t) { } catch (Throwable t) {
// Use the exception converter to convert the exception if any of its causes // 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.EditSession;
import com.sk89q.worldedit.LocalSession; 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.extent.Extent;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -37,6 +39,9 @@ public final class Request {
World world; World world;
private private
@Nullable @Nullable
Actor actor;
private
@Nullable
LocalSession session; LocalSession session;
private private
@Nullable @Nullable
@ -81,6 +86,15 @@ public final class Request {
return null; return null;
} }
@Nullable
public Actor getActor() {
return actor;
}
public void setActor(@Nullable Actor actor) {
this.actor = actor;
}
/** /**
* Get the request session. * 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.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
<<<<<<< HEAD
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
=======
>>>>>>> refs/remotes/sk89q/master
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.LazyBlock; import com.sk89q.worldedit.blocks.LazyBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder; 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.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.world.biome.BaseBiome; 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 com.sk89q.worldedit.world.weather.WeatherType;
import java.util.Collections; import java.util.Collections;

View File

@ -20,14 +20,14 @@
package com.sk89q.worldedit.world.registry; package com.sk89q.worldedit.world.registry;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import com.google.gson.Gson; import com.google.gson.*;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BlockMaterial; import com.sk89q.worldedit.blocks.BlockMaterial;
import com.sk89q.worldedit.util.gson.VectorAdapter; import com.sk89q.worldedit.util.gson.VectorAdapter;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URL; import java.net.URL;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.HashMap; import java.util.HashMap;
@ -75,6 +75,18 @@ public class BundledBlockData {
private void loadFromResource() throws IOException { private void loadFromResource() throws IOException {
GsonBuilder gsonBuilder = new GsonBuilder(); GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Vector.class, new VectorAdapter()); 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(); Gson gson = gsonBuilder.create();
URL url = BundledBlockData.class.getResource("blocks.json"); URL url = BundledBlockData.class.getResource("blocks.json");
if (url == null) { if (url == null) {

View File

@ -178,7 +178,11 @@ public class LegacyMapper {
private BlockState getBlock(int combinedId) { private BlockState getBlock(int combinedId) {
if (combinedId < blockArr.length) { 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); Integer extra = extraId4DataToStateId.get(combinedId);
if (extra == null) { 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 @Override
public boolean isFullCube() { public boolean isFullCube() {
if (blockMaterial == null) { if (blockMaterial == null) {

View File

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

View File

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