Archiviert
13
0

Improvements to BlockStates

* Actually capture all the data of TileEntities. This is done by creating a copy of the TileEntity. The methods of BlockState which currently directly access the TileEntity reference will modify the data of that TileEntity-snapshot instead.
* With the call to BlockState.update, the captured TileEntity data gets applied to the current TileEntity in the world.
* Methods which trigger block specific actions will use the current TileEntity from the world.
* CraftBlockState does not hand out the wrapped or the snapshot TileEntity directly. Instead, it provides an applyTo method to copy the data to a given TileEntity and a method to directly get a copy of the TileEntity NBT data represented by the BlockState. CraftMetaBlockState was updated to make use of that.
* Added #getSnapshotInventory() to bukkit which allows modifiying the captured inventory snapshots of containers.
* Tried to clarify which methods only work if the BlockState is placed, which methods require the block in the world to still be of the same type (methods which trigger actions), and that .getInventory() directly modifies the inventory of the block in the world if the BlockState is placed and becomes invalid if the block type is changed.

Backwards compatibility

* If the BlockState acts as InventoryHolder, getInventory() will still return the inventory directly backed by the TileEntity in the world (like before), and not the snapshot inventory. This compromise should reduce the potential of these changes to break existing plugins, or craftbukkit's own use of BlockState.
* The snapshot's inventory can be accessed by a new method getSnapshotInventory()
* In case the BlockState is not placed (if it was retrieved from the MetaBlockState of an item), the getInventory() method will however return the snapshot inventory. So that when the BlockState gets applied back to the item, the inventory changes are properly included.
* With the changes to CraftMetaBlockState it is no longer required to call the update method before passing a modified BlockState to the CraftMetaBlockState. For backwards compatibility the update method will simply return true for a non-placed BlockState, without actually doing anything.

Impact on plugins
* Restoring blocks now actually works as expected, properly restoring the TileEntity data, reglardless if the block changed its type in the meantime.
* Plugins are now consistently required to call the update method in order to apply changes to blocks. Though, regarding the Javadoc they should have been required to do so anyways.
* New feature: Plugins can take and modify inventory snapshots.
* Breaking change: If a plugin gets the BlockState of a block in the world, modifies the inventory returned by .getInventory(), and then tries to use the same BlockState to apply the TileEntity data to an ItemStack block meta, the ItemStack will use the snapshot inventory, disregarding the changes made to the inventory returned by .getInventory(). This is the compromise of .getInventory() returning the inventory directly backed by the TileEntity in the world.

Other fixes related to BlockState:
* TileEntityContainer#getLocation() will run into a NPE if the TileEntity is non-placed (ex. when getting the BlockState from a CraftMetaBlockState).
* Beacon.getEntitiesInRange() would previously throw a NPE if called for a non-placed BlockState. It was changed to now require to be placed and use the current TileEntity in the world. If the TileEntity in the world is no longer a beacon, it will return an empty list.
* EndGateway now supports setting and getting the exit location even for non-placed EndGateways (inside BlockStateMeta) by using / returning a location with world being null.
Dieser Commit ist enthalten in:
Lukas Hennig 2017-08-05 14:37:19 +10:00 committet von md_5
Ursprung 63029f4ff3
Commit 19507baf8b
31 geänderte Dateien mit 531 neuen und 652 gelöschten Zeilen

Datei anzeigen

@ -1,6 +1,6 @@
--- a/net/minecraft/server/TileEntityBrewingStand.java
+++ b/net/minecraft/server/TileEntityBrewingStand.java
@@ -3,6 +3,15 @@
@@ -3,6 +3,16 @@
import java.util.Arrays;
import java.util.Iterator;
@ -11,12 +11,13 @@
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.inventory.BrewEvent;
+import org.bukkit.event.inventory.BrewingStandFuelEvent;
+import org.bukkit.inventory.InventoryHolder;
+// CraftBukkit end
+
public class TileEntityBrewingStand extends TileEntityContainer implements ITickable, IWorldInventory {
private static final int[] a = new int[] { 3};
@@ -14,6 +23,31 @@
@@ -14,6 +24,31 @@
private Item k;
private String l;
private int fuelLevel;
@ -48,7 +49,7 @@
public TileEntityBrewingStand() {
this.items = NonNullList.a(5, ItemStack.a);
@@ -55,8 +89,19 @@
@@ -55,8 +90,19 @@
ItemStack itemstack = (ItemStack) this.items.get(4);
if (this.fuelLevel <= 0 && itemstack.getItem() == Items.BLAZE_POWDER) {
@ -70,7 +71,7 @@
this.update();
}
@@ -64,9 +109,14 @@
@@ -64,9 +110,14 @@
boolean flag1 = this.brewTime > 0;
ItemStack itemstack1 = (ItemStack) this.items.get(3);
@ -87,13 +88,14 @@
if (flag2 && flag) {
this.p();
@@ -140,6 +190,15 @@
@@ -140,6 +191,16 @@
private void p() {
ItemStack itemstack = (ItemStack) this.items.get(3);
+ // CraftBukkit start
+ if (getOwner() != null) {
+ BrewEvent event = new BrewEvent(world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), (org.bukkit.inventory.BrewerInventory) this.getOwner().getInventory(), this.fuelLevel);
+ InventoryHolder owner = this.getOwner();
+ if (owner != null) {
+ BrewEvent event = new BrewEvent(world.getWorld().getBlockAt(position.getX(), position.getY(), position.getZ()), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), this.fuelLevel);
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return;
@ -103,7 +105,7 @@
for (int i = 0; i < 3; ++i) {
this.items.set(i, PotionBrewer.d(itemstack, (ItemStack) this.items.get(i)));
@@ -210,7 +269,7 @@
@@ -210,7 +271,7 @@
}
public int getMaxStackSize() {

Datei anzeigen

@ -1,6 +1,6 @@
--- a/net/minecraft/server/TileEntityContainer.java
+++ b/net/minecraft/server/TileEntityContainer.java
@@ -37,4 +37,11 @@
@@ -37,4 +37,12 @@
public IChatBaseComponent getScoreboardDisplayName() {
return (IChatBaseComponent) (this.hasCustomName() ? new ChatComponentText(this.getName()) : new ChatMessage(this.getName(), new Object[0]));
}
@ -8,6 +8,7 @@
+ // CraftBukkit start
+ @Override
+ public org.bukkit.Location getLocation() {
+ if (world == null) return null;
+ return new org.bukkit.Location(world.getWorld(), position.getX(), position.getY(), position.getZ());
+ }
+ // CraftBukkit end

Datei anzeigen

@ -12,33 +12,23 @@ import org.bukkit.block.Banner;
import org.bukkit.block.Block;
import org.bukkit.block.banner.Pattern;
import org.bukkit.block.banner.PatternType;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftBanner extends CraftBlockState implements Banner {
public class CraftBanner extends CraftBlockEntityState<TileEntityBanner> implements Banner {
private final TileEntityBanner banner;
private DyeColor base;
private List<Pattern> patterns = new ArrayList<Pattern>();
public CraftBanner(final Block block) {
super(block);
CraftWorld world = (CraftWorld) block.getWorld();
banner = (TileEntityBanner) world.getTileEntityAt(getX(), getY(), getZ());
base = DyeColor.getByDyeData((byte) banner.color.getInvColorIndex());
if (banner.patterns != null) {
for (int i = 0; i < banner.patterns.size(); i++) {
NBTTagCompound p = (NBTTagCompound) banner.patterns.get(i);
patterns.add(new Pattern(DyeColor.getByDyeData((byte) p.getInt("Color")), PatternType.getByIdentifier(p.getString("Pattern"))));
}
}
super(block, TileEntityBanner.class);
}
public CraftBanner(final Material material, final TileEntityBanner te) {
super(material);
banner = te;
super(material, te);
}
@Override
public void load(TileEntityBanner banner) {
super.load(banner);
base = DyeColor.getByDyeData((byte) banner.color.getInvColorIndex());
@ -96,10 +86,9 @@ public class CraftBanner extends CraftBlockState implements Banner {
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
public void applyTo(TileEntityBanner banner) {
super.applyTo(banner);
if (result) {
banner.color = EnumColor.fromInvColorIndex(base.getDyeData());
NBTTagList newPatterns = new NBTTagList();
@ -110,17 +99,6 @@ public class CraftBanner extends CraftBlockState implements Banner {
compound.setString("Pattern", p.getPattern().getIdentifier());
newPatterns.add(compound);
}
banner.patterns = newPatterns;
banner.update();
}
return result;
}
@Override
public TileEntityBanner getTileEntity() {
return banner;
}
}

Datei anzeigen

@ -4,56 +4,47 @@ import java.util.ArrayList;
import java.util.Collection;
import net.minecraft.server.EntityHuman;
import net.minecraft.server.MobEffectList;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityBeacon;
import org.bukkit.Material;
import org.bukkit.block.Beacon;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventoryBeacon;
import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.BeaconInventory;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
public class CraftBeacon extends CraftContainer implements Beacon {
private final CraftWorld world;
private final TileEntityBeacon beacon;
public class CraftBeacon extends CraftContainer<TileEntityBeacon> implements Beacon {
public CraftBeacon(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
beacon = (TileEntityBeacon) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityBeacon.class);
}
public CraftBeacon(final Material material, final TileEntityBeacon te) {
super(material, te);
world = null;
beacon = te;
}
public Inventory getInventory() {
return new CraftInventoryBeacon(beacon);
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
beacon.update();
}
return result;
public BeaconInventory getSnapshotInventory() {
return new CraftInventoryBeacon(this.getSnapshot());
}
@Override
public TileEntityBeacon getTileEntity() {
return beacon;
public BeaconInventory getInventory() {
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventoryBeacon(this.getTileEntity());
}
@Override
public Collection<LivingEntity> getEntitiesInRange() {
TileEntity tileEntity = this.getTileEntityFromWorld();
if (tileEntity instanceof TileEntityBeacon) {
TileEntityBeacon beacon = (TileEntityBeacon) tileEntity;
Collection<EntityHuman> nms = beacon.getHumansInRange();
Collection<LivingEntity> bukkit = new ArrayList<LivingEntity>(nms.size());
@ -64,38 +55,43 @@ public class CraftBeacon extends CraftContainer implements Beacon {
return bukkit;
}
// block is no longer a beacon
return new ArrayList<LivingEntity>();
}
@Override
public int getTier() {
return beacon.levels;
return this.getSnapshot().levels;
}
@Override
public PotionEffect getPrimaryEffect() {
return beacon.getPrimaryEffect();
return this.getSnapshot().getPrimaryEffect();
}
@Override
public void setPrimaryEffect(PotionEffectType effect) {
beacon.primaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null;
this.getSnapshot().primaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null;
}
@Override
public PotionEffect getSecondaryEffect() {
return beacon.getSecondaryEffect();
return this.getSnapshot().getSecondaryEffect();
}
@Override
public void setSecondaryEffect(PotionEffectType effect) {
beacon.secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null;
this.getSnapshot().secondaryEffect = (effect != null) ? MobEffectList.fromId(effect.getId()) : null;
}
@Override
public String getCustomName() {
TileEntityBeacon beacon = this.getSnapshot();
return beacon.hasCustomName() ? beacon.getName() : null;
}
@Override
public void setCustomName(String name) {
beacon.setCustomName(name);
this.getSnapshot().setCustomName(name);
}
}

Datei anzeigen

@ -2,36 +2,29 @@ package org.bukkit.craftbukkit.block;
import com.google.common.base.Preconditions;
import net.minecraft.server.EnumColor;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityBed;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.Bed;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftBed extends CraftBlockState implements Bed {
public class CraftBed extends CraftBlockEntityState<TileEntityBed> implements Bed {
private final TileEntityBed bed;
private DyeColor color;
public CraftBed(Block block) {
super(block);
bed = (TileEntityBed) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
color = DyeColor.getByWoolData((byte) bed.a().getColorIndex());
super(block, TileEntityBed.class);
}
public CraftBed(Material material, TileEntityBed te) {
super(material);
bed = te;
color = DyeColor.getByWoolData((byte) bed.a().getColorIndex());
super(material, te);
}
@Override
public TileEntity getTileEntity() {
return bed;
public void load(TileEntityBed bed) {
super.load(bed);
color = DyeColor.getByWoolData((byte) bed.a().getColorIndex());
}
@Override
@ -47,14 +40,9 @@ public class CraftBed extends CraftBlockState implements Bed {
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
public void applyTo(TileEntityBed bed) {
super.applyTo(bed);
if (result) {
bed.a(EnumColor.fromColorIndex(color.getWoolData()));
bed.update();
}
return result;
}
}

Datei anzeigen

@ -336,9 +336,16 @@ public class CraftBlock implements Block {
case BED_BLOCK:
return new CraftBed(this);
default:
TileEntity tileEntity = chunk.getCraftWorld().getTileEntityAt(x, y, z);
if (tileEntity != null) {
// block with unhandled TileEntity:
return new CraftBlockEntityState<TileEntity>(this, (Class<TileEntity>) tileEntity.getClass());
} else {
// Block without TileEntity:
return new CraftBlockState(this);
}
}
}
public Biome getBiome() {
return getWorld().getBiome(x, z);

Datei anzeigen

@ -0,0 +1,120 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.NBTTagCompound;
import net.minecraft.server.TileEntity;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState {
private final Class<T> tileEntityClass;
private final T tileEntity;
private final T snapshot;
public CraftBlockEntityState(Block block, Class<T> tileEntityClass) {
super(block);
this.tileEntityClass = tileEntityClass;
// get tile entity from block:
CraftWorld world = (CraftWorld) this.getWorld();
this.tileEntity = tileEntityClass.cast(world.getTileEntityAt(this.getX(), this.getY(), this.getZ()));
// copy tile entity data:
this.snapshot = this.createSnapshot(tileEntity);
this.load(snapshot);
}
public CraftBlockEntityState(Material material, T tileEntity) {
super(material);
this.tileEntityClass = (Class<T>) tileEntity.getClass();
this.tileEntity = tileEntity;
// copy tile entity data:
this.snapshot = this.createSnapshot(tileEntity);
this.load(snapshot);
}
private T createSnapshot(T tileEntity) {
if (tileEntity == null) {
return null;
}
NBTTagCompound nbtTagCompound = tileEntity.save(new NBTTagCompound());
T snapshot = (T) TileEntity.create(null, nbtTagCompound);
return snapshot;
}
// copies the TileEntity-specific data, retains the position
private void copyData(T from, T to) {
BlockPosition pos = to.getPosition();
NBTTagCompound nbtTagCompound = from.save(new NBTTagCompound());
to.load(nbtTagCompound);
// reset the original position:
to.setPosition(pos);
}
// gets the wrapped TileEntity
protected T getTileEntity() {
return tileEntity;
}
// gets the cloned TileEntity which is used to store the captured data
protected T getSnapshot() {
return snapshot;
}
// gets the current TileEntity from the world at this position
protected TileEntity getTileEntityFromWorld() {
requirePlaced();
return ((CraftWorld) this.getWorld()).getTileEntityAt(this.getX(), this.getY(), this.getZ());
}
// gets the NBT data of the TileEntity represented by this block state
public NBTTagCompound getSnapshotNBT() {
// update snapshot
applyTo(snapshot);
return snapshot.save(new NBTTagCompound());
}
// copies the data of the given tile entity data to this block state
protected void load(T tileEntity) {
if (tileEntity != null && tileEntity != snapshot) {
copyData(tileEntity, snapshot);
}
}
// applies the TileEntity data of this block state to the given TileEntity
protected void applyTo(T tileEntity) {
if (tileEntity != null && tileEntity != snapshot) {
copyData(snapshot, tileEntity);
}
}
protected boolean isApplicable(TileEntity tileEntity) {
return tileEntityClass.isInstance(tileEntity);
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result && this.isPlaced()) {
TileEntity tile = getTileEntityFromWorld();
if (isApplicable(tile)) {
applyTo(tileEntityClass.cast(tile));
tile.update();
}
}
return result;
}
}

Datei anzeigen

@ -3,7 +3,6 @@ package org.bukkit.craftbukkit.block;
import net.minecraft.server.BlockPosition;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
@ -17,9 +16,7 @@ import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin;
import java.util.List;
import net.minecraft.server.EnumDirection;
import net.minecraft.server.IBlockData;
import net.minecraft.server.TileEntity;
public class CraftBlockState implements BlockState {
private final CraftWorld world;
@ -256,10 +253,6 @@ public class CraftBlockState implements BlockState {
return hash;
}
public TileEntity getTileEntity() {
return null;
}
public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
requirePlaced();
chunk.getCraftWorld().getBlockMetadata().setMetadata(getBlock(), metadataKey, newMetadataValue);

Datei anzeigen

@ -4,69 +4,61 @@ import net.minecraft.server.TileEntityBrewingStand;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BrewingStand;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventoryBrewer;
import org.bukkit.inventory.BrewerInventory;
public class CraftBrewingStand extends CraftContainer implements BrewingStand {
private final TileEntityBrewingStand brewingStand;
public class CraftBrewingStand extends CraftContainer<TileEntityBrewingStand> implements BrewingStand {
public CraftBrewingStand(Block block) {
super(block);
brewingStand = (TileEntityBrewingStand) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityBrewingStand.class);
}
public CraftBrewingStand(final Material material, final TileEntityBrewingStand te) {
super(material, te);
brewingStand = te;
}
@Override
public BrewerInventory getSnapshotInventory() {
return new CraftInventoryBrewer(this.getSnapshot());
}
@Override
public BrewerInventory getInventory() {
return new CraftInventoryBrewer(brewingStand);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventoryBrewer(this.getTileEntity());
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
brewingStand.update();
}
return result;
}
public int getBrewingTime() {
return brewingStand.getProperty(0);
}
public void setBrewingTime(int brewTime) {
brewingStand.setProperty(0, brewTime);
return this.getSnapshot().getProperty(0);
}
@Override
public TileEntityBrewingStand getTileEntity() {
return brewingStand;
public void setBrewingTime(int brewTime) {
this.getSnapshot().setProperty(0, brewTime);
}
@Override
public int getFuelLevel() {
return brewingStand.getProperty(1);
return this.getSnapshot().getProperty(1);
}
@Override
public void setFuelLevel(int level) {
brewingStand.setProperty(1, level);
this.getSnapshot().setProperty(1, level);
}
@Override
public String getCustomName() {
TileEntityBrewingStand brewingStand = this.getSnapshot();
return brewingStand.hasCustomName() ? brewingStand.getName() : null;
}
@Override
public void setCustomName(String name) {
brewingStand.setCustomName(name);
this.getSnapshot().setCustomName(name);
}
}

Datei anzeigen

@ -11,36 +11,43 @@ import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest;
import org.bukkit.inventory.Inventory;
public class CraftChest extends CraftLootable implements Chest {
private final CraftWorld world;
private final TileEntityChest chest;
public class CraftChest extends CraftLootable<TileEntityChest> implements Chest {
public CraftChest(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
chest = (TileEntityChest) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityChest.class);
}
public CraftChest(final Material material, final TileEntityChest te) {
super(material, te);
chest = te;
world = null;
}
@Override
public Inventory getSnapshotInventory() {
return new CraftInventory(this.getSnapshot());
}
@Override
public Inventory getBlockInventory() {
return new CraftInventory(chest);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventory(this.getTileEntity());
}
@Override
public Inventory getInventory() {
int x = getX();
int y = getY();
int z = getZ();
// The logic here is basically identical to the logic in BlockChest.interact
CraftInventory inventory = new CraftInventory(chest);
CraftInventory inventory = (CraftInventory) this.getBlockInventory();
if (!isPlaced()) {
return inventory;
}
// The logic here is basically identical to the logic in BlockChest.interact
int x = this.getX();
int y = this.getY();
int z = this.getZ();
CraftWorld world = (CraftWorld) this.getWorld();
int id;
if (world.getBlockTypeIdAt(x, y, z) == Material.CHEST.getId()) {
id = Material.CHEST.getId();
@ -68,20 +75,4 @@ public class CraftChest extends CraftLootable implements Chest {
}
return inventory;
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
chest.update();
}
return result;
}
@Override
public TileEntityChest getTileEntity() {
return chest;
}
}

Datei anzeigen

@ -4,58 +4,53 @@ import net.minecraft.server.TileEntityCommand;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CommandBlock;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftCommandBlock extends CraftBlockState implements CommandBlock {
private final TileEntityCommand commandBlock;
public class CraftCommandBlock extends CraftBlockEntityState<TileEntityCommand> implements CommandBlock {
private String command;
private String name;
public CraftCommandBlock(Block block) {
super(block);
CraftWorld world = (CraftWorld) block.getWorld();
commandBlock = (TileEntityCommand) world.getTileEntityAt(getX(), getY(), getZ());
command = commandBlock.getCommandBlock().getCommand();
name = commandBlock.getCommandBlock().getName();
super(block, TileEntityCommand.class);
}
public CraftCommandBlock(final Material material, final TileEntityCommand te) {
super(material);
commandBlock = te;
super(material, te);
}
@Override
public void load(TileEntityCommand commandBlock) {
super.load(commandBlock);
command = commandBlock.getCommandBlock().getCommand();
name = commandBlock.getCommandBlock().getName();
}
@Override
public String getCommand() {
return command;
}
@Override
public void setCommand(String command) {
this.command = command != null ? command : "";
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name != null ? name : "@";
}
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
@Override
public void applyTo(TileEntityCommand commandBlock) {
super.applyTo(commandBlock);
if (result) {
commandBlock.getCommandBlock().setCommand(command);
commandBlock.getCommandBlock().setName(name);
}
return result;
}
@Override
public TileEntityCommand getTileEntity() {
return commandBlock;
}
}

Datei anzeigen

@ -1,33 +1,17 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityComparator;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Comparator;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftComparator extends CraftBlockState implements Comparator {
private final CraftWorld world;
private final TileEntityComparator comparator;
public class CraftComparator extends CraftBlockEntityState<TileEntityComparator> implements Comparator {
public CraftComparator(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
comparator = (TileEntityComparator) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityComparator.class);
}
public CraftComparator(final Material material, final TileEntityComparator te) {
super(material);
comparator = te;
world = null;
}
@Override
public TileEntity getTileEntity() {
return comparator;
super(material, te);
}
}

Datei anzeigen

@ -1,41 +1,33 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.ChestLock;
import net.minecraft.server.ITileInventory;
import net.minecraft.server.TileEntityContainer;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Lockable;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.block.Container;
public class CraftContainer extends CraftBlockState implements Lockable {
public abstract class CraftContainer<T extends TileEntityContainer> extends CraftBlockEntityState<T> implements Container {
private final ITileInventory container;
public CraftContainer(Block block) {
super(block);
container = (TileEntityContainer) ((CraftWorld) block.getWorld()).getTileEntityAt(block.getX(), block.getY(), block.getZ());
public CraftContainer(Block block, Class<T> tileEntityClass) {
super(block, tileEntityClass);
}
public CraftContainer(final Material material, ITileInventory tileEntity) {
super(material);
container = tileEntity;
public CraftContainer(final Material material, T tileEntity) {
super(material, tileEntity);
}
@Override
public boolean isLocked() {
return container.isLocked();
return this.getSnapshot().isLocked();
}
@Override
public String getLock() {
return container.getLock().getKey();
return this.getSnapshot().getLock().getKey();
}
@Override
public void setLock(String key) {
container.setLock(key == null ? ChestLock.a : new ChestLock(key));
this.getSnapshot().setLock(key == null ? ChestLock.a : new ChestLock(key));
}
}

Datei anzeigen

@ -6,40 +6,39 @@ import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.entity.EntityType;
public class CraftCreatureSpawner extends CraftBlockState implements CreatureSpawner {
private final TileEntityMobSpawner spawner;
public class CraftCreatureSpawner extends CraftBlockEntityState<TileEntityMobSpawner> implements CreatureSpawner {
public CraftCreatureSpawner(final Block block) {
super(block);
spawner = (TileEntityMobSpawner) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityMobSpawner.class);
}
public CraftCreatureSpawner(final Material material, TileEntityMobSpawner te) {
super(material);
spawner = te;
super(material, te);
}
@Override
public EntityType getSpawnedType() {
MinecraftKey key = spawner.getSpawner().getMobName();
MinecraftKey key = this.getSnapshot().getSpawner().getMobName();
return (key == null) ? EntityType.PIG : EntityType.fromName(key.getKey());
}
@Override
public void setSpawnedType(EntityType entityType) {
if (entityType == null || entityType.getName() == null) {
throw new IllegalArgumentException("Can't spawn EntityType " + entityType + " from mobspawners!");
}
spawner.getSpawner().setMobName(new MinecraftKey(entityType.getName()));
this.getSnapshot().getSpawner().setMobName(new MinecraftKey(entityType.getName()));
}
@Override
public String getCreatureTypeName() {
return spawner.getSpawner().getMobName().getKey();
return this.getSnapshot().getSpawner().getMobName().getKey();
}
@Override
public void setCreatureTypeByName(String creatureType) {
// Verify input
EntityType type = EntityType.fromName(creatureType);
@ -49,16 +48,13 @@ public class CraftCreatureSpawner extends CraftBlockState implements CreatureSpa
setSpawnedType(type);
}
@Override
public int getDelay() {
return spawner.getSpawner().spawnDelay;
}
public void setDelay(int delay) {
spawner.getSpawner().spawnDelay = delay;
return this.getSnapshot().getSpawner().spawnDelay;
}
@Override
public TileEntityMobSpawner getTileEntity() {
return spawner;
public void setDelay(int delay) {
this.getSnapshot().getSpawner().spawnDelay = delay;
}
}

Datei anzeigen

@ -1,33 +1,17 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityLightDetector;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.DaylightDetector;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftDaylightDetector extends CraftBlockState implements DaylightDetector {
private final CraftWorld world;
private final TileEntityLightDetector detector;
public class CraftDaylightDetector extends CraftBlockEntityState<TileEntityLightDetector> implements DaylightDetector {
public CraftDaylightDetector(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
detector = (TileEntityLightDetector) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityLightDetector.class);
}
public CraftDaylightDetector(final Material material, final TileEntityLightDetector te) {
super(material);
detector = te;
world = null;
}
@Override
public TileEntity getTileEntity() {
return detector;
super(material, te);
}
}

Datei anzeigen

@ -14,27 +14,31 @@ import org.bukkit.craftbukkit.projectiles.CraftBlockProjectileSource;
import org.bukkit.inventory.Inventory;
import org.bukkit.projectiles.BlockProjectileSource;
public class CraftDispenser extends CraftLootable implements Dispenser {
private final CraftWorld world;
private final TileEntityDispenser dispenser;
public class CraftDispenser extends CraftLootable<TileEntityDispenser> implements Dispenser {
public CraftDispenser(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
dispenser = (TileEntityDispenser) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityDispenser.class);
}
public CraftDispenser(final Material material, final TileEntityDispenser te) {
super(material, te);
world = null;
dispenser = te;
}
@Override
public Inventory getSnapshotInventory() {
return new CraftInventory(this.getSnapshot());
}
@Override
public Inventory getInventory() {
return new CraftInventory(dispenser);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventory(this.getTileEntity());
}
@Override
public BlockProjectileSource getBlockProjectileSource() {
Block block = getBlock();
@ -42,13 +46,15 @@ public class CraftDispenser extends CraftLootable implements Dispenser {
return null;
}
return new CraftBlockProjectileSource(dispenser);
return new CraftBlockProjectileSource((TileEntityDispenser) this.getTileEntityFromWorld());
}
@Override
public boolean dispense() {
Block block = getBlock();
if (block.getType() == Material.DISPENSER) {
CraftWorld world = (CraftWorld) this.getWorld();
BlockDispenser dispense = (BlockDispenser) Blocks.DISPENSER;
dispense.dispense(world.getHandle(), new BlockPosition(getX(), getY(), getZ()));
@ -57,20 +63,4 @@ public class CraftDispenser extends CraftLootable implements Dispenser {
return false;
}
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
dispenser.update();
}
return result;
}
@Override
public TileEntityDispenser getTileEntity() {
return dispenser;
}
}

Datei anzeigen

@ -12,50 +12,39 @@ import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.inventory.Inventory;
public class CraftDropper extends CraftLootable implements Dropper {
private final CraftWorld world;
private final TileEntityDropper dropper;
public class CraftDropper extends CraftLootable<TileEntityDropper> implements Dropper {
public CraftDropper(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
dropper = (TileEntityDropper) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityDropper.class);
}
public CraftDropper(final Material material, TileEntityDropper te) {
super(material, te);
world = null;
dropper = te;
}
@Override
public Inventory getSnapshotInventory() {
return new CraftInventory(this.getSnapshot());
}
@Override
public Inventory getInventory() {
return new CraftInventory(dropper);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventory(this.getTileEntity());
}
@Override
public void drop() {
Block block = getBlock();
if (block.getType() == Material.DROPPER) {
CraftWorld world = (CraftWorld) this.getWorld();
BlockDropper drop = (BlockDropper) Blocks.DROPPER;
drop.dispense(world.getHandle(), new BlockPosition(getX(), getY(), getZ()));
}
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
dropper.update();
}
return result;
}
@Override
public TileEntityDropper getTileEntity() {
return dropper;
}
}

Datei anzeigen

@ -1,43 +1,28 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityEnchantTable;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.block.EnchantingTable;
public class CraftEnchantingTable extends CraftBlockState implements EnchantingTable {
private final CraftWorld world;
private final TileEntityEnchantTable enchant;
public class CraftEnchantingTable extends CraftBlockEntityState<TileEntityEnchantTable> implements EnchantingTable {
public CraftEnchantingTable(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
enchant = (TileEntityEnchantTable) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityEnchantTable.class);
}
public CraftEnchantingTable(final Material material, final TileEntityEnchantTable te) {
super(material);
enchant = te;
world = null;
}
@Override
public TileEntity getTileEntity() {
return enchant;
super(material, te);
}
@Override
public String getCustomName() {
TileEntityEnchantTable enchant = this.getSnapshot();
return enchant.hasCustomName() ? enchant.getName() : null;
}
@Override
public void setCustomName(String name) {
enchant.setCustomName(name);
this.getSnapshot().setCustomName(name);
}
}

Datei anzeigen

@ -6,66 +6,41 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.EndGateway;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftEndGateway extends CraftBlockState implements EndGateway {
private final CraftWorld world;
private final TileEntityEndGateway gateway;
public class CraftEndGateway extends CraftBlockEntityState<TileEntityEndGateway> implements EndGateway {
public CraftEndGateway(Block block) {
super(block);
world = (CraftWorld) block.getWorld();
gateway = (TileEntityEndGateway) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityEndGateway.class);
}
public CraftEndGateway(final Material material, TileEntityEndGateway te) {
super(material);
world = null;
this.gateway = te;
super(material, te);
}
@Override
public Location getExitLocation() {
BlockPosition pos = gateway.exitPortal;
return pos == null ? null : new Location(world, pos.getX(), pos.getY(), pos.getZ());
BlockPosition pos = this.getSnapshot().exitPortal;
return pos == null ? null : new Location(this.isPlaced() ? this.getWorld() : null, pos.getX(), pos.getY(), pos.getZ());
}
@Override
public void setExitLocation(Location location) {
if (location == null) {
gateway.exitPortal = null;
} else if (location.getWorld() != world) {
this.getSnapshot().exitPortal = null;
} else if (location.getWorld() != (this.isPlaced() ? this.getWorld() : null)) {
throw new IllegalArgumentException("Cannot set exit location to different world");
} else {
gateway.exitPortal = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ());
this.getSnapshot().exitPortal = new BlockPosition(location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
}
@Override
public boolean isExactTeleport() {
return gateway.exactTeleport;
return this.getSnapshot().exactTeleport;
}
@Override
public void setExactTeleport(boolean exact) {
gateway.exactTeleport = exact;
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
gateway.update();
}
return result;
}
@Override
public TileEntityEndGateway getTileEntity() {
return gateway;
this.getSnapshot().exactTeleport = exact;
}
}

Datei anzeigen

@ -1,33 +1,17 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityEnderChest;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.EnderChest;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftEnderChest extends CraftBlockState implements EnderChest {
private final CraftWorld world;
private final TileEntityEnderChest chest;
public class CraftEnderChest extends CraftBlockEntityState<TileEntityEnderChest> implements EnderChest {
public CraftEnderChest(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
chest = (TileEntityEnderChest) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityEnderChest.class);
}
public CraftEnderChest(final Material material, final TileEntityEnderChest te) {
super(material);
chest = te;
world = null;
}
@Override
public TileEntity getTileEntity() {
return chest;
super(material, te);
}
}

Datei anzeigen

@ -1,37 +1,30 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.ItemStack;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityFlowerPot;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.FlowerPot;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.material.MaterialData;
public class CraftFlowerPot extends CraftBlockState implements FlowerPot {
public class CraftFlowerPot extends CraftBlockEntityState<TileEntityFlowerPot> implements FlowerPot {
private final TileEntityFlowerPot pot;
private MaterialData contents;
public CraftFlowerPot(Block block) {
super(block);
pot = (TileEntityFlowerPot) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
contents = (pot.getItem() == null) ? null : CraftItemStack.asBukkitCopy(pot.getContents()).getData();
super(block, TileEntityFlowerPot.class);
}
public CraftFlowerPot(Material material, TileEntityFlowerPot te) {
super(material);
pot = te;
contents = (pot.getItem() == null) ? null : CraftItemStack.asBukkitCopy(pot.getContents()).getData();
super(material, te);
}
@Override
public TileEntity getTileEntity() {
return pot;
public void load(TileEntityFlowerPot pot) {
super.load(pot);
contents = (pot.getItem() == null) ? null : CraftItemStack.asBukkitCopy(pot.getContents()).getData();
}
@Override
@ -45,14 +38,9 @@ public class CraftFlowerPot extends CraftBlockState implements FlowerPot {
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
public void applyTo(TileEntityFlowerPot pot) {
super.applyTo(pot);
if (result) {
pot.setContents(contents == null ? ItemStack.a : CraftItemStack.asNMSCopy(contents.toItemStack(1)));
pot.update();
}
return result;
}
}

Datei anzeigen

@ -4,67 +4,61 @@ import net.minecraft.server.TileEntityFurnace;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Furnace;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventoryFurnace;
import org.bukkit.inventory.FurnaceInventory;
public class CraftFurnace extends CraftContainer implements Furnace {
private final TileEntityFurnace furnace;
public class CraftFurnace extends CraftContainer<TileEntityFurnace> implements Furnace {
public CraftFurnace(final Block block) {
super(block);
furnace = (TileEntityFurnace) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityFurnace.class);
}
public CraftFurnace(final Material material, final TileEntityFurnace te) {
super(material, te);
furnace = te;
}
public FurnaceInventory getInventory() {
return new CraftInventoryFurnace(furnace);
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
furnace.update();
public FurnaceInventory getSnapshotInventory() {
return new CraftInventoryFurnace(this.getSnapshot());
}
return result;
@Override
public FurnaceInventory getInventory() {
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventoryFurnace(this.getTileEntity());
}
@Override
public short getBurnTime() {
return (short) furnace.getProperty(0);
return (short) this.getSnapshot().getProperty(0);
}
@Override
public void setBurnTime(short burnTime) {
furnace.setProperty(0, burnTime);
this.getSnapshot().setProperty(0, burnTime);
}
@Override
public short getCookTime() {
return (short) furnace.getProperty(2);
return (short) this.getSnapshot().getProperty(2);
}
@Override
public void setCookTime(short cookTime) {
furnace.setProperty(2, cookTime);
this.getSnapshot().setProperty(2, cookTime);
}
@Override
public String getCustomName() {
TileEntityFurnace furnace = this.getSnapshot();
return furnace.hasCustomName() ? furnace.getName() : null;
}
@Override
public void setCustomName(String name) {
furnace.setCustomName(name);
}
@Override
public TileEntityFurnace getTileEntity() {
return furnace;
this.getSnapshot().setCustomName(name);
}
}

Datei anzeigen

@ -4,42 +4,30 @@ import net.minecraft.server.TileEntityHopper;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Hopper;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.inventory.Inventory;
public class CraftHopper extends CraftLootable implements Hopper {
private final TileEntityHopper hopper;
public class CraftHopper extends CraftLootable<TileEntityHopper> implements Hopper {
public CraftHopper(final Block block) {
super(block);
hopper = (TileEntityHopper) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityHopper.class);
}
public CraftHopper(final Material material, final TileEntityHopper te) {
super(material, te);
hopper = te;
}
@Override
public Inventory getSnapshotInventory() {
return new CraftInventory(this.getSnapshot());
}
@Override
public Inventory getInventory() {
return new CraftInventory(hopper);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result) {
hopper.update();
}
return result;
}
@Override
public TileEntityHopper getTileEntity() {
return hopper;
return new CraftInventory(this.getTileEntity());
}
}

Datei anzeigen

@ -1,7 +1,11 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.*;
import net.minecraft.server.BlockJukeBox;
import net.minecraft.server.BlockJukeBox.TileEntityRecordPlayer;
import net.minecraft.server.BlockPosition;
import net.minecraft.server.Blocks;
import net.minecraft.server.ItemStack;
import net.minecraft.server.TileEntity;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -9,26 +13,41 @@ import org.bukkit.block.Jukebox;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
public class CraftJukebox extends CraftBlockState implements Jukebox {
private final CraftWorld world;
private final TileEntityRecordPlayer jukebox;
public class CraftJukebox extends CraftBlockEntityState<TileEntityRecordPlayer> implements Jukebox {
public CraftJukebox(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
jukebox = (TileEntityRecordPlayer) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityRecordPlayer.class);
}
public CraftJukebox(final Material material, TileEntityRecordPlayer te) {
super(material);
world = null;
jukebox = te;
super(material, te);
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
if (result && this.isPlaced() && this.getType() == Material.JUKEBOX) {
CraftWorld world = (CraftWorld) this.getWorld();
Material record = this.getPlaying();
if (record == Material.AIR) {
world.getHandle().setTypeAndData(new BlockPosition(this.getX(), this.getY(), this.getZ()),
Blocks.JUKEBOX.getBlockData()
.set(BlockJukeBox.HAS_RECORD, false), 3);
} else {
world.getHandle().setTypeAndData(new BlockPosition(this.getX(), this.getY(), this.getZ()),
Blocks.JUKEBOX.getBlockData()
.set(BlockJukeBox.HAS_RECORD, true), 3);
}
world.playEffect(this.getLocation(), Effect.RECORD_PLAY, record.getId());
}
return result;
}
@Override
public Material getPlaying() {
ItemStack record = jukebox.getRecord();
ItemStack record = this.getSnapshot().getRecord();
if (record.isEmpty()) {
return Material.AIR;
}
@ -41,38 +60,29 @@ public class CraftJukebox extends CraftBlockState implements Jukebox {
record = Material.AIR;
}
jukebox.setRecord(new ItemStack(CraftMagicNumbers.getItem(record), 1));
if (!isPlaced()) {
return;
}
jukebox.update();
this.getSnapshot().setRecord(new ItemStack(CraftMagicNumbers.getItem(record), 1));
if (record == Material.AIR) {
setRawData((byte) 0);
world.getHandle().setTypeAndData(new BlockPosition(getX(), getY(), getZ()),
Blocks.JUKEBOX.getBlockData()
.set(BlockJukeBox.HAS_RECORD, false), 3);
} else {
setRawData((byte) 1);
world.getHandle().setTypeAndData(new BlockPosition(getX(), getY(), getZ()),
Blocks.JUKEBOX.getBlockData()
.set(BlockJukeBox.HAS_RECORD, true), 3);
}
world.playEffect(getLocation(), Effect.RECORD_PLAY, record.getId());
}
@Override
public boolean isPlaying() {
return getRawData() == 1;
}
@Override
public boolean eject() {
requirePlaced();
boolean result = isPlaying();
TileEntity tileEntity = this.getTileEntityFromWorld();
if (!(tileEntity instanceof TileEntityRecordPlayer)) return false;
TileEntityRecordPlayer jukebox = (TileEntityRecordPlayer) tileEntity;
boolean result = !jukebox.getRecord().isEmpty();
CraftWorld world = (CraftWorld) this.getWorld();
((BlockJukeBox) Blocks.JUKEBOX).dropRecord(world.getHandle(), new BlockPosition(getX(), getY(), getZ()), null);
return result;
}
@Override
public TileEntityRecordPlayer getTileEntity() {
return jukebox;
}
}

Datei anzeigen

@ -4,31 +4,25 @@ import net.minecraft.server.TileEntityLootable;
import org.bukkit.Material;
import org.bukkit.Nameable;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftLootable extends CraftContainer implements Nameable {
public abstract class CraftLootable<T extends TileEntityLootable> extends CraftContainer<T> implements Nameable {
private final TileEntityLootable te;
public CraftLootable(Block block) {
super(block);
te = (TileEntityLootable) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
public CraftLootable(Block block, Class<T> tileEntityClass) {
super(block, tileEntityClass);
}
public CraftLootable(Material material, TileEntityLootable tileEntity) {
public CraftLootable(Material material, T tileEntity) {
super(material, tileEntity);
te = tileEntity;
}
@Override
public String getCustomName() {
return te.hasCustomName() ? te.getName() : null;
T lootable = this.getSnapshot();
return lootable.hasCustomName() ? lootable.getName() : null;
}
@Override
public void setCustomName(String name) {
te.setCustomName(name);
this.getSnapshot().setCustomName(name);
}
}

Datei anzeigen

@ -11,43 +11,43 @@ import org.bukkit.block.NoteBlock;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
public class CraftNoteBlock extends CraftBlockState implements NoteBlock {
private final CraftWorld world;
private final TileEntityNote note;
public class CraftNoteBlock extends CraftBlockEntityState<TileEntityNote> implements NoteBlock {
public CraftNoteBlock(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
note = (TileEntityNote) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityNote.class);
}
public CraftNoteBlock(final Material material, final TileEntityNote te) {
super(material);
world = null;
note = te;
super(material, te);
}
@Override
public Note getNote() {
return new Note(note.note);
return new Note(this.getSnapshot().note);
}
@Override
public byte getRawNote() {
return note.note;
return this.getSnapshot().note;
}
public void setNote(Note n) {
note.note = n.getId();
@Override
public void setNote(Note note) {
this.getSnapshot().note = note.getId();
}
public void setRawNote(byte n) {
note.note = n;
@Override
public void setRawNote(byte note) {
this.getSnapshot().note = note;
}
@Override
public boolean play() {
Block block = getBlock();
if (block.getType() == Material.NOTE_BLOCK) {
TileEntityNote note = (TileEntityNote) this.getTileEntityFromWorld();
CraftWorld world = (CraftWorld) this.getWorld();
note.play(world.getHandle(), new BlockPosition(getX(), getY(), getZ()));
return true;
} else {
@ -60,6 +60,7 @@ public class CraftNoteBlock extends CraftBlockState implements NoteBlock {
Block block = getBlock();
if (block.getType() == Material.NOTE_BLOCK) {
CraftWorld world = (CraftWorld) this.getWorld();
world.getHandle().playBlockAction(new BlockPosition(getX(), getY(), getZ()), CraftMagicNumbers.getBlock(block), instrument, note);
return true;
} else {
@ -72,15 +73,11 @@ public class CraftNoteBlock extends CraftBlockState implements NoteBlock {
Block block = getBlock();
if (block.getType() == Material.NOTE_BLOCK) {
CraftWorld world = (CraftWorld) this.getWorld();
world.getHandle().playBlockAction(new BlockPosition(getX(), getY(), getZ()), CraftMagicNumbers.getBlock(block), instrument.getType(), note.getId());
return true;
} else {
return false;
}
}
@Override
public TileEntityNote getTileEntity() {
return note;
}
}

Datei anzeigen

@ -1,47 +1,43 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.BlockShulkerBox;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityShulkerBox;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.ShulkerBox;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.inventory.CraftInventory;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.inventory.Inventory;
public class CraftShulkerBox extends CraftLootable implements ShulkerBox {
private final CraftWorld world;
private final TileEntityShulkerBox box;
public class CraftShulkerBox extends CraftLootable<TileEntityShulkerBox> implements ShulkerBox {
public CraftShulkerBox(final Block block) {
super(block);
world = (CraftWorld) block.getWorld();
box = (TileEntityShulkerBox) world.getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityShulkerBox.class);
}
public CraftShulkerBox(final Material material, final TileEntityShulkerBox te) {
super(material, te);
box = te;
world = null;
}
@Override
public TileEntity getTileEntity() {
return box;
public Inventory getSnapshotInventory() {
return new CraftInventory(this.getSnapshot());
}
@Override
public Inventory getInventory() {
return new CraftInventory(box);
if (!this.isPlaced()) {
return this.getSnapshotInventory();
}
return new CraftInventory(this.getTileEntity());
}
@Override
public DyeColor getColor() {
return DyeColor.getByWoolData((byte) ((BlockShulkerBox) box.getBlock()).color.getColorIndex());
net.minecraft.server.Block block = CraftMagicNumbers.getBlock(this.getType());
return DyeColor.getByWoolData((byte) ((BlockShulkerBox) block).color.getColorIndex());
}
}

Datei anzeigen

@ -6,52 +6,49 @@ import net.minecraft.server.TileEntitySign;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftChatMessage;
public class CraftSign extends CraftBlockState implements Sign {
private final TileEntitySign sign;
private final String[] lines;
public class CraftSign extends CraftBlockEntityState<TileEntitySign> implements Sign {
private String[] lines;
public CraftSign(final Block block) {
super(block);
CraftWorld world = (CraftWorld) block.getWorld();
sign = (TileEntitySign) world.getTileEntityAt(getX(), getY(), getZ());
lines = new String[sign.lines.length];
System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length);
super(block, TileEntitySign.class);
}
public CraftSign(final Material material, final TileEntitySign te) {
super(material);
sign = te;
super(material, te);
}
@Override
public void load(TileEntitySign sign) {
super.load(sign);
lines = new String[sign.lines.length];
System.arraycopy(revertComponents(sign.lines), 0, lines, 0, lines.length);
}
@Override
public String[] getLines() {
return lines;
}
@Override
public String getLine(int index) throws IndexOutOfBoundsException {
return lines[index];
}
@Override
public void setLine(int index, String line) throws IndexOutOfBoundsException {
lines[index] = line;
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
public void applyTo(TileEntitySign sign) {
super.applyTo(sign);
if (result) {
IChatBaseComponent[] newLines = sanitizeLines(lines);
System.arraycopy(newLines, 0, sign.lines, 0, 4);
sign.update();
}
return result;
}
public static IChatBaseComponent[] sanitizeLines(String[] lines) {
@ -79,9 +76,4 @@ public class CraftSign extends CraftBlockState implements Sign {
private static String revertComponent(IChatBaseComponent component) {
return CraftChatMessage.fromComponent(component);
}
@Override
public TileEntitySign getTileEntity() {
return sign;
}
}

Datei anzeigen

@ -12,28 +12,26 @@ import org.bukkit.SkullType;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Skull;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftSkull extends CraftBlockState implements Skull {
public class CraftSkull extends CraftBlockEntityState<TileEntitySkull> implements Skull {
private static final int MAX_OWNER_LENGTH = 16;
private final TileEntitySkull skull;
private GameProfile profile;
private SkullType skullType;
private byte rotation;
public CraftSkull(final Block block) {
super(block);
CraftWorld world = (CraftWorld) block.getWorld();
skull = (TileEntitySkull) world.getTileEntityAt(getX(), getY(), getZ());
profile = skull.getGameProfile();
skullType = getSkullType(skull.getSkullType());
rotation = (byte) skull.rotation;
super(block, TileEntitySkull.class);
}
public CraftSkull(final Material material, final TileEntitySkull te) {
super(material);
skull = te;
super(material, te);
}
@Override
public void load(TileEntitySkull skull) {
super.load(skull);
profile = skull.getGameProfile();
skullType = getSkullType(skull.getSkullType());
rotation = (byte) skull.rotation;
@ -153,14 +151,17 @@ public class CraftSkull extends CraftBlockState implements Skull {
}
}
@Override
public boolean hasOwner() {
return profile != null;
}
@Override
public String getOwner() {
return hasOwner() ? profile.getName() : null;
}
@Override
public boolean setOwner(String name) {
if (name == null || name.length() > MAX_OWNER_LENGTH) {
return false;
@ -205,18 +206,22 @@ public class CraftSkull extends CraftBlockState implements Skull {
this.profile = new GameProfile(player.getUniqueId(), player.getName());
}
@Override
public BlockFace getRotation() {
return getBlockFace(rotation);
}
@Override
public void setRotation(BlockFace rotation) {
this.rotation = getBlockFace(rotation);
}
@Override
public SkullType getSkullType() {
return skullType;
}
@Override
public void setSkullType(SkullType skullType) {
this.skullType = skullType;
@ -226,10 +231,9 @@ public class CraftSkull extends CraftBlockState implements Skull {
}
@Override
public boolean update(boolean force, boolean applyPhysics) {
boolean result = super.update(force, applyPhysics);
public void applyTo(TileEntitySkull skull) {
super.applyTo(skull);
if (result) {
if (skullType == SkullType.PLAYER) {
skull.setGameProfile(profile);
} else {
@ -237,14 +241,5 @@ public class CraftSkull extends CraftBlockState implements Skull {
}
skull.setRotation(rotation);
skull.update();
}
return result;
}
@Override
public TileEntitySkull getTileEntity() {
return skull;
}
}

Datei anzeigen

@ -1,29 +1,16 @@
package org.bukkit.craftbukkit.block;
import net.minecraft.server.TileEntity;
import net.minecraft.server.TileEntityStructure;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.CraftWorld;
public class CraftStructureBlock extends CraftBlockState {
private final TileEntityStructure structure;
public class CraftStructureBlock extends CraftBlockEntityState<TileEntityStructure> {
public CraftStructureBlock(Block block) {
super(block);
this.structure = (TileEntityStructure) ((CraftWorld) block.getWorld()).getTileEntityAt(getX(), getY(), getZ());
super(block, TileEntityStructure.class);
}
public CraftStructureBlock(Material material, TileEntityStructure structure) {
super(material);
this.structure = structure;
}
@Override
public TileEntity getTileEntity() {
return structure;
super(material, structure);
}
}

Datei anzeigen

@ -34,7 +34,7 @@ import org.bukkit.block.BlockState;
import org.bukkit.configuration.serialization.DelegateDeserialization;
import org.bukkit.craftbukkit.block.CraftBanner;
import org.bukkit.craftbukkit.block.CraftBeacon;
import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.CraftBlockEntityState;
import org.bukkit.craftbukkit.block.CraftBrewingStand;
import org.bukkit.craftbukkit.block.CraftChest;
import org.bukkit.craftbukkit.block.CraftCommandBlock;
@ -384,7 +384,6 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
}
return new CraftComparator(material, (TileEntityComparator) te);
case PISTON_BASE:
default:
throw new IllegalStateException("Missing blockState for " + material);
}
@ -393,70 +392,68 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
@Override
public void setBlockState(BlockState blockState) {
Validate.notNull(blockState, "blockState must not be null");
TileEntity te = ((CraftBlockState) blockState).getTileEntity();
Validate.notNull(te, "Invalid tile for " + blockState);
boolean valid;
switch (material) {
case SIGN:
case SIGN_POST:
case WALL_SIGN:
valid = te instanceof TileEntitySign;
valid = blockState instanceof CraftSign;
break;
case CHEST:
case TRAPPED_CHEST:
valid = te instanceof TileEntityChest;
valid = blockState instanceof CraftChest;
break;
case BURNING_FURNACE:
case FURNACE:
valid = te instanceof TileEntityFurnace;
valid = blockState instanceof CraftFurnace;
break;
case DISPENSER:
valid = te instanceof TileEntityDispenser;
valid = blockState instanceof CraftDispenser;
break;
case DROPPER:
valid = te instanceof TileEntityDropper;
valid = blockState instanceof CraftDropper;
break;
case END_GATEWAY:
valid = te instanceof TileEntityEndGateway;
valid = blockState instanceof CraftEndGateway;
break;
case HOPPER:
valid = te instanceof TileEntityHopper;
valid = blockState instanceof CraftHopper;
break;
case MOB_SPAWNER:
valid = te instanceof TileEntityMobSpawner;
valid = blockState instanceof CraftCreatureSpawner;
break;
case NOTE_BLOCK:
valid = te instanceof TileEntityNote;
valid = blockState instanceof CraftNoteBlock;
break;
case JUKEBOX:
valid = te instanceof BlockJukeBox.TileEntityRecordPlayer;
valid = blockState instanceof CraftJukebox;
break;
case BREWING_STAND_ITEM:
valid = te instanceof TileEntityBrewingStand;
valid = blockState instanceof CraftBrewingStand;
break;
case SKULL:
valid = te instanceof TileEntitySkull;
valid = blockState instanceof CraftSkull;
break;
case COMMAND:
case COMMAND_REPEATING:
case COMMAND_CHAIN:
valid = te instanceof TileEntityCommand;
valid = blockState instanceof CraftCommandBlock;
break;
case BEACON:
valid = te instanceof TileEntityBeacon;
valid = blockState instanceof CraftBeacon;
break;
case SHIELD:
case BANNER:
case WALL_BANNER:
case STANDING_BANNER:
valid = te instanceof TileEntityBanner;
valid = blockState instanceof CraftBanner;
break;
case FLOWER_POT_ITEM:
valid = te instanceof TileEntityFlowerPot;
valid = blockState instanceof CraftFlowerPot;
break;
case STRUCTURE_BLOCK:
valid = te instanceof TileEntityStructure;
valid = blockState instanceof CraftStructureBlock;
break;
case WHITE_SHULKER_BOX:
case ORANGE_SHULKER_BOX:
@ -474,20 +471,20 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
case GREEN_SHULKER_BOX:
case RED_SHULKER_BOX:
case BLACK_SHULKER_BOX:
valid = te instanceof TileEntityShulkerBox;
valid = blockState instanceof CraftShulkerBox;
break;
case ENCHANTMENT_TABLE:
valid = te instanceof TileEntityEnchantTable;
valid = blockState instanceof CraftEnchantingTable;
break;
case ENDER_CHEST:
valid = te instanceof TileEntityEnderChest;
valid = blockState instanceof CraftEnderChest;
break;
case DAYLIGHT_DETECTOR:
case DAYLIGHT_DETECTOR_INVERTED:
valid = te instanceof TileEntityLightDetector;
valid = blockState instanceof CraftDaylightDetector;
break;
case REDSTONE_COMPARATOR:
valid = te instanceof TileEntityComparator;
valid = blockState instanceof CraftComparator;
break;
default:
valid = false;
@ -496,7 +493,6 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
Validate.isTrue(valid, "Invalid blockState for " + material);
blockEntityTag = new NBTTagCompound();
te.save(blockEntityTag);
blockEntityTag = ((CraftBlockEntityState) blockState).getSnapshotNBT();
}
}