mirror of
https://github.com/PurpurMC/Purpur.git
synced 2026-02-17 16:37:43 +01:00
715 lines
35 KiB
Diff
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
|
|
|