Files
Purpur/patches/server/0131-Tuinity-Piston-pushable-TileEntities.patch
William Blake Galbreath fdf64880d1 Add PrepareGrindstoneEvent
2020-06-18 23:31:20 -05:00

715 lines
35 KiB
Diff

From 5a033005a5db9a2fa0d3c1dbff281d56469988ae Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Sun, 14 Jun 2020 00:34:47 -0700
Subject: [PATCH] Tuinity - Piston pushable TileEntities
---
.../java/net/minecraft/server/BlockChest.java | 2 +-
.../net/minecraft/server/BlockPiston.java | 30 ++++++++-
.../minecraft/server/BlockPistonMoving.java | 7 ++-
src/main/java/net/minecraft/server/Chunk.java | 11 ++++
.../java/net/minecraft/server/MCUtil.java | 14 +++++
.../java/net/minecraft/server/TileEntity.java | 49 ++++++++++++++-
.../minecraft/server/TileEntityBeacon.java | 20 +++++-
.../minecraft/server/TileEntityBeehive.java | 7 +++
.../server/TileEntityBrewingStand.java | 21 ++++++-
.../net/minecraft/server/TileEntityChest.java | 16 +++++
.../minecraft/server/TileEntityConduit.java | 21 ++++++-
.../minecraft/server/TileEntityFurnace.java | 26 ++++++--
.../minecraft/server/TileEntityJukeBox.java | 7 +++
.../minecraft/server/TileEntityLectern.java | 23 ++++++-
.../minecraft/server/TileEntityPiston.java | 63 +++++++++++++++++--
src/main/java/net/minecraft/server/World.java | 13 +++-
.../java/net/pl3x/purpur/PurpurConfig.java | 5 ++
17 files changed, 308 insertions(+), 27 deletions(-)
diff --git a/src/main/java/net/minecraft/server/BlockChest.java b/src/main/java/net/minecraft/server/BlockChest.java
index 72fb92f7c3..e9d1847fd5 100644
--- a/src/main/java/net/minecraft/server/BlockChest.java
+++ b/src/main/java/net/minecraft/server/BlockChest.java
@@ -10,7 +10,7 @@ import javax.annotation.Nullable;
public class BlockChest extends BlockChestAbstract<TileEntityChest> implements IBlockWaterlogged {
public static final BlockStateDirection FACING = BlockFacingHorizontal.FACING;
- public static final BlockStateEnum<BlockPropertyChestType> c = BlockProperties.ay;
+ public static final BlockStateEnum<BlockPropertyChestType> c = BlockProperties.ay; public static final BlockStateEnum<BlockPropertyChestType> getChestTypeEnum() { return BlockChest.c; } // Purpur - OBFHELPER
public static final BlockStateBoolean d = BlockProperties.C;
protected static final VoxelShape e = Block.a(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D);
protected static final VoxelShape f = Block.a(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D);
diff --git a/src/main/java/net/minecraft/server/BlockPiston.java b/src/main/java/net/minecraft/server/BlockPiston.java
index 0b7bed5e92..33b25d599e 100644
--- a/src/main/java/net/minecraft/server/BlockPiston.java
+++ b/src/main/java/net/minecraft/server/BlockPiston.java
@@ -280,7 +280,10 @@ public class BlockPiston extends BlockDirectional {
return false;
}
- return !block.isTileEntity();
+ // Purpur start - pushable TE's
+ TileEntity tileEntity = world.getTileEntity(blockposition);
+ return !block.isTileEntity() || (tileEntity != null && tileEntity.isPushable());
+ // Purpur end - pushable TE's
} else {
return false;
}
@@ -392,8 +395,29 @@ public class BlockPiston extends BlockDirectional {
map.remove(blockposition3);
world.setTypeAndData(blockposition3, (IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPiston.FACING, enumdirection), 68);
iblockdata1 = world.getType(oldPos); map.replace(oldPos, iblockdata1); // Purpur - fix piston physics inconsistency - move after the physics update
- world.setTileEntity(blockposition3, BlockPistonMoving.a(iblockdata1, enumdirection, flag, false)); // Paper - fix piston physics inconsistency
- world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 68); // Purpur - set air to prevent later physics updates from seeing this block
+ // Purpur start - pushable TE's
+ TileEntity tileEntity = world.getTileEntity(oldPos);
+ if (tileEntity != null) {
+ if (!tileEntity.isPushable()) {
+ tileEntity = null;
+ } else {
+ // ensure the death of world tied state
+ if (tileEntity instanceof IInventory) {
+ MCUtil.closeInventory((IInventory)tileEntity, org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE);
+ }
+ if (tileEntity instanceof TileEntityLectern) {
+ MCUtil.closeInventory(((TileEntityLectern)tileEntity).inventory, org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE);
+ }
+ // now copy
+ tileEntity = tileEntity.createCopyForPush((WorldServer)world, oldPos, blockposition3, iblockdata1);
+ }
+ }
+ // removing the old pos TE is an ugly hack to prevent containers from dropping items
+ // when they're moved.
+ world.removeTileEntity(oldPos);
+ world.setTileEntity(blockposition3, BlockPistonMoving.createPistonTile(iblockdata1, enumdirection, flag, false, tileEntity)); // Paper - fix piston physics inconsistency
+ world.setTypeAndData(oldPos, Blocks.AIR.getBlockData(), 2 | 16 | 1024); // Paper - set air to prevent later physics updates from seeing this block
+ // Purpur end - pushable TE's
--j;
aiblockdata[j] = iblockdata1;
}
diff --git a/src/main/java/net/minecraft/server/BlockPistonMoving.java b/src/main/java/net/minecraft/server/BlockPistonMoving.java
index 809ee9f9a6..93dfd0fa8d 100644
--- a/src/main/java/net/minecraft/server/BlockPistonMoving.java
+++ b/src/main/java/net/minecraft/server/BlockPistonMoving.java
@@ -21,7 +21,12 @@ public class BlockPistonMoving extends BlockTileEntity {
}
public static TileEntity a(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1) {
- return new TileEntityPiston(iblockdata, enumdirection, flag, flag1);
+ // Purpur start - add tileEntity parameter
+ return createPistonTile(iblockdata, enumdirection, flag, flag1, null);
+ }
+ public static TileEntity createPistonTile(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1, TileEntity tileEntity) {
+ return new TileEntityPiston(iblockdata, enumdirection, flag, flag1, tileEntity);
+ // Purpur end - add tileEntity parameter
}
@Override
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index d7beb47d9e..c7bedee89e 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -511,6 +511,12 @@ public class Chunk implements IChunkAccess {
@Nullable
public IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag, boolean doPlace) {
+ // Purpur start - add tileEntity parameter
+ return this.setType(blockposition, iblockdata, flag, doPlace, null);
+ }
+ @Nullable
+ public IBlockData setType(BlockPosition blockposition, IBlockData iblockdata, boolean flag, boolean doPlace, TileEntity newTileEntity) {
+ // Purpur end - add tileEntity parameter
// CraftBukkit end
int i = blockposition.getX() & 15;
int j = blockposition.getY();
@@ -569,6 +575,10 @@ public class Chunk implements IChunkAccess {
}
if (block instanceof ITileEntity) {
+ // Purpur start - add tileEntity parameter
+ if (newTileEntity != null) {
+ this.world.setTileEntity(blockposition, newTileEntity);
+ } else { // Purpur end - add tileEntity parameter
tileentity = this.a(blockposition, Chunk.EnumTileEntityState.CHECK);
if (tileentity == null) {
tileentity = ((ITileEntity) block).createTile(this.world);
@@ -576,6 +586,7 @@ public class Chunk implements IChunkAccess {
} else {
tileentity.invalidateBlockCache();
}
+ } // Purpur - add tileEntity parameter
}
this.s = true;
diff --git a/src/main/java/net/minecraft/server/MCUtil.java b/src/main/java/net/minecraft/server/MCUtil.java
index 87d5800211..6b97484031 100644
--- a/src/main/java/net/minecraft/server/MCUtil.java
+++ b/src/main/java/net/minecraft/server/MCUtil.java
@@ -48,6 +48,20 @@ public final class MCUtil {
new ThreadFactoryBuilder().setNameFormat("Paper Object Cleaner").build()
);
+ // Purpur start
+ private static org.bukkit.entity.HumanEntity[] EMPTY_HUMAN_ARRAY = new org.bukkit.entity.HumanEntity[0];
+ public static void closeInventory(IInventory inventory, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ List<org.bukkit.entity.HumanEntity> viewers = inventory.getViewers();
+ if (viewers.isEmpty()) {
+ return;
+ }
+
+ for (org.bukkit.entity.HumanEntity viewer : viewers.toArray(EMPTY_HUMAN_ARRAY)) {
+ viewer.closeInventory(reason);
+ }
+ }
+ // Purpur end
+
public static final long INVALID_CHUNK_KEY = getCoordinateKey(Integer.MAX_VALUE, Integer.MAX_VALUE);
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
index a8e64dfdab..3cd3ba1175 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -12,7 +12,7 @@ import org.bukkit.inventory.InventoryHolder;
import co.aikar.timings.MinecraftTimings; // Paper
import co.aikar.timings.Timing; // Paper
-public abstract class TileEntity implements KeyedObject { // Paper
+public abstract class TileEntity implements KeyedObject, Cloneable { // Purpur // Paper
public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper
// CraftBukkit start - data containers
@@ -27,7 +27,7 @@ public abstract class TileEntity implements KeyedObject { // Paper
protected BlockPosition position;
protected boolean f;
@Nullable
- private IBlockData c;
+ private IBlockData c;protected final IBlockData getBlockDataCache() { return this.c; } public final void setBlockDataCache(final IBlockData value) { this.c = value; } // Purpur - OBFHELPER
private boolean g;
public TileEntity(TileEntityTypes<?> tileentitytypes) {
@@ -35,6 +35,51 @@ public abstract class TileEntity implements KeyedObject { // Paper
this.tileType = tileentitytypes;
}
+ // Purpur start - pushable TE's
+ public boolean isPushable() {
+ if (!net.pl3x.purpur.PurpurConfig.pistonsCanPushTileEntities) {
+ return false;
+ }
+ IBlockData block = this.getBlock();
+ if (this.isRemoved() || !this.tileType.isValidBlock(block.getBlock())) {
+ return false;
+ }
+ EnumPistonReaction reaction = block.getPushReaction();
+ return reaction == EnumPistonReaction.NORMAL || reaction == EnumPistonReaction.PUSH_ONLY;
+ }
+
+ @Override
+ protected final TileEntity clone() {
+ try {
+ return (TileEntity)super.clone();
+ } catch (final Throwable thr) {
+ if (thr instanceof ThreadDeath) {
+ throw (ThreadDeath)thr;
+ }
+ throw new InternalError(thr);
+ }
+ }
+
+ // this method presumes the old TE has been completely dropped from worldstate and has no ties to it anymore (this
+ // includes players interacting with them)
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ final TileEntity copy = this.clone();
+
+ copy.world = world;
+ copy.position = newPos;
+
+ // removed is manually set to false after placing the entity into the world.
+ copy.setBlockDataCache(blockData);
+
+ return copy;
+ }
+
+ // updates TE state to its new position
+ public void onPostPush() {
+ this.update();
+ }
+ // Purpur end - pushable TE's
+
// Paper start
private String tileEntityKeyString = null;
private MinecraftKey tileEntityKey = null;
diff --git a/src/main/java/net/minecraft/server/TileEntityBeacon.java b/src/main/java/net/minecraft/server/TileEntityBeacon.java
index df2d6c3b07..333a40d4fa 100644
--- a/src/main/java/net/minecraft/server/TileEntityBeacon.java
+++ b/src/main/java/net/minecraft/server/TileEntityBeacon.java
@@ -35,7 +35,7 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic
@Nullable
public IChatBaseComponent customName;
public ChestLock chestLock;
- private final IContainerProperties containerProperties;
+ private IContainerProperties containerProperties; // Purpur - need non-final for `createCopyForPush`
// CraftBukkit start - add fields and methods
public PotionEffect getPrimaryEffect() {
return (this.primaryEffect != null) ? CraftPotionUtil.toBukkit(new MobEffect(this.primaryEffect, getLevel(), getAmplification(), true, true)) : null;
@@ -49,8 +49,12 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic
public TileEntityBeacon() {
super(TileEntityTypes.BEACON);
this.chestLock = ChestLock.a;
- this.containerProperties = new IContainerProperties() {
- @Override
+ // Purpur start - pushable TE's
+ this.containerProperties = this.getNewContainerProperties();
+ }
+ protected final IContainerProperties getNewContainerProperties() {
+ return new IContainerProperties() {
+ // Purpur end - pushable TE's
public int getProperty(int i) {
switch (i) {
case 0:
@@ -90,6 +94,16 @@ public class TileEntityBeacon extends TileEntity implements ITileInventory, ITic
};
}
+ // Purpur start - pushable TE's
+ @Override
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ TileEntityBeacon copy = (TileEntityBeacon)super.createCopyForPush(world, oldPos, newPos, blockData);
+ copy.containerProperties = copy.getNewContainerProperties(); // old properties retains reference to old te
+
+ return copy;
+ }
+ // Purpur end - pushable TE's
+
@Override
public void tick() {
int i = this.position.getX();
diff --git a/src/main/java/net/minecraft/server/TileEntityBeehive.java b/src/main/java/net/minecraft/server/TileEntityBeehive.java
index 417152d16c..b8e7e82ab3 100644
--- a/src/main/java/net/minecraft/server/TileEntityBeehive.java
+++ b/src/main/java/net/minecraft/server/TileEntityBeehive.java
@@ -12,6 +12,13 @@ public class TileEntityBeehive extends TileEntity implements ITickable {
public BlockPosition flowerPos = null;
public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold
+ // Purpur start - pushable TE's
+ @Override
+ public boolean isPushable() {
+ return false; // TODO until there is a good solution to making the already existing bees in the world re-acquire this position, this cannot be done.
+ }
+ // Purpur end - pushable TE's
+
public TileEntityBeehive() {
super(TileEntityTypes.BEEHIVE);
}
diff --git a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
index 441157cf7f..3a5b7a7151 100644
--- a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
+++ b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
@@ -24,7 +24,7 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
private boolean[] j;
private Item k;
public int fuelLevel;
- protected final IContainerProperties a;
+ protected IContainerProperties a; protected final void setContainerProperties(IContainerProperties value) { this.a = value; } // Purpur - OBFHELPER // Purpur - need non-final for `createCopyForPush`
// CraftBukkit start - add fields and methods
private int lastTick = MinecraftServer.currentTick;
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
@@ -59,7 +59,13 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
public TileEntityBrewingStand() {
super(TileEntityTypes.BREWING_STAND);
this.items = NonNullList.a(5, ItemStack.a);
- this.a = new IContainerProperties() {
+ // Purpur start - pushable TE's
+ this.a = this.getNewContainerProperties();
+ }
+ protected final IContainerProperties getNewContainerProperties() {
+ // moved from constructor - this should be re-copied if it changes
+ return new IContainerProperties() {
+ // Purpur end - pushable TE's
@Override
public int getProperty(int i) {
switch (i) {
@@ -91,6 +97,17 @@ public class TileEntityBrewingStand extends TileEntityContainer implements IWorl
};
}
+ // Purpur start - pushable TE's
+ @Override
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ TileEntityBrewingStand copy = (TileEntityBrewingStand)super.createCopyForPush(world, oldPos, newPos, blockData);
+
+ copy.setContainerProperties(copy.getNewContainerProperties()); // old properties retains reference to old te
+
+ return copy;
+ }
+ // Purpur end - pushable TE's
+
@Override
protected IChatBaseComponent getContainerName() {
return new ChatMessage("container.brewing", new Object[0]);
diff --git a/src/main/java/net/minecraft/server/TileEntityChest.java b/src/main/java/net/minecraft/server/TileEntityChest.java
index 9a5f2da8c0..f33f33bad9 100644
--- a/src/main/java/net/minecraft/server/TileEntityChest.java
+++ b/src/main/java/net/minecraft/server/TileEntityChest.java
@@ -45,6 +45,22 @@ public class TileEntityChest extends TileEntityLootable { // Paper - Remove ITic
}
// CraftBukkit end
+ // Purpur start
+ @Override
+ public boolean isPushable() {
+ if (!super.isPushable()) {
+ return false;
+ }
+ // what should happen when a double chest is moved is generally just a mess to deal with in the current
+ // codebase. TODO try and figure it out
+ IBlockData type = this.getBlock();
+ if (type.getBlock() == Blocks.CHEST || type.getBlock() == Blocks.TRAPPED_CHEST) {
+ return type.get(BlockChest.getChestTypeEnum()) == BlockPropertyChestType.SINGLE;
+ }
+ return false;
+ }
+ // Purpur end
+
protected TileEntityChest(TileEntityTypes<?> tileentitytypes) {
super(tileentitytypes);
this.items = NonNullList.a(27, ItemStack.a);
diff --git a/src/main/java/net/minecraft/server/TileEntityConduit.java b/src/main/java/net/minecraft/server/TileEntityConduit.java
index 07f265b299..44ea73a7c6 100644
--- a/src/main/java/net/minecraft/server/TileEntityConduit.java
+++ b/src/main/java/net/minecraft/server/TileEntityConduit.java
@@ -16,15 +16,32 @@ public class TileEntityConduit extends TileEntity implements ITickable {
private static final Block[] b = new Block[]{Blocks.PRISMARINE, Blocks.PRISMARINE_BRICKS, Blocks.SEA_LANTERN, Blocks.DARK_PRISMARINE};
public int a;
private float c;
- private boolean g;
+ private boolean g; private final void setActive(boolean value) { this.g = value; } // Purpur - OBFHELPER
private boolean h;
- private final List<BlockPosition> i;
+ private final List<BlockPosition> i; private final List<BlockPosition> getPositionsActivating() { return this.i; } // Purpur - OBFHELPER
@Nullable
private EntityLiving target;
@Nullable
private UUID k;
private long l;
+ // Purpur start - make TE's pushable
+ @Override
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ final TileEntityConduit copy = (TileEntityConduit)super.createCopyForPush(world, oldPos, newPos, blockData);
+
+ // the following states need to be re-calculated
+ copy.getPositionsActivating().clear();
+ copy.setActive(false);
+ copy.target = null;
+ // also set our state because the copy and this share the same activating block list
+ this.setActive(false);
+ this.target = null;
+
+ return copy;
+ }
+ // Purpur end - make TE's pushable
+
public TileEntityConduit() {
this(TileEntityTypes.CONDUIT);
}
diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java
index 91ef7ac60f..3ad5041cab 100644
--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java
+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java
@@ -30,14 +30,23 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API
public int cookTime;
public int cookTimeTotal;
- protected final IContainerProperties b;
+ protected IContainerProperties b; protected final void setContainerProperties(IContainerProperties value) { this.b = value; } // Purpur - OBFHELPER // Purpur - need non-final for `createCopyForPush`
private final Map<MinecraftKey, Integer> n;
protected final Recipes<? extends RecipeCooking> c;
protected TileEntityFurnace(TileEntityTypes<?> tileentitytypes, Recipes<? extends RecipeCooking> recipes) {
super(tileentitytypes);
this.items = NonNullList.a(3, ItemStack.a);
- this.b = new IContainerProperties() {
+ this.b = this.getNewContainerProperties(); // Purpur - pushable TE's
+ this.n = Maps.newHashMap();
+ this.c = recipes;
+ }
+
+ // Purpur start - pushable TE's
+ protected final IContainerProperties getNewContainerProperties() {
+ // moved from constructor - this should be re-copied if it changes
+ return new IContainerProperties() {
+ // Purpur end - pushable TE's
@Override
public int getProperty(int i) {
switch (i) {
@@ -77,10 +86,19 @@ public abstract class TileEntityFurnace extends TileEntityContainer implements I
return 4;
}
};
- this.n = Maps.newHashMap();
- this.c = recipes;
}
+ // Purpur start - pushable TE's
+ @Override
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ TileEntityFurnace copy = (TileEntityFurnace)super.createCopyForPush(world, oldPos, newPos, blockData);
+
+ copy.setContainerProperties(copy.getNewContainerProperties()); // old properties retains reference to old te
+
+ return copy;
+ }
+ // Purpur end - pushable TE's
+
public static Map<Item, Integer> f() {
Map<Item, Integer> map = Maps.newLinkedHashMap();
diff --git a/src/main/java/net/minecraft/server/TileEntityJukeBox.java b/src/main/java/net/minecraft/server/TileEntityJukeBox.java
index d66d9ff188..284eb8d000 100644
--- a/src/main/java/net/minecraft/server/TileEntityJukeBox.java
+++ b/src/main/java/net/minecraft/server/TileEntityJukeBox.java
@@ -4,6 +4,13 @@ public class TileEntityJukeBox extends TileEntity implements Clearable {
private ItemStack a;
+ // Purpur start - pushable TE's
+ @Override
+ public boolean isPushable() {
+ return false; // disabled due to buggy sound
+ }
+ // Purpur end - pushable TE's
+
public TileEntityJukeBox() {
super(TileEntityTypes.JUKEBOX);
this.a = ItemStack.a;
diff --git a/src/main/java/net/minecraft/server/TileEntityLectern.java b/src/main/java/net/minecraft/server/TileEntityLectern.java
index 6c2b48bdbe..dbe5faf0ed 100644
--- a/src/main/java/net/minecraft/server/TileEntityLectern.java
+++ b/src/main/java/net/minecraft/server/TileEntityLectern.java
@@ -16,7 +16,7 @@ import org.bukkit.inventory.InventoryHolder;
public class TileEntityLectern extends TileEntity implements Clearable, ITileInventory, ICommandListener { // CraftBukkit - ICommandListener
// CraftBukkit start - add fields and methods
- public final IInventory inventory = new LecternInventory();
+ public IInventory inventory = new LecternInventory(); // Purpur - need non-final for `createCopyForPush`
public class LecternInventory implements IInventory {
public List<HumanEntity> transaction = new ArrayList<>();
@@ -136,7 +136,12 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
@Override
public void clear() {}
};
- private final IContainerProperties containerProperties = new IContainerProperties() {
+ // Purpur start - pushable TE's
+ private IContainerProperties containerProperties = this.getNewContainerProperties(); // Purpur - need non-final for `createCopyForPush`
+
+ protected final IContainerProperties getNewContainerProperties() {
+ return new IContainerProperties() {
+ // Purpur end - pushable TE's
@Override
public int getProperty(int i) {
return i == 0 ? TileEntityLectern.this.page : 0;
@@ -155,6 +160,20 @@ public class TileEntityLectern extends TileEntity implements Clearable, ITileInv
return 1;
}
};
+ // Purpur start - pushable TE's
+ }
+
+ @Override
+ public TileEntity createCopyForPush(WorldServer world, BlockPosition oldPos, BlockPosition newPos, IBlockData blockData) {
+ TileEntityLectern copy = (TileEntityLectern)super.createCopyForPush(world, oldPos, newPos, blockData);
+
+ copy.inventory = copy.new LecternInventory();
+ copy.containerProperties = copy.getNewContainerProperties(); // old properties retains reference to old te
+
+ return copy;
+ }
+ // Purpur end - pushable TE's
+
private ItemStack book;
private int page;
private int maxPage;
diff --git a/src/main/java/net/minecraft/server/TileEntityPiston.java b/src/main/java/net/minecraft/server/TileEntityPiston.java
index 946522f636..93c54eb08f 100644
--- a/src/main/java/net/minecraft/server/TileEntityPiston.java
+++ b/src/main/java/net/minecraft/server/TileEntityPiston.java
@@ -5,10 +5,10 @@ import java.util.List;
public class TileEntityPiston extends TileEntity implements ITickable {
- private IBlockData a;
+ private IBlockData a; protected final IBlockData getBlockData() { return this.a; } // Purpur - OBFHELPER
private EnumDirection b;
private boolean c;
- private boolean g;
+ private boolean g; protected final boolean isSource() { return this.g; } // Purpur - OBFHELPER
private static final ThreadLocal<EnumDirection> h = ThreadLocal.withInitial(() -> {
return null;
});
@@ -16,12 +16,27 @@ public class TileEntityPiston extends TileEntity implements ITickable {
private float j;
private long k;
+ // Purpur start - pushable TE's
+ private TileEntity tileEntity;
+
+ @Override
+ public boolean isPushable() {
+ return false; // fuck no.
+ }
+ // Purpur end - pushable TE's
+
public TileEntityPiston() {
super(TileEntityTypes.PISTON);
}
public TileEntityPiston(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1) {
+ // Purpur start - add tileEntity parameter
+ this(iblockdata, enumdirection, flag, flag1, null);
+ }
+ public TileEntityPiston(IBlockData iblockdata, EnumDirection enumdirection, boolean flag, boolean flag1, TileEntity tileEntity) {
this();
+ this.tileEntity = tileEntity;
+ // Purpur end - add tileEntity parameter
this.a = iblockdata;
this.b = enumdirection;
this.c = flag;
@@ -30,7 +45,7 @@ public class TileEntityPiston extends TileEntity implements ITickable {
@Override
public NBTTagCompound b() {
- return this.save(new NBTTagCompound());
+ return this.save(new NBTTagCompound(), false); // Purpur - clients don't need the copied tile entity.
}
public boolean d() {
@@ -257,7 +272,22 @@ public class TileEntityPiston extends TileEntity implements ITickable {
iblockdata = Block.b(this.a, (GeneratorAccess) this.world, this.position);
}
- this.world.setTypeAndData(this.position, iblockdata, 3);
+ // Purpur start - pushable TE's
+ if ((iblockdata.isAir() && !this.isSource()) && !this.getBlockData().isAir()) {
+ // if the block can't exist at the location anymore, we need to fire drops for it, as
+ // setTypeAndData wont.
+
+ // careful - the previous pos is moving_piston, which wont fire drops. So we're safe from dupes.
+ // but the setAir should be before the drop.
+ this.world.setAir(this.position, false);
+ Block.dropItems(this.getBlockData(), this.world, this.position, null, null, ItemStack.NULL_ITEM);
+ } else {
+ this.world.setTypeAndData(this.position, iblockdata, 3, iblockdata.getBlock() == this.getBlockData().getBlock() ? this.tileEntity : null);
+ }
+ if (this.tileEntity != null && this.world.getType(this.position).getBlock() == this.getBlockData().getBlock()) {
+ this.tileEntity.onPostPush();
+ }
+ // Purpur end - pushable TE's
this.world.a(this.position, iblockdata.getBlock(), this.position);
}
}
@@ -282,7 +312,12 @@ public class TileEntityPiston extends TileEntity implements ITickable {
iblockdata = (IBlockData) iblockdata.set(BlockProperties.C, false);
}
- this.world.setTypeAndData(this.position, iblockdata, 67);
+ // Purpur start - pushable TE's
+ this.world.setTypeAndData(this.position, iblockdata, 67, this.tileEntity);
+ if (this.tileEntity != null && this.world.getType(this.position).getBlock() == this.getBlockData().getBlock()) {
+ this.tileEntity.onPostPush();
+ }
+ // Purpur end - pushable TE's
this.world.a(this.position, iblockdata.getBlock(), this.position);
}
}
@@ -309,16 +344,34 @@ public class TileEntityPiston extends TileEntity implements ITickable {
this.j = this.i;
this.c = nbttagcompound.getBoolean("extending");
this.g = nbttagcompound.getBoolean("source");
+ // Purpur start - pushable TE's
+ if (nbttagcompound.hasKey("Purpur.tileEntity")) {
+ NBTTagCompound compound = nbttagcompound.getCompound("Purpur.tileEntity");
+ if (!compound.isEmpty()) {
+ this.tileEntity = TileEntity.create(compound);
+ }
+ }
+ // Purpur end - pushable TE's
}
@Override
public NBTTagCompound save(NBTTagCompound nbttagcompound) {
+ // Purpur start - add saveTile param
+ return this.save(nbttagcompound, true);
+ }
+ public NBTTagCompound save(NBTTagCompound nbttagcompound, boolean saveTile) {
+ // Purpur end - add saveTile param
super.save(nbttagcompound);
nbttagcompound.set("blockState", GameProfileSerializer.a(this.a));
nbttagcompound.setInt("facing", this.b.b());
nbttagcompound.setFloat("progress", this.j);
nbttagcompound.setBoolean("extending", this.c);
nbttagcompound.setBoolean("source", this.g);
+ // Purpur start - pushable TE's
+ if (saveTile && this.tileEntity != null) {
+ nbttagcompound.set("Purpur.tileEntity", this.tileEntity.save(new NBTTagCompound()));
+ }
+ // Purpur end - pushable TE's
return nbttagcompound;
}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 41e977d1e0..1c444a6474 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -342,6 +342,15 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@Override
public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i) {
+ // Purpur start - add tileEntity parameter
+ return this.setTypeAndData(blockposition, iblockdata, i, null);
+ }
+ public boolean setTypeAndData(BlockPosition blockposition, IBlockData iblockdata, int i, TileEntity tileEntity) {
+ if (tileEntity != null) {
+ // even though we set it later in the call, some calls actually remove it / check it.
+ this.setTileEntity(blockposition, tileEntity);
+ }
+ // Purpur end - add tileEntity parameter
// CraftBukkit start - tree generation
if (this.captureTreeGeneration) {
// Paper start
@@ -374,7 +383,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
}
// CraftBukkit end
- IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0); // CraftBukkit custom NO_PLACE flag
+ IBlockData iblockdata1 = chunk.setType(blockposition, iblockdata, (i & 64) != 0, (i & 1024) == 0, tileEntity); // CraftBukkit custom NO_PLACE flag // Purpur - add tileEntity parameter
this.chunkPacketBlockController.onBlockChange(this, blockposition, iblockdata, iblockdata1, i); // Paper - Anti-Xray
if (iblockdata1 == null) {
@@ -1111,7 +1120,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
while (iterator.hasNext()) {
TileEntity tileentity1 = (TileEntity) iterator.next();
- if (tileentity1.getPosition().equals(blockposition)) {
+ if (tileentity != tileentity1 && tileentity1.getPosition().equals(blockposition)) { // Purpur - don't remove us if we double set...
tileentity1.ab_();
iterator.remove();
}
diff --git a/src/main/java/net/pl3x/purpur/PurpurConfig.java b/src/main/java/net/pl3x/purpur/PurpurConfig.java
index ab88636cad..defe880a6e 100644
--- a/src/main/java/net/pl3x/purpur/PurpurConfig.java
+++ b/src/main/java/net/pl3x/purpur/PurpurConfig.java
@@ -206,4 +206,9 @@ public class PurpurConfig {
enchantment.setMaxLevel(maxLevel);
}
}
+
+ public static boolean pistonsCanPushTileEntities = false;
+ private static void pistonsCanPushTileEntities() {
+ pistonsCanPushTileEntities = getBoolean("settings.blocks.pistons.can-push-tile-entities", pistonsCanPushTileEntities);
+ }
}
--
2.26.2