block registration / p2

This commit is contained in:
Jesse Boyd 2016-05-17 20:00:08 +10:00
parent 183fcccc64
commit 90b5bb2801
7 changed files with 652 additions and 50 deletions

View File

@ -47,7 +47,9 @@ import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
@ -155,6 +157,7 @@ public class Fawe {
private Thread thread = Thread.currentThread();
private Fawe(final IFawe implementation) {
this.INSTANCE = this;
this.IMP = implementation;
this.thread = Thread.currentThread();
/*
@ -212,6 +215,21 @@ public class Fawe {
Settings.setup(new File(this.IMP.getDirectory(), "config.yml"));
// Setting up message.yml
BBC.load(new File(this.IMP.getDirectory(), "message.yml"));
// Block rotation
try {
BundledBlockData.getInstance().loadFromResource();
} catch (IOException e) {
e.printStackTrace();
}
File jar = MainUtil.getJarFile();
File file = MainUtil.copyFile(jar, "extrablocks.json", null);
if (file != null && file.exists()) {
try {
BundledBlockData.getInstance().add(file.toURI().toURL(), false);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private WorldEdit worldedit;
@ -266,6 +284,7 @@ public class Fawe {
Operations.inject(); // Optimizations
// BlockData
BlockData.inject(); // Temporary fix for 1.9.4
BundledBlockData.inject(); // Add custom rotation
try {
CommandManager.inject(); // Async commands
PlatformManager.inject(); // Async brushes / tools

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLocation;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.regions.FaweMaskManager;
@ -12,7 +13,6 @@ import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.util.WEManager;
import com.intellectualcrafters.plot.object.PseudoRandom;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.NBTInputStream;

View File

@ -4,13 +4,12 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.regions.FaweMask;
import com.boydti.fawe.regions.FaweMaskManager;
import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Location;
import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.object.RegionWrapper;
import com.plotsquared.listener.WEManager;
import com.sk89q.worldedit.BlockVector;
import java.util.HashSet;
import org.bukkit.entity.Player;
public class PlotSquaredFeature extends FaweMaskManager {
public PlotSquaredFeature() {
@ -20,53 +19,33 @@ public class PlotSquaredFeature extends FaweMaskManager {
@Override
public FaweMask getMask(FawePlayer fp) {
final PlotPlayer pp = PlotPlayer.wrap(fp.parent);
Plot plot = pp.getCurrentPlot();
Location loc = pp.getLocation();
final String world = loc.getWorld();
if (plot == null) {
int min = Integer.MAX_VALUE;
for (final Plot p : pp.getPlots()) {
if (p.getArea().worldname.equals(world)) {
Location bot = p.getBottomAbs();
Location top = p.getTopAbs();
Location center = new Location(bot.getWorld(), (bot.getX() + top.getX())/2, 0, (bot.getZ() + top.getZ()) / 2);
final double d = center.getEuclideanDistanceSquared(loc);
if (d < min) {
min = (int) d;
plot = p;
}
}
}
final PlotPlayer pp = PlotPlayer.wrap((Player) fp.parent);
final HashSet<RegionWrapper> regions = WEManager.getMask(pp);
if (regions.size() == 0 || !PS.get().hasPlotArea(pp.getLocation().getWorld())) {
return null;
}
if (plot != null) {
final PlotId id = plot.getId();
if (plot.owner != null) {
if (plot.isOwner(pp.getUUID()) || plot.getTrusted().contains(pp.getUUID()) || (plot.getMembers().contains(pp.getUUID()) && pp.hasPermission("fawe.plotsquared.member"))) {
RegionWrapper region = plot.getLargestRegion();
HashSet<RegionWrapper> regions = plot.getRegions();
final BlockVector pos1 = new BlockVector(region.minX, 0, region.minZ);
final BlockVector pos2 = new BlockVector(region.maxX, 256, region.maxZ);
final HashSet<com.boydti.fawe.object.RegionWrapper> faweRegions = new HashSet<com.boydti.fawe.object.RegionWrapper>();
for (final com.intellectualcrafters.plot.object.RegionWrapper current : regions) {
faweRegions.add(new com.boydti.fawe.object.RegionWrapper(current.minX, current.maxX, current.minZ, current.maxZ));
}
return new FaweMask(pos1, pos2) {
@Override
public String getName() {
return "PLOT^2:" + id;
}
@Override
public HashSet<com.boydti.fawe.object.RegionWrapper> getRegions() {
return faweRegions;
}
};
}
}
final HashSet<com.boydti.fawe.object.RegionWrapper> faweRegions = new HashSet<>();
for (final RegionWrapper current : regions) {
faweRegions.add(new com.boydti.fawe.object.RegionWrapper(current.minX, current.maxX, current.minZ, current.maxZ));
}
return null;
final RegionWrapper region = regions.iterator().next();
final BlockVector pos1 = new BlockVector(region.minX, 0, region.minZ);
final BlockVector pos2 = new BlockVector(region.maxX, 256, region.maxZ);
return new FaweMask(pos1, pos2) {
@Override
public String getName() {
return "PLOT^2";
}
@Override
public boolean contains(BlockVector loc) {
return WEManager.maskContains(regions, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
@Override
public HashSet<com.boydti.fawe.object.RegionWrapper> getRegions() {
return faweRegions;
}
};
}
}

View File

@ -17,10 +17,19 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.Location;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class MainUtil {
/*
@ -65,6 +74,68 @@ public class MainUtil {
}
}
public static File getJarFile() {
try {
URL url = Fawe.class.getProtectionDomain().getCodeSource().getLocation();
return new File(new URL(url.toURI().toString().split("\\!")[0].replaceAll("jar:file", "file")).toURI().getPath());
} catch (MalformedURLException | URISyntaxException | SecurityException e) {
e.printStackTrace();
return new File(Fawe.imp().getDirectory().getParentFile(), "FastAsyncWorldEdit.jar");
}
}
public static File copyFile(File jar, String resource, File output) {
try {
if (output == null) {
output = Fawe.imp().getDirectory();
}
if (!output.exists()) {
output.mkdirs();
}
File newFile = new File(output, resource);
if (newFile.exists()) {
return newFile;
}
try (InputStream stream = Fawe.imp().getClass().getResourceAsStream(resource.startsWith("/") ? resource : "/" + resource)) {
byte[] buffer = new byte[2048];
if (stream == null) {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(jar))) {
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String name = ze.getName();
if (name.equals(resource)) {
new File(newFile.getParent()).mkdirs();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
ze = null;
} else {
ze = zis.getNextEntry();
}
}
zis.closeEntry();
}
return newFile;
}
newFile.createNewFile();
try (FileOutputStream fos = new FileOutputStream(newFile)) {
int len;
while ((len = stream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
return newFile;
}
} catch (IOException e) {
e.printStackTrace();
Fawe.debug("&cCould not save " + resource);
}
return null;
}
public static void sendCompressedMessage(FaweStreamChangeSet set, Actor actor)
{
try {

View File

@ -72,6 +72,7 @@ public final class BlockData {
break;
case 203: // BlockId.PURPUR_STAIRS
case BlockID.RED_SANDSTONE_STAIRS:
case BlockID.OAK_WOOD_STAIRS:
case BlockID.COBBLESTONE_STAIRS:
case BlockID.BRICK_STAIRS:
@ -166,6 +167,7 @@ public final class BlockData {
}
break;
}
case 198: // BlockID.END_ROD
case BlockID.DISPENSER:
case BlockID.DROPPER:
int dispPower = data & 0x8;
@ -312,6 +314,8 @@ public final class BlockData {
}
break;
case 203: // BlockId.PURPUR_STAIRS
case BlockID.RED_SANDSTONE_STAIRS:
case BlockID.OAK_WOOD_STAIRS:
case BlockID.COBBLESTONE_STAIRS:
case BlockID.BRICK_STAIRS:
@ -614,6 +618,8 @@ public final class BlockData {
case BlockID.WOODEN_STEP:
return data ^ (flipY << 3);
case 203: // BlockId.PURPUR_STAIRS
case BlockID.RED_SANDSTONE_STAIRS:
case BlockID.OAK_WOOD_STAIRS:
case BlockID.COBBLESTONE_STAIRS:
case BlockID.BRICK_STAIRS:
@ -686,6 +692,7 @@ public final class BlockData {
}
break;
case 198: // BlockID.END_ROD
case BlockID.DROPPER:
case BlockID.DISPENSER:
int dispPower = data & 0x8;
@ -909,6 +916,8 @@ public final class BlockData {
if (data < 1 || data > 4) return -1;
return mod((data - 1 + increment), 4) + 1;
case 203: // BlockId.PURPUR_STAIRS
case BlockID.RED_SANDSTONE_STAIRS:
case BlockID.OAK_WOOD_STAIRS:
case BlockID.COBBLESTONE_STAIRS:
case BlockID.BRICK_STAIRS:
@ -989,6 +998,7 @@ public final class BlockData {
if (withoutFlags < 2 || withoutFlags > 5) return -1;
return (mod((withoutFlags - 2 + increment), 4) + 2) | extra;
case 198: // BlockID.END_ROD
case BlockID.DISPENSER:
case BlockID.DROPPER:
store = data & 0x8;

View File

@ -0,0 +1,521 @@
/*
* 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.world.registry;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockMaterial;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.annotation.Nullable;
/**
* Provides block data based on the built-in block database that is bundled
* with WorldEdit.
*
* <p>A new instance cannot be created. Use {@link #getInstance()} to get
* an instance.</p>
*
* <p>The data is read from a JSON file that is bundled with WorldEdit. If
* reading fails (which occurs when this class is first instantiated), then
* the methods will return {@code null}s for all blocks.</p>
*/
public class BundledBlockData {
private static final Logger log = Logger.getLogger(BundledBlockData.class.getCanonicalName());
private static final BundledBlockData INSTANCE = new BundledBlockData();
private final Map<String, BlockEntry> idMap = new HashMap<String, BlockEntry>();
private final Map<Integer, BlockEntry> legacyMap = new HashMap<Integer, BlockEntry>(); // Trove usage removed temporarily
/**
* Create a new instance.
*/
private BundledBlockData() {
}
/**
* Attempt to load the data from file.
*
* @throws IOException thrown on I/O error
*/
public void loadFromResource() throws IOException {
URL url = WorldEdit.getInstance().getClass().getResource("/com/sk89q/worldedit/world/registry/blocks.json");
add(url, false);
}
public void add(URL url, boolean overwrite) throws IOException {
if (url == null) {
throw new IOException("Could not find " + url);
}
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Vector.class, new FaweVectorAdapter());
Gson gson = gsonBuilder.create();
String data = Resources.toString(url, Charset.defaultCharset());
List<BlockEntry> entries = gson.fromJson(data, new TypeToken<List<BlockEntry>>() {}.getType());
for (BlockEntry entry : entries) {
add(entry, overwrite);
}
}
public boolean add(BlockEntry entry, boolean overwrite) {
entry.postDeserialization();
if (!overwrite && (idMap.containsKey(entry.id) || legacyMap.containsKey(entry.legacyId))) {
return false;
}
idMap.put(entry.id, entry);
legacyMap.put(entry.legacyId, entry);
return true;
}
/**
* Return the entry for the given block ID.
*
* @param id the ID
* @return the entry, or null
*/
@Nullable
public BlockEntry findById(String id) {
return idMap.get(id);
}
/**
* Return the entry for the given block legacy numeric ID.
*
* @param id the ID
* @return the entry, or null
*/
@Nullable
public BlockEntry findById(int id) {
return legacyMap.get(id);
}
/**
* Convert the given string ID to a legacy numeric ID.
*
* @param id the ID
* @return the legacy ID, which may be null if the block does not have a legacy ID
*/
@Nullable
public Integer toLegacyId(String id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.legacyId;
} else {
return null;
}
}
/**
* Get the material properties for the given block.
*
* @param id the legacy numeric ID
* @return the material's properties, or null
*/
@Nullable
public BlockMaterial getMaterialById(int id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.material;
} else {
return null;
}
}
/**
* Get the states for the given block.
*
* @param id the legacy numeric ID
* @return the block's states, or null if no information is available
*/
@Nullable
public Map<String, ? extends State> getStatesById(int id) {
BlockEntry entry = findById(id);
if (entry != null) {
return entry.states;
} else {
return null;
}
}
/**
* Get a singleton instance of this object.
*
* @return the instance
*/
public static BundledBlockData getInstance() {
return INSTANCE;
}
public static class BlockEntry {
private int legacyId;
private String id;
private String unlocalizedName;
private List<String> aliases;
private Map<String, FaweState> states = new HashMap<String, FaweState>();
private FaweBlockMaterial material = new FaweBlockMaterial();
void postDeserialization() {
for (FaweState state : states.values()) {
state.postDeserialization();
}
}
}
public static Class<?> inject() {
return BundledBlockData.class;
}
public class FaweVectorAdapter implements JsonDeserializer<Vector> {
@Override
public Vector deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray jsonArray = json.getAsJsonArray();
if (jsonArray.size() != 3) {
throw new JsonParseException("Expected array of 3 length for Vector");
}
double x = jsonArray.get(0).getAsDouble();
double y = jsonArray.get(1).getAsDouble();
double z = jsonArray.get(2).getAsDouble();
return new Vector(x, y, z);
}
}
class FaweStateValue implements StateValue {
private FaweState state;
private Byte data;
private Vector direction;
void setState(FaweState state) {
this.state = state;
}
@Override
public boolean isSet(BaseBlock block) {
return data != null && (block.getData() & state.getDataMask()) == data;
}
@Override
public boolean set(BaseBlock block) {
if (data != null) {
block.setData((block.getData() & ~state.getDataMask()) | data);
return true;
} else {
return false;
}
}
@Override
public Vector getDirection() {
return direction;
}
}
class FaweState implements State {
private Byte dataMask;
private Map<String, FaweStateValue> values;
@Override
public Map<String, FaweStateValue> valueMap() {
return Collections.unmodifiableMap(values);
}
@Nullable
@Override
public StateValue getValue(BaseBlock block) {
for (StateValue value : values.values()) {
if (value.isSet(block)) {
return value;
}
}
return null;
}
byte getDataMask() {
return dataMask != null ? dataMask : 0xF;
}
@Override
public boolean hasDirection() {
for (FaweStateValue value : values.values()) {
if (value.getDirection() != null) {
return true;
}
}
return false;
}
void postDeserialization() {
for (FaweStateValue v : values.values()) {
v.setState(this);
}
}
}
public static class FaweBlockMaterial implements BlockMaterial {
private boolean renderedAsNormalBlock;
private boolean fullCube;
private boolean opaque;
private boolean powerSource;
private boolean liquid;
private boolean solid;
private float hardness;
private float resistance;
private float slipperiness;
private boolean grassBlocking;
private float ambientOcclusionLightValue;
private int lightOpacity;
private int lightValue;
private boolean fragileWhenPushed;
private boolean unpushable;
private boolean adventureModeExempt;
private boolean ticksRandomly;
private boolean usingNeighborLight;
private boolean movementBlocker;
private boolean burnable;
private boolean toolRequired;
private boolean replacedDuringPlacement;
@Override
public boolean isRenderedAsNormalBlock() {
return renderedAsNormalBlock;
}
public void setRenderedAsNormalBlock(boolean renderedAsNormalBlock) {
this.renderedAsNormalBlock = renderedAsNormalBlock;
}
@Override
public boolean isFullCube() {
return fullCube;
}
public void setFullCube(boolean fullCube) {
this.fullCube = fullCube;
}
@Override
public boolean isOpaque() {
return opaque;
}
public void setOpaque(boolean opaque) {
this.opaque = opaque;
}
@Override
public boolean isPowerSource() {
return powerSource;
}
public void setPowerSource(boolean powerSource) {
this.powerSource = powerSource;
}
@Override
public boolean isLiquid() {
return liquid;
}
public void setLiquid(boolean liquid) {
this.liquid = liquid;
}
@Override
public boolean isSolid() {
return solid;
}
public void setSolid(boolean solid) {
this.solid = solid;
}
@Override
public float getHardness() {
return hardness;
}
public void setHardness(float hardness) {
this.hardness = hardness;
}
@Override
public float getResistance() {
return resistance;
}
public void setResistance(float resistance) {
this.resistance = resistance;
}
@Override
public float getSlipperiness() {
return slipperiness;
}
public void setSlipperiness(float slipperiness) {
this.slipperiness = slipperiness;
}
@Override
public boolean isGrassBlocking() {
return grassBlocking;
}
public void setGrassBlocking(boolean grassBlocking) {
this.grassBlocking = grassBlocking;
}
@Override
public float getAmbientOcclusionLightValue() {
return ambientOcclusionLightValue;
}
public void setAmbientOcclusionLightValue(float ambientOcclusionLightValue) {
this.ambientOcclusionLightValue = ambientOcclusionLightValue;
}
@Override
public int getLightOpacity() {
return lightOpacity;
}
public void setLightOpacity(int lightOpacity) {
this.lightOpacity = lightOpacity;
}
@Override
public int getLightValue() {
return lightValue;
}
public void setLightValue(int lightValue) {
this.lightValue = lightValue;
}
@Override
public boolean isFragileWhenPushed() {
return fragileWhenPushed;
}
public void setFragileWhenPushed(boolean fragileWhenPushed) {
this.fragileWhenPushed = fragileWhenPushed;
}
@Override
public boolean isUnpushable() {
return unpushable;
}
public void setUnpushable(boolean unpushable) {
this.unpushable = unpushable;
}
@Override
public boolean isAdventureModeExempt() {
return adventureModeExempt;
}
public void setAdventureModeExempt(boolean adventureModeExempt) {
this.adventureModeExempt = adventureModeExempt;
}
@Override
public boolean isTicksRandomly() {
return ticksRandomly;
}
public void setTicksRandomly(boolean ticksRandomly) {
this.ticksRandomly = ticksRandomly;
}
@Override
public boolean isUsingNeighborLight() {
return usingNeighborLight;
}
public void setUsingNeighborLight(boolean usingNeighborLight) {
this.usingNeighborLight = usingNeighborLight;
}
@Override
public boolean isMovementBlocker() {
return movementBlocker;
}
public void setMovementBlocker(boolean movementBlocker) {
this.movementBlocker = movementBlocker;
}
@Override
public boolean isBurnable() {
return burnable;
}
public void setBurnable(boolean burnable) {
this.burnable = burnable;
}
@Override
public boolean isToolRequired() {
return toolRequired;
}
public void setToolRequired(boolean toolRequired) {
this.toolRequired = toolRequired;
}
@Override
public boolean isReplacedDuringPlacement() {
return replacedDuringPlacement;
}
public void setReplacedDuringPlacement(boolean replacedDuringPlacement) {
this.replacedDuringPlacement = replacedDuringPlacement;
}
}
}

View File

@ -0,0 +1,2 @@
// Add extra blocks here
// See: https://github.com/sk89q/WorldEdit/blob/master/worldedit-core/src/main/resources/com/sk89q/worldedit/world/registry/blocks.json