Added PlaceEvent and MultiPlaceEvent which fires before placing a block.

Before calling "ItemStack.tryPlaceItemInWorld", a recording flag is turned on for
setBlock to capture a blocksnapshot for each block that attempts to be placed.

If 1 block is captured, a "BlockEvent.PlaceEvent" is fired to notify mods.
If 2 or more blocks are captured, a "BlockEvent.PlaceEvent" is fired first with the first block
captured followed by a "BlockEvent.MultiPlaceEvent" with all captured blocks. This extra event
is required for items that have the ability to place 2 or more blocks such as a BlockBed.

If either event is cancelled, the recorded block snapshot(s), item stacksize, and item meta will
revert back to the captured snapshot(s).
If the events are not cancelled, a notification will be sent to clients and block physics will be updated.

What this means for mods is Forge will be able to capture all player block placement automatically and fire
a PlaceEvent and/or MultiPlaceEvent.
If for whatever reason your mod does not use the standard placement methods then you will need to fire the
appropriate placement events in order to notify mods/servers.

This commit also includes a new utility class called BlockSnapshot which is serializable. This new class is used in conjunction with
both PlaceEvent and MultiPlaceEvent in order to record a snapshot of block space before it is altered. This
allows us to restore the block(s) if an event is cancelled. The class also provides the ability to restore a snapshot
to any location using the restoreToLocation method. This should be helpful to many mods that are looking to be able
to capture block data then restore it to back to any location required.
This commit is contained in:
bloodshot 2014-08-26 22:47:22 -04:00
parent 9ccf454b88
commit 37f91681d9
9 changed files with 719 additions and 72 deletions

View File

@ -116,9 +116,12 @@
}
public final void func_149697_b(World p_149697_1_, int p_149697_2_, int p_149697_3_, int p_149697_4_, int p_149697_5_, int p_149697_6_)
@@ -624,18 +652,14 @@
@@ -622,20 +650,16 @@
public void func_149690_a(World p_149690_1_, int p_149690_2_, int p_149690_3_, int p_149690_4_, int p_149690_5_, float p_149690_6_, int p_149690_7_)
{
if (!p_149690_1_.field_72995_K)
- if (!p_149690_1_.field_72995_K)
+ if (!p_149690_1_.field_72995_K && !p_149690_1_.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
{
- int j1 = this.func_149679_a(p_149690_7_, p_149690_1_.field_73012_v);
+ ArrayList<ItemStack> items = getDrops(p_149690_1_, p_149690_2_, p_149690_3_, p_149690_4_, p_149690_5_, p_149690_7_);
@ -139,9 +142,12 @@
}
}
}
@@ -645,6 +669,11 @@
@@ -643,8 +667,13 @@
protected void func_149642_a(World p_149642_1_, int p_149642_2_, int p_149642_3_, int p_149642_4_, ItemStack p_149642_5_)
{
if (!p_149642_1_.field_72995_K && p_149642_1_.func_82736_K().func_82766_b("doTileDrops"))
- if (!p_149642_1_.field_72995_K && p_149642_1_.func_82736_K().func_82766_b("doTileDrops"))
+ if (!p_149642_1_.field_72995_K && p_149642_1_.func_82736_K().func_82766_b("doTileDrops") && !p_149642_1_.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
{
+ if (captureDrops.get())
+ {

View File

@ -0,0 +1,17 @@
--- ../src-base/minecraft/net/minecraft/item/ItemLilyPad.java
+++ ../src-work/minecraft/net/minecraft/item/ItemLilyPad.java
@@ -46,7 +46,14 @@
if (p_77659_2_.func_147439_a(i, j, k).func_149688_o() == Material.field_151586_h && p_77659_2_.func_72805_g(i, j, k) == 0 && p_77659_2_.func_147437_c(i, j + 1, k))
{
+ // special case for handling block placement with water lilies
+ net.minecraftforge.common.util.BlockSnapshot blocksnapshot = net.minecraftforge.common.util.BlockSnapshot.getBlockSnapshot(p_77659_2_, i, j + 1, k);
p_77659_2_.func_147449_b(i, j + 1, k, Blocks.field_150392_bi);
+ if (net.minecraftforge.event.ForgeEventFactory.onPlayerBlockPlace(p_77659_3_, blocksnapshot, net.minecraftforge.common.util.ForgeDirection.UP).isCanceled())
+ {
+ blocksnapshot.restore(true, false);
+ return p_77659_1_;
+ }
if (!p_77659_3_.field_71075_bZ.field_75098_d)
{

View File

@ -8,7 +8,15 @@
public final class ItemStack
{
@@ -182,7 +183,7 @@
@@ -124,6 +125,7 @@
public boolean func_77943_a(EntityPlayer p_77943_1_, World p_77943_2_, int p_77943_3_, int p_77943_4_, int p_77943_5_, int p_77943_6_, float p_77943_7_, float p_77943_8_, float p_77943_9_)
{
+ if (!p_77943_2_.field_72995_K) return net.minecraftforge.common.ForgeHooks.onPlaceItemIntoWorld(this, p_77943_1_, p_77943_2_, p_77943_3_, p_77943_4_, p_77943_5_, p_77943_6_, p_77943_7_, p_77943_8_, p_77943_9_);
boolean flag = this.func_77973_b().func_77648_a(this, p_77943_1_, p_77943_2_, p_77943_3_, p_77943_4_, p_77943_5_, p_77943_6_, p_77943_7_, p_77943_8_, p_77943_9_);
if (flag)
@@ -182,7 +184,7 @@
public int func_77976_d()
{
@ -17,7 +25,7 @@
}
public boolean func_77985_e()
@@ -192,7 +193,7 @@
@@ -192,7 +194,7 @@
public boolean func_77984_f()
{
@ -26,7 +34,7 @@
}
public boolean func_77981_g()
@@ -202,32 +203,27 @@
@@ -202,32 +204,27 @@
public boolean func_77951_h()
{
@ -64,7 +72,7 @@
}
public boolean func_96631_a(int p_96631_1_, Random p_96631_2_)
@@ -259,8 +255,8 @@
@@ -259,8 +256,8 @@
}
}
@ -75,7 +83,7 @@
}
}
@@ -319,7 +315,7 @@
@@ -319,7 +316,7 @@
public boolean func_150998_b(Block p_150998_1_)
{
@ -84,7 +92,7 @@
}
public boolean func_111282_a(EntityPlayer p_111282_1_, EntityLivingBase p_111282_2_)
@@ -626,16 +622,24 @@
@@ -626,16 +623,24 @@
{
arraylist.add("Durability: " + (this.func_77958_k() - this.func_77952_i()) + " / " + this.func_77958_k());
}
@ -110,7 +118,7 @@
public EnumRarity func_77953_t()
{
return this.func_77973_b().func_77613_e(this);
@@ -737,7 +741,7 @@
@@ -737,7 +742,7 @@
}
else
{

View File

@ -103,7 +103,15 @@
{
return;
}
@@ -500,7 +532,11 @@
@@ -487,6 +519,7 @@
WorldServer worldserver = this.field_147367_d.func_71218_a(this.field_147369_b.field_71093_bK);
ItemStack itemstack = this.field_147369_b.field_71071_by.func_70448_g();
boolean flag = false;
+ boolean placeResult = true;
int i = p_147346_1_.func_149576_c();
int j = p_147346_1_.func_149571_d();
int k = p_147346_1_.func_149570_e();
@@ -500,7 +533,11 @@
return;
}
@ -116,7 +124,7 @@
}
else if (p_147346_1_.func_149571_d() >= this.field_147367_d.func_71207_Z() - 1 && (p_147346_1_.func_149568_f() == 1 || p_147346_1_.func_149571_d() >= this.field_147367_d.func_71207_Z()))
{
@@ -511,7 +547,9 @@
@@ -511,9 +548,15 @@
}
else
{
@ -125,9 +133,25 @@
+ dist *= dist;
+ if (this.field_147380_r && this.field_147369_b.func_70092_e((double)i + 0.5D, (double)j + 0.5D, (double)k + 0.5D) < dist && !this.field_147367_d.func_96290_a(worldserver, i, j, k, this.field_147369_b))
{
this.field_147369_b.field_71134_c.func_73078_a(this.field_147369_b, worldserver, itemstack, i, j, k, l, p_147346_1_.func_149573_h(), p_147346_1_.func_149569_i(), p_147346_1_.func_149575_j());
- this.field_147369_b.field_71134_c.func_73078_a(this.field_147369_b, worldserver, itemstack, i, j, k, l, p_147346_1_.func_149573_h(), p_147346_1_.func_149569_i(), p_147346_1_.func_149575_j());
+ // record block place result so we can update client itemstack size if place event was cancelled.
+ if (!this.field_147369_b.field_71134_c.func_73078_a(this.field_147369_b, worldserver, itemstack, i, j, k, l, p_147346_1_.func_149573_h(), p_147346_1_.func_149569_i(), p_147346_1_.func_149575_j()))
+ {
+ placeResult = false;
+ }
}
@@ -677,6 +715,8 @@
flag = true;
@@ -572,7 +615,7 @@
this.field_147369_b.field_71070_bA.func_75142_b();
this.field_147369_b.field_71137_h = false;
- if (!ItemStack.func_77989_b(this.field_147369_b.field_71071_by.func_70448_g(), p_147346_1_.func_149574_g()))
+ if (!ItemStack.func_77989_b(this.field_147369_b.field_71071_by.func_70448_g(), p_147346_1_.func_149574_g()) || !placeResult) // force client itemstack update if place event was cancelled
{
this.func_147359_a(new S2FPacketSetSlot(this.field_147369_b.field_71070_bA.field_75152_c, slot.field_75222_d, this.field_147369_b.field_71071_by.func_70448_g()));
}
@@ -677,6 +720,8 @@
else
{
ChatComponentTranslation chatcomponenttranslation1 = new ChatComponentTranslation("chat.type.text", new Object[] {this.field_147369_b.func_145748_c_(), s});
@ -136,7 +160,7 @@
this.field_147367_d.func_71203_ab().func_148544_a(chatcomponenttranslation1, false);
}
@@ -812,7 +852,7 @@
@@ -812,7 +857,7 @@
return;
}

View File

@ -36,7 +36,13 @@
public boolean field_72999_e;
public List field_72996_f = new ArrayList();
protected List field_72997_g = new ArrayList();
@@ -97,6 +124,11 @@
@@ -94,9 +121,17 @@
private boolean field_147481_N;
int[] field_72994_J;
private static final String __OBFID = "CL_00000140";
+ public boolean restoringBlockSnapshots = false;
+ public boolean captureBlockSnapshots = false;
+ public ArrayList<net.minecraftforge.common.util.BlockSnapshot> capturedBlockSnapshots = new ArrayList<net.minecraftforge.common.util.BlockSnapshot>();
public BiomeGenBase func_72807_a(final int p_72807_1_, final int p_72807_2_)
{
@ -48,7 +54,7 @@
if (this.func_72899_e(p_72807_1_, 0, p_72807_2_))
{
Chunk chunk = this.func_72938_d(p_72807_1_, p_72807_2_);
@@ -143,7 +175,13 @@
@@ -143,7 +178,13 @@
this.field_72984_F = p_i45368_5_;
this.field_72986_A = new WorldInfo(p_i45368_4_, p_i45368_2_);
this.field_73011_w = p_i45368_3_;
@ -63,7 +69,7 @@
VillageCollection villagecollection = (VillageCollection)this.field_72988_C.func_75742_a(VillageCollection.class, "villages");
if (villagecollection == null)
@@ -157,7 +195,10 @@
@@ -157,7 +198,10 @@
this.field_72982_D.func_82566_a(this);
}
@ -75,7 +81,7 @@
this.field_73020_y = this.func_72970_h();
this.func_72966_v();
this.func_72947_a();
@@ -172,7 +213,7 @@
@@ -172,7 +216,7 @@
this.field_72994_J = new int[32768];
this.field_73019_z = p_i45369_1_;
this.field_72984_F = p_i45369_5_;
@ -84,7 +90,7 @@
this.field_72986_A = p_i45369_1_.func_75757_d();
if (p_i45369_4_ != null)
@@ -200,6 +241,15 @@
@@ -200,6 +244,15 @@
this.field_73011_w.func_76558_a(this);
this.field_73020_y = this.func_72970_h();
@ -100,7 +106,7 @@
if (!this.field_72986_A.func_76070_v())
{
try
@@ -225,12 +275,12 @@
@@ -225,12 +278,12 @@
this.field_72986_A.func_76091_d(true);
}
@ -115,7 +121,7 @@
}
else
{
@@ -242,6 +292,20 @@
@@ -242,6 +295,20 @@
this.func_72947_a();
}
@ -136,7 +142,7 @@
protected abstract IChunkProvider func_72970_h();
protected void func_72963_a(WorldSettings p_72963_1_)
@@ -295,7 +359,8 @@
@@ -295,7 +362,8 @@
public boolean func_147437_c(int p_147437_1_, int p_147437_2_, int p_147437_3_)
{
@ -146,7 +152,82 @@
}
public boolean func_72899_e(int p_72899_1_, int p_72899_2_, int p_72899_3_)
@@ -927,7 +992,7 @@
@@ -367,33 +435,33 @@
{
Chunk chunk = this.func_72964_e(p_147465_1_ >> 4, p_147465_3_ >> 4);
Block block1 = null;
+ net.minecraftforge.common.util.BlockSnapshot blockSnapshot = null;
if ((p_147465_6_ & 1) != 0)
{
block1 = chunk.func_150810_a(p_147465_1_ & 15, p_147465_2_, p_147465_3_ & 15);
+ if (this.captureBlockSnapshots && block1 != null && !this.field_72995_K)
+ {
+ blockSnapshot = net.minecraftforge.common.util.BlockSnapshot.getBlockSnapshot(this, p_147465_1_, p_147465_2_, p_147465_3_, p_147465_6_);
+ this.capturedBlockSnapshots.add(blockSnapshot);
+ }
}
boolean flag = chunk.func_150807_a(p_147465_1_ & 15, p_147465_2_, p_147465_3_ & 15, p_147465_4_, p_147465_5_);
+
+ if (!flag && this.captureBlockSnapshots && block1 != null && !this.field_72995_K)
+ {
+ this.capturedBlockSnapshots.remove(blockSnapshot);
+ }
+
this.field_72984_F.func_76320_a("checkLight");
this.func_147451_t(p_147465_1_, p_147465_2_, p_147465_3_);
this.field_72984_F.func_76319_b();
- if (flag)
+ if (flag && !this.captureBlockSnapshots) // Don't notify clients or update physics while capturing blockstates
{
- if ((p_147465_6_ & 2) != 0 && (!this.field_72995_K || (p_147465_6_ & 4) == 0) && chunk.func_150802_k())
- {
- this.func_147471_g(p_147465_1_, p_147465_2_, p_147465_3_);
- }
-
- if (!this.field_72995_K && (p_147465_6_ & 1) != 0)
- {
- this.func_147444_c(p_147465_1_, p_147465_2_, p_147465_3_, block1);
-
- if (p_147465_4_.func_149740_M())
- {
- this.func_147453_f(p_147465_1_, p_147465_2_, p_147465_3_, p_147465_4_);
- }
- }
+ // Modularize client and physic updates
+ this.markAndNotifyBlock(p_147465_1_, p_147465_2_, p_147465_3_, chunk, block1, p_147465_4_, p_147465_6_);
}
return flag;
@@ -405,6 +473,25 @@
}
}
+ // Split off from original setBlock(int p_147465_1_, int p_147465_2_, int p_147465_3_, Block p_147465_4_, int p_147465_5_, int p_147465_6_) method in order to directly send client and physic updates
+ public void markAndNotifyBlock(int x, int y, int z, Chunk chunk, Block oldBlock, Block newBlock, int flag)
+ {
+ if ((flag & 2) != 0 && (chunk == null || chunk.func_150802_k()))
+ {
+ this.func_147471_g(x, y, z);
+ }
+
+ if (!this.field_72995_K && (flag & 1) != 0)
+ {
+ this.func_147444_c(x, y, z, oldBlock);
+
+ if (newBlock.func_149740_M())
+ {
+ this.func_147453_f(x, y, z, newBlock);
+ }
+ }
+ }
+
public int func_72805_g(int p_72805_1_, int p_72805_2_, int p_72805_3_)
{
if (p_72805_1_ >= -30000000 && p_72805_3_ >= -30000000 && p_72805_1_ < 30000000 && p_72805_3_ < 30000000)
@@ -927,7 +1014,7 @@
public boolean func_72935_r()
{
@ -155,7 +236,7 @@
}
public MovingObjectPosition func_72933_a(Vec3 p_72933_1_, Vec3 p_72933_2_)
@@ -1158,6 +1223,12 @@
@@ -1158,6 +1245,12 @@
public void func_72956_a(Entity p_72956_1_, String p_72956_2_, float p_72956_3_, float p_72956_4_)
{
@ -168,7 +249,7 @@
for (int i = 0; i < this.field_73021_x.size(); ++i)
{
((IWorldAccess)this.field_73021_x.get(i)).func_72704_a(p_72956_2_, p_72956_1_.field_70165_t, p_72956_1_.field_70163_u - (double)p_72956_1_.field_70129_M, p_72956_1_.field_70161_v, p_72956_3_, p_72956_4_);
@@ -1166,6 +1237,12 @@
@@ -1166,6 +1259,12 @@
public void func_85173_a(EntityPlayer p_85173_1_, String p_85173_2_, float p_85173_3_, float p_85173_4_)
{
@ -181,7 +262,17 @@
for (int i = 0; i < this.field_73021_x.size(); ++i)
{
((IWorldAccess)this.field_73021_x.get(i)).func_85102_a(p_85173_1_, p_85173_2_, p_85173_1_.field_70165_t, p_85173_1_.field_70163_u - (double)p_85173_1_.field_70129_M, p_85173_1_.field_70161_v, p_85173_3_, p_85173_4_);
@@ -1227,6 +1304,7 @@
@@ -1206,6 +1305,9 @@
public boolean func_72838_d(Entity p_72838_1_)
{
+ // do not drop any items while restoring blocksnapshots. Prevents dupes
+ if (!this.field_72995_K && (p_72838_1_ == null || (p_72838_1_ instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;
+
int i = MathHelper.func_76128_c(p_72838_1_.field_70165_t / 16.0D);
int j = MathHelper.func_76128_c(p_72838_1_.field_70161_v / 16.0D);
boolean flag = p_72838_1_.field_98038_p;
@@ -1227,6 +1329,7 @@
this.field_73010_i.add(entityplayer);
this.func_72854_c();
}
@ -189,7 +280,7 @@
this.func_72964_e(i, j).func_76612_a(p_72838_1_);
this.field_72996_f.add(p_72838_1_);
@@ -1398,6 +1476,20 @@
@@ -1398,6 +1501,20 @@
public int func_72967_a(float p_72967_1_)
{
@ -210,7 +301,7 @@
float f1 = this.func_72826_c(p_72967_1_);
float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F);
@@ -1414,11 +1506,9 @@
@@ -1414,11 +1531,9 @@
f2 = 1.0F - f2;
f2 = (float)((double)f2 * (1.0D - (double)(this.func_72867_j(p_72967_1_) * 5.0F) / 16.0D));
f2 = (float)((double)f2 * (1.0D - (double)(this.func_72819_i(p_72967_1_) * 5.0F) / 16.0D));
@ -223,7 +314,7 @@
public void func_72848_b(IWorldAccess p_72848_1_)
{
this.field_73021_x.remove(p_72848_1_);
@@ -1427,6 +1517,12 @@
@@ -1427,6 +1542,12 @@
@SideOnly(Side.CLIENT)
public float func_72971_b(float p_72971_1_)
{
@ -236,7 +327,7 @@
float f1 = this.func_72826_c(p_72971_1_);
float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.2F);
@@ -1449,6 +1545,12 @@
@@ -1449,6 +1570,12 @@
@SideOnly(Side.CLIENT)
public Vec3 func_72833_a(Entity p_72833_1_, float p_72833_2_)
{
@ -249,7 +340,7 @@
float f1 = this.func_72826_c(p_72833_2_);
float f2 = MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
@@ -1465,9 +1567,7 @@
@@ -1465,9 +1592,7 @@
int i = MathHelper.func_76128_c(p_72833_1_.field_70165_t);
int j = MathHelper.func_76128_c(p_72833_1_.field_70163_u);
int k = MathHelper.func_76128_c(p_72833_1_.field_70161_v);
@ -260,7 +351,7 @@
float f4 = (float)(l >> 16 & 255) / 255.0F;
float f5 = (float)(l >> 8 & 255) / 255.0F;
float f6 = (float)(l & 255) / 255.0F;
@@ -1529,6 +1629,11 @@
@@ -1529,6 +1654,11 @@
public float func_130001_d()
{
@ -272,7 +363,7 @@
return WorldProvider.field_111203_a[this.field_73011_w.func_76559_b(this.field_72986_A.func_76073_f())];
}
@@ -1541,6 +1646,12 @@
@@ -1541,6 +1671,12 @@
@SideOnly(Side.CLIENT)
public Vec3 func_72824_f(float p_72824_1_)
{
@ -285,7 +376,7 @@
float f1 = this.func_72826_c(p_72824_1_);
float f2 = MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
@@ -1602,6 +1713,8 @@
@@ -1602,6 +1738,8 @@
public int func_72825_h(int p_72825_1_, int p_72825_2_)
{
Chunk chunk = this.func_72938_d(p_72825_1_, p_72825_2_);
@ -294,7 +385,7 @@
int k = chunk.func_76625_h() + 15;
p_72825_1_ &= 15;
@@ -1609,7 +1722,7 @@
@@ -1609,7 +1747,7 @@
{
Block block = chunk.func_150810_a(p_72825_1_, k, p_72825_2_);
@ -303,7 +394,7 @@
{
return k + 1;
}
@@ -1621,7 +1734,13 @@
@@ -1621,7 +1759,13 @@
@SideOnly(Side.CLIENT)
public float func_72880_h(float p_72880_1_)
{
@ -318,7 +409,7 @@
float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.25F);
if (f2 < 0.0F)
@@ -1675,7 +1794,15 @@
@@ -1675,7 +1819,15 @@
entity.func_85029_a(crashreportcategory);
}
@ -335,7 +426,7 @@
}
if (entity.field_70128_L)
@@ -1737,7 +1864,16 @@
@@ -1737,7 +1889,16 @@
crashreport = CrashReport.func_85055_a(throwable1, "Ticking entity");
crashreportcategory = crashreport.func_85058_a("Entity being ticked");
entity.func_85029_a(crashreportcategory);
@ -353,7 +444,7 @@
}
}
@@ -1780,7 +1916,16 @@
@@ -1780,7 +1941,16 @@
crashreport = CrashReport.func_85055_a(throwable, "Ticking block entity");
crashreportcategory = crashreport.func_85058_a("Block entity being ticked");
tileentity.func_145828_a(crashreportcategory);
@ -371,7 +462,7 @@
}
}
@@ -1794,7 +1939,7 @@
@@ -1794,7 +1964,7 @@
if (chunk != null)
{
@ -380,7 +471,7 @@
}
}
}
@@ -1802,6 +1947,10 @@
@@ -1802,6 +1972,10 @@
if (!this.field_147483_b.isEmpty())
{
@ -391,7 +482,7 @@
this.field_147482_g.removeAll(this.field_147483_b);
this.field_147483_b.clear();
}
@@ -1822,18 +1971,18 @@
@@ -1822,18 +1996,18 @@
{
this.field_147482_g.add(tileentity1);
}
@ -414,7 +505,7 @@
}
}
@@ -1846,14 +1995,11 @@
@@ -1846,14 +2020,11 @@
public void func_147448_a(Collection p_147448_1_)
{
@ -432,7 +523,7 @@
}
public void func_72870_g(Entity p_72870_1_)
@@ -1865,10 +2011,19 @@
@@ -1865,10 +2036,19 @@
{
int i = MathHelper.func_76128_c(p_72866_1_.field_70165_t);
int j = MathHelper.func_76128_c(p_72866_1_.field_70161_v);
@ -454,7 +545,7 @@
p_72866_1_.field_70142_S = p_72866_1_.field_70165_t;
p_72866_1_.field_70137_T = p_72866_1_.field_70163_u;
p_72866_1_.field_70136_U = p_72866_1_.field_70161_v;
@@ -2086,6 +2241,10 @@
@@ -2086,6 +2266,10 @@
{
return true;
}
@ -465,7 +556,7 @@
}
}
}
@@ -2378,13 +2537,15 @@
@@ -2378,13 +2562,15 @@
public void func_147455_a(int p_147455_1_, int p_147455_2_, int p_147455_3_, TileEntity p_147455_4_)
{
@ -485,7 +576,7 @@
Iterator iterator = this.field_147484_a.iterator();
while (iterator.hasNext())
@@ -2403,40 +2564,22 @@
@@ -2403,40 +2589,22 @@
else
{
this.field_147482_g.add(p_147455_4_);
@ -536,7 +627,7 @@
}
public void func_147457_a(TileEntity p_147457_1_)
@@ -2453,8 +2596,7 @@
@@ -2453,8 +2621,7 @@
public static boolean func_147466_a(IBlockAccess p_147466_0_, int p_147466_1_, int p_147466_2_, int p_147466_3_)
{
Block block = p_147466_0_.func_147439_a(p_147466_1_, p_147466_2_, p_147466_3_);
@ -546,7 +637,7 @@
}
public boolean func_147445_c(int p_147445_1_, int p_147445_2_, int p_147445_3_, boolean p_147445_4_)
@@ -2466,7 +2608,7 @@
@@ -2466,7 +2633,7 @@
if (chunk != null && !chunk.func_76621_g())
{
Block block = this.func_147439_a(p_147445_1_, p_147445_2_, p_147445_3_);
@ -555,7 +646,7 @@
}
else
{
@@ -2491,8 +2633,7 @@
@@ -2491,8 +2658,7 @@
public void func_72891_a(boolean p_72891_1_, boolean p_72891_2_)
{
@ -565,7 +656,7 @@
}
public void func_72835_b()
@@ -2502,6 +2643,11 @@
@@ -2502,6 +2668,11 @@
private void func_72947_a()
{
@ -577,7 +668,7 @@
if (this.field_72986_A.func_76059_o())
{
this.field_73004_o = 1.0F;
@@ -2515,6 +2661,11 @@
@@ -2515,6 +2686,11 @@
protected void func_72979_l()
{
@ -589,7 +680,7 @@
if (!this.field_73011_w.field_76576_e)
{
if (!this.field_72995_K)
@@ -2599,6 +2750,7 @@
@@ -2599,6 +2775,7 @@
{
this.field_72993_I.clear();
this.field_72984_F.func_76320_a("buildList");
@ -597,7 +688,7 @@
int i;
EntityPlayer entityplayer;
int j;
@@ -2693,6 +2845,11 @@
@@ -2693,6 +2870,11 @@
public boolean func_72834_c(int p_72834_1_, int p_72834_2_, int p_72834_3_, boolean p_72834_4_)
{
@ -609,7 +700,7 @@
BiomeGenBase biomegenbase = this.func_72807_a(p_72834_1_, p_72834_3_);
float f = biomegenbase.func_150564_a(p_72834_1_, p_72834_2_, p_72834_3_);
@@ -2748,6 +2905,11 @@
@@ -2748,6 +2930,11 @@
public boolean func_147478_e(int p_147478_1_, int p_147478_2_, int p_147478_3_, boolean p_147478_4_)
{
@ -621,7 +712,7 @@
BiomeGenBase biomegenbase = this.func_72807_a(p_147478_1_, p_147478_3_);
float f = biomegenbase.func_150564_a(p_147478_1_, p_147478_2_, p_147478_3_);
@@ -2797,10 +2959,11 @@
@@ -2797,10 +2984,11 @@
else
{
Block block = this.func_147439_a(p_98179_1_, p_98179_2_, p_98179_3_);
@ -636,7 +727,7 @@
{
i1 = 1;
}
@@ -2900,7 +3063,7 @@
@@ -2900,7 +3088,7 @@
int j4 = i2 + Facing.field_71586_b[i4];
int k4 = j2 + Facing.field_71587_c[i4];
int l4 = k2 + Facing.field_71585_d[i4];
@ -645,7 +736,7 @@
i3 = this.func_72972_b(p_147463_1_, j4, k4, l4);
if (i3 == l2 - i5 && i1 < this.field_72994_J.length)
@@ -2998,10 +3161,10 @@
@@ -2998,10 +3186,10 @@
public List func_94576_a(Entity p_94576_1_, AxisAlignedBB p_94576_2_, IEntitySelector p_94576_3_)
{
ArrayList arraylist = new ArrayList();
@ -660,7 +751,7 @@
for (int i1 = i; i1 <= j; ++i1)
{
@@ -3024,10 +3187,10 @@
@@ -3024,10 +3212,10 @@
public List func_82733_a(Class p_82733_1_, AxisAlignedBB p_82733_2_, IEntitySelector p_82733_3_)
{
@ -675,7 +766,7 @@
ArrayList arraylist = new ArrayList();
for (int i1 = i; i1 <= j; ++i1)
@@ -3104,11 +3267,14 @@
@@ -3104,11 +3292,14 @@
public void func_72868_a(List p_72868_1_)
{
@ -693,7 +784,7 @@
}
}
@@ -3121,7 +3287,7 @@
@@ -3121,7 +3312,7 @@
{
Block block1 = this.func_147439_a(p_147472_2_, p_147472_3_, p_147472_4_);
AxisAlignedBB axisalignedbb = p_147472_5_ ? null : p_147472_1_.func_149668_a(this, p_147472_2_, p_147472_3_, p_147472_4_);
@ -702,7 +793,7 @@
}
public PathEntity func_72865_a(Entity p_72865_1_, Entity p_72865_2_, float p_72865_3_, boolean p_72865_4_, boolean p_72865_5_, boolean p_72865_6_, boolean p_72865_7_)
@@ -3226,7 +3392,8 @@
@@ -3226,7 +3417,8 @@
public int func_72878_l(int p_72878_1_, int p_72878_2_, int p_72878_3_, int p_72878_4_)
{
@ -712,7 +803,7 @@
}
public boolean func_72864_z(int p_72864_1_, int p_72864_2_, int p_72864_3_)
@@ -3374,7 +3541,7 @@
@@ -3374,7 +3566,7 @@
public long func_72905_C()
{
@ -721,7 +812,7 @@
}
public long func_82737_E()
@@ -3384,22 +3551,22 @@
@@ -3384,22 +3576,22 @@
public long func_72820_D()
{
@ -748,7 +839,7 @@
}
@SideOnly(Side.CLIENT)
@@ -3419,12 +3586,20 @@
@@ -3419,12 +3611,20 @@
if (!this.field_72996_f.contains(p_72897_1_))
{
@ -770,7 +861,7 @@
return true;
}
@@ -3514,8 +3689,7 @@
@@ -3514,8 +3714,7 @@
public boolean func_72958_C(int p_72958_1_, int p_72958_2_, int p_72958_3_)
{
@ -780,7 +871,7 @@
}
public void func_72823_a(String p_72823_1_, WorldSavedData p_72823_2_)
@@ -3569,12 +3743,12 @@
@@ -3569,12 +3768,12 @@
public int func_72800_K()
{
@ -795,7 +886,7 @@
}
public Random func_72843_D(int p_72843_1_, int p_72843_2_, int p_72843_3_)
@@ -3598,7 +3772,7 @@
@@ -3598,7 +3797,7 @@
@SideOnly(Side.CLIENT)
public double func_72919_O()
{
@ -804,7 +895,7 @@
}
public CrashReportCategory func_72914_a(CrashReport p_72914_1_)
@@ -3663,25 +3837,24 @@
@@ -3663,25 +3862,24 @@
public void func_147453_f(int p_147453_1_, int p_147453_2_, int p_147453_3_, Block p_147453_4_)
{
@ -843,7 +934,7 @@
}
}
}
@@ -3722,4 +3895,110 @@
@@ -3722,4 +3920,110 @@
iworldaccess.func_147584_b();
}
}

View File

@ -16,15 +16,19 @@ import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.ContainerRepair;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemAxe;
import net.minecraft.item.ItemBucket;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemSpade;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S23PacketBlockChange;
import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityNote;
import net.minecraft.util.AxisAlignedBB;
@ -37,6 +41,7 @@ import net.minecraft.util.WeightedRandom;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
@ -430,6 +435,100 @@ public class ForgeHooks
return event;
}
public static boolean onPlaceItemIntoWorld(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ)
{
// handle all placement events here
int meta = itemstack.getItemDamage();
int size = itemstack.stackSize;
NBTTagCompound nbt = null;
if (itemstack.getTagCompound() != null)
{
nbt = (NBTTagCompound)itemstack.getTagCompound().copy();
}
if (!(itemstack.getItem() instanceof ItemBucket)) // if not bucket
{
world.captureBlockSnapshots = true;
}
boolean flag = itemstack.getItem().onItemUse(itemstack, player, world, x, y, z, side, hitX, hitY, hitZ);
world.captureBlockSnapshots = false;
if (flag)
{
// save new item data
int newMeta = itemstack.getItemDamage();
int newSize = itemstack.stackSize;
NBTTagCompound newNBT = null;
if (itemstack.getTagCompound() != null)
{
newNBT = (NBTTagCompound)itemstack.getTagCompound().copy();
}
net.minecraftforge.event.world.BlockEvent.PlaceEvent placeEvent = null;
List<net.minecraftforge.common.util.BlockSnapshot> blockSnapshots = (List<net.minecraftforge.common.util.BlockSnapshot>) world.capturedBlockSnapshots.clone();
world.capturedBlockSnapshots.clear();
// make sure to set pre-placement item data for event
itemstack.setItemDamage(meta);
itemstack.stackSize = size;
if (nbt != null)
{
itemstack.setTagCompound(nbt);
}
if (blockSnapshots.size() > 1)
{
placeEvent = ForgeEventFactory.onPlayerMultiBlockPlace(player, blockSnapshots, net.minecraftforge.common.util.ForgeDirection.getOrientation(side));
}
else if (blockSnapshots.size() == 1)
{
placeEvent = ForgeEventFactory.onPlayerBlockPlace(player, blockSnapshots.get(0), net.minecraftforge.common.util.ForgeDirection.getOrientation(side));
}
if (placeEvent != null && (placeEvent.isCanceled()))
{
flag = false; // cancel placement
// revert back all captured blocks
for (net.minecraftforge.common.util.BlockSnapshot blocksnapshot : blockSnapshots)
{
world.restoringBlockSnapshots = true;
blocksnapshot.restore(true, false);
world.restoringBlockSnapshots = false;
}
}
else
{
// Change the stack to its new content
itemstack.setItemDamage(newMeta);
itemstack.stackSize = newSize;
if (nbt != null)
{
itemstack.setTagCompound(newNBT);
}
for (net.minecraftforge.common.util.BlockSnapshot blocksnapshot : blockSnapshots)
{
int blockX = blocksnapshot.x;
int blockY = blocksnapshot.y;
int blockZ = blocksnapshot.z;
int metadata = world.getBlockMetadata(blockX, blockY, blockZ);
int updateFlag = blocksnapshot.flag;
Block oldBlock = blocksnapshot.replacedBlock;
Block newBlock = world.getBlock(blockX, blockY, blockZ);
if (newBlock != null && !(newBlock.hasTileEntity(metadata))) // Containers get placed automatically
{
newBlock.onBlockAdded(world, blockX, blockY, blockZ);
}
world.markAndNotifyBlock(blockX, blockY, blockZ, null, oldBlock, newBlock, updateFlag);
}
player.addStat(StatList.objectUseStats[Item.getIdFromItem(itemstack.getItem())], 1);
}
}
world.capturedBlockSnapshots.clear();
return flag;
}
public static boolean onAnvilChange(ContainerRepair container, ItemStack left, ItemStack right, IInventory outputSlot, String name, int baseCost)
{
AnvilUpdateEvent e = new AnvilUpdateEvent(left, right, name, baseCost);

View File

@ -0,0 +1,312 @@
package net.minecraftforge.common.util;
import java.io.Serializable;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
/**
* Represents a captured snapshot of a block which will not change
* automatically.
* <p>
* Unlike Block, which only one object can exist per coordinate, BlockSnapshot
* can exist multiple times for any given Block.
*/
@SuppressWarnings("serial")
public class BlockSnapshot implements Serializable
{
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("forge.debugBlockSnapshot", "false"));
public final int x;
public final int y;
public final int z;
public final int dimId;
public transient Block replacedBlock;
public final int meta;
public int flag;
private final NBTTagCompound nbt;
public transient World world;
public final UniqueIdentifier blockIdentifier;
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta)
{
this.world = world;
this.dimId = world.provider.dimensionId;
this.x = x;
this.y = y;
this.z = z;
this.replacedBlock = block;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(block);
this.meta = meta;
this.flag = 3;
TileEntity te = world.getTileEntity(x, y, z);
if (te != null)
{
nbt = new NBTTagCompound();
te.writeToNBT(nbt);
}
else nbt = null;
if (DEBUG)
{
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), x, y, z, block, meta);
}
}
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta, NBTTagCompound nbt)
{
this.world = world;
this.dimId = world.provider.dimensionId;
this.x = x;
this.y = y;
this.z = z;
this.replacedBlock = block;
this.blockIdentifier = GameRegistry.findUniqueIdentifierFor(block);
this.meta = meta;
this.flag = 3;
this.nbt = nbt;
if (DEBUG)
{
System.out.printf("Created BlockSnapshot - [World: %s ][Location: %d,%d,%d ][Block: %s ][Meta: %d ]", world.getWorldInfo().getWorldName(), x, y, z, block, meta);
}
}
public BlockSnapshot(World world, int x, int y, int z, Block block, int meta, int flag)
{
this(world, x, y, z, block, meta);
this.flag = flag;
}
/**
* Raw constructor designed for serialization usages.
*/
public BlockSnapshot(int dimension, int x, int y, int z, String modid, String blockName, int meta, int flag, NBTTagCompound nbt)
{
this.dimId = dimension;
this.x = x;
this.y = y;
this.z = z;
this.meta = meta;
this.flag = flag;
this.blockIdentifier = new UniqueIdentifier(modid + ":" + blockName);
this.nbt = nbt;
}
public static BlockSnapshot getBlockSnapshot(World world, int x, int y, int z)
{
return new BlockSnapshot(world, x, y, z, world.getBlock(x, y, z), world.getBlockMetadata(x, y,z));
}
public static BlockSnapshot getBlockSnapshot(World world, int x, int y, int z, int flag)
{
return new BlockSnapshot(world, x, y, z, world.getBlock(x, y, z), world.getBlockMetadata(x, y,z), flag);
}
public static BlockSnapshot readFromNBT(NBTTagCompound tag)
{
NBTTagCompound nbt = tag.getBoolean("hasTE") ? null : tag.getCompoundTag("tileEntity");
return new BlockSnapshot(
tag.getInteger("dimension"),
tag.getInteger("posX"),
tag.getInteger("posY"),
tag.getInteger("posZ"),
tag.getString("blockMod"),
tag.getString("blockName"),
tag.getInteger("metadata"),
tag.getInteger("flag"),
nbt);
}
public Block getCurrentBlock()
{
return world.getBlock(x, y, z);
}
public World getWorld()
{
if (this.world == null)
{
this.world = DimensionManager.getWorld(dimId);
}
return this.world;
}
public Block getReplacedBlock()
{
if (this.replacedBlock == null)
{
this.replacedBlock = GameRegistry.findBlock(this.blockIdentifier.modId, this.blockIdentifier.name);
}
return this.replacedBlock;
}
public TileEntity getTileEntity()
{
if (nbt != null)
return TileEntity.createAndLoadEntity(nbt);
else return null;
}
public boolean restore()
{
return restore(false);
}
public boolean restore(boolean force)
{
return restore(force, true);
}
public boolean restore(boolean force, boolean applyPhysics)
{
if (getCurrentBlock() != getReplacedBlock() || world.getBlockMetadata(x & 15, y, z & 15) != meta)
{
if (force)
{
world.setBlock(x, y, z, getReplacedBlock(), meta, applyPhysics ? 3 : 2);
}
else
{
return false;
}
}
world.setBlockMetadataWithNotify(x, y, z, meta, applyPhysics ? 3 : 2);
world.markBlockForUpdate(x, y, z);
TileEntity te = null;
if (nbt != null)
{
te = world.getTileEntity(x, y, z);
if (te != null)
{
te.readFromNBT(nbt);
}
}
if (DEBUG)
{
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), x, y, z, meta, getReplacedBlock(), te, force, applyPhysics);
}
return true;
}
public boolean restoreToLocation(World world, int x, int y, int z, boolean force, boolean applyPhysics)
{
if (getCurrentBlock() != getReplacedBlock() || world.getBlockMetadata(x & 15, y, z & 15) != meta)
{
if (force)
{
world.setBlock(x, y, z, getReplacedBlock(), meta, applyPhysics ? 3 : 2);
}
else
{
return false;
}
}
world.setBlockMetadataWithNotify(x, y, z, meta, applyPhysics ? 3 : 2);
world.markBlockForUpdate(x, y, z);
TileEntity te = null;
if (nbt != null)
{
te = world.getTileEntity(x, y, z);
if (te != null)
{
te.readFromNBT(nbt);
}
}
if (DEBUG)
{
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][applyPhysics: %s]", world.getWorldInfo().getWorldName(), x, y, z, meta, getReplacedBlock(), te, force, applyPhysics);
}
return true;
}
public void writeToNBT(NBTTagCompound compound)
{
compound.setString("blockMod", blockIdentifier.modId);
compound.setString("blockName", blockIdentifier.name);
compound.setInteger("posX", x);
compound.setInteger("posY", y);
compound.setInteger("posZ", z);
compound.setInteger("flag", flag);
compound.setInteger("dimension", dimId);
compound.setInteger("metadata", meta);
compound.setBoolean("hasTE", nbt != null);
if (nbt != null)
{
compound.setTag("tileEntity", nbt);
}
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final BlockSnapshot other = (BlockSnapshot) obj;
if (this.x != other.x)
{
return false;
}
if (this.y != other.y)
{
return false;
}
if (this.z != other.z)
{
return false;
}
if (this.meta != other.meta)
{
return false;
}
if (this.dimId != other.dimId)
{
return false;
}
if (this.nbt != other.nbt && (this.nbt == null || !this.nbt.equals(other.nbt)))
{
return false;
}
if (this.world != other.world && (this.world == null || !this.world.equals(other.world)))
{
return false;
}
if (this.blockIdentifier != other.blockIdentifier && (this.blockIdentifier == null || !this.blockIdentifier.equals(other.blockIdentifier)))
{
return false;
}
return true;
}
@Override
public int hashCode()
{
int hash = 7;
hash = 73 * hash + this.x;
hash = 73 * hash + this.y;
hash = 73 * hash + this.z;
hash = 73 * hash + this.meta;
hash = 73 * hash + this.dimId;
hash = 73 * hash + (this.nbt != null ? this.nbt.hashCode() : 0);
hash = 73 * hash + (this.world != null ? this.world.hashCode() : 0);
hash = 73 * hash + (this.blockIdentifier != null ? this.blockIdentifier.hashCode() : 0);
return hash;
}
}

View File

@ -14,6 +14,7 @@ import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
@ -21,6 +22,8 @@ import net.minecraft.world.biome.BiomeGenBase;
import net.minecraft.world.storage.IPlayerFileData;
import net.minecraft.world.storage.SaveHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.entity.EntityStruckByLightningEvent;
import net.minecraftforge.event.entity.living.LivingPackSizeEvent;
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
@ -33,10 +36,31 @@ import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
import net.minecraftforge.event.entity.player.PlayerUseItemEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.BlockEvent.MultiPlaceEvent;
import net.minecraftforge.event.world.BlockEvent.PlaceEvent;
import net.minecraftforge.event.world.WorldEvent;
public class ForgeEventFactory
{
public static MultiPlaceEvent onPlayerMultiBlockPlace(EntityPlayer player, List<BlockSnapshot> blockSnapshots, ForgeDirection direction)
{
Block placedAgainst = blockSnapshots.get(0).world.getBlock(blockSnapshots.get(0).x + direction.getOpposite().offsetX, blockSnapshots.get(0).y + direction.getOpposite().offsetY, blockSnapshots.get(0).z + direction.getOpposite().offsetZ);
MultiPlaceEvent event = new MultiPlaceEvent(blockSnapshots, placedAgainst, player);
MinecraftForge.EVENT_BUS.post(event);
return event;
}
public static PlaceEvent onPlayerBlockPlace(EntityPlayer player, BlockSnapshot blockSnapshot, ForgeDirection direction)
{
Block placedAgainst = blockSnapshot.world.getBlock(blockSnapshot.x + direction.getOpposite().offsetX, blockSnapshot.y + direction.getOpposite().offsetY, blockSnapshot.z + direction.getOpposite().offsetZ);
PlaceEvent event = new PlaceEvent(blockSnapshot, placedAgainst, player);
MinecraftForge.EVENT_BUS.post(event);
return event;
}
public static boolean doPlayerHarvestCheck(EntityPlayer player, Block block, boolean success)
{
PlayerEvent.HarvestCheck event = new PlayerEvent.HarvestCheck(player, block, success);

View File

@ -1,17 +1,24 @@
package net.minecraftforge.event.world;
import java.util.ArrayList;
import java.util.List;
import com.google.common.collect.ImmutableList;
import cpw.mods.fml.common.eventhandler.Cancelable;
import cpw.mods.fml.common.eventhandler.Event;
import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.util.BlockSnapshot;
public class BlockEvent extends Event {
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("forge.debugBlockEvent", "false"));
public final int x;
public final int y;
public final int z;
@ -111,4 +118,63 @@ public class BlockEvent extends Event {
this.exp = exp;
}
}
/**
* Called when a block is placed by a player.
*
* If a Block Place event is cancelled, the block will not be placed.
*/
@Cancelable
public static class PlaceEvent extends BlockEvent {
public final EntityPlayer player;
public final ItemStack itemInHand;
public final BlockSnapshot blockSnapshot;
public final Block placedBlock;
public final Block placedAgainst;
public PlaceEvent(BlockSnapshot blockSnapshot, Block placedAgainst, EntityPlayer player) {
super(blockSnapshot.x, blockSnapshot.y, blockSnapshot.z, blockSnapshot.world, blockSnapshot.getCurrentBlock(), blockSnapshot.meta);
this.player = player;
this.itemInHand = player.getCurrentEquippedItem();
this.blockSnapshot = blockSnapshot;
this.placedBlock = blockSnapshot.getCurrentBlock();
this.placedAgainst = placedAgainst;
if (DEBUG)
{
System.out.printf("Created PlaceEvent - [PlacedBlock: %s ][PlacedAgainst: %s ][ItemStack: %s ][Player: %s ]\n", placedBlock, placedAgainst, player.getCurrentEquippedItem(), player);
}
}
}
/**
* Fired when a single block placement action of a player triggers the
* creation of multiple blocks(e.g. placing a bed block). The block returned
* by {@link #block} and its related methods is the block where
* the placed block would exist if the placement only affected a single
* block.
*/
@Cancelable
public static class MultiPlaceEvent extends PlaceEvent {
private final List<BlockSnapshot> blockSnapshots;
public MultiPlaceEvent(List<BlockSnapshot> blockSnapshots, Block placedAgainst, EntityPlayer player) {
super(blockSnapshots.get(0), placedAgainst, player);
this.blockSnapshots = ImmutableList.copyOf(blockSnapshots);
if (DEBUG)
{
System.out.printf("Created MultiPlaceEvent - [PlacedAgainst: %s ][ItemInHand: %s ][Player: %s ]\n", placedAgainst, this.itemInHand, player);
}
}
/**
* Gets a list of blocksnapshots for all blocks which were replaced by the
* placement of the new blocks. Most of these blocks will just be of type AIR.
*
* @return immutable list of replaced BlockSnapshots
*/
public List<BlockSnapshot> getReplacedBlockSnapshots() {
return blockSnapshots;
}
}
}