Merge pull request #852 from MinecraftForge/breakevent

Merge BreakEvent branch, as nobody has told me that it breaks everything. And in prep from 1.7.
This commit is contained in:
LexManos 2013-11-09 00:43:58 -08:00
commit cfd368e18f
10 changed files with 245 additions and 14 deletions

View file

@ -47,6 +47,7 @@ public aqz.a(F)Laqz; #MD:Block/func_71900_a #setLightValue
public aqz.r()Laqz; #MD:Block/func_71875_q #setBlockUnbreakable public aqz.r()Laqz; #MD:Block/func_71875_q #setBlockUnbreakable
public aqz.b(Z)Laqz; #MD:Block/func_71907_b #setTickRandomly public aqz.b(Z)Laqz; #MD:Block/func_71907_b #setTickRandomly
public aqz.a(FFFFFF)V #MD:Block/func_71905_a #setBlockBounds public aqz.a(FFFFFF)V #MD:Block/func_71905_a #setBlockBounds
public aqz.j(Labw;IIII)V #MD:Block/func_71923_g #dropXpOnBlockBreak
# NetServerHandler # NetServerHandler
public ka.f #FD:NetServerHandler/field_72572_g #playerInAirTime public ka.f #FD:NetServerHandler/field_72572_g #playerInAirTime
# TileEntity # TileEntity

View file

@ -1,16 +1,19 @@
package net.minecraftforge.common; package net.minecraftforge.common;
import net.minecraft.entity.player.EntityPlayer; import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemInWorldManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatMessageComponent; import net.minecraft.util.ChatMessageComponent;
import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World; import net.minecraft.world.World;
//Preliminary, simple Fake Player class //Preliminary, simple Fake Player class
public class FakePlayer extends EntityPlayer public class FakePlayer extends EntityPlayerMP
{ {
public FakePlayer(World world, String name) public FakePlayer(World world, String name)
{ {
super(world, name); super(FMLCommonHandler.instance().getMinecraftServerInstance(), world, name, new ItemInWorldManager(world));
} }
public void sendChatToPlayer(String s){} public void sendChatToPlayer(String s){}

View file

@ -5,14 +5,30 @@ import net.minecraft.world.World;
//To be expanded for generic Mod fake players? //To be expanded for generic Mod fake players?
public class FakePlayerFactory public class FakePlayerFactory
{ {
// Map of all active fake player usernames to their entities
private static java.util.Map<String, FakePlayer> fakePlayers = new java.util.HashMap<String, FakePlayer>();
private static FakePlayer MINECRAFT_PLAYER = null; private static FakePlayer MINECRAFT_PLAYER = null;
public static FakePlayer getMinecraft(World world) public static FakePlayer getMinecraft(World world)
{ {
if (MINECRAFT_PLAYER == null) if (MINECRAFT_PLAYER == null)
{ {
MINECRAFT_PLAYER = new FakePlayer(world, "[Minecraft]"); MINECRAFT_PLAYER = FakePlayerFactory.get(world, "[Minecraft]");
} }
return MINECRAFT_PLAYER; return MINECRAFT_PLAYER;
} }
/**
* Get a fake player with a given username
*/
public static FakePlayer get(World world, String username)
{
if (!fakePlayers.containsKey(username))
{
FakePlayer fakePlayer = new FakePlayer(world, username);
fakePlayers.put(username, fakePlayer);
}
return fakePlayers.get(username);
}
} }

View file

@ -7,10 +7,12 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container; import net.minecraft.inventory.Container;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemArmor; import net.minecraft.item.ItemArmor;
@ -18,7 +20,10 @@ import net.minecraft.item.ItemAxe;
import net.minecraft.item.ItemPickaxe; import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemSpade; import net.minecraft.item.ItemSpade;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.network.NetServerHandler; import net.minecraft.network.NetServerHandler;
import net.minecraft.network.packet.Packet53BlockChange;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChatMessageComponent; import net.minecraft.util.ChatMessageComponent;
import net.minecraft.util.DamageSource; import net.minecraft.util.DamageSource;
@ -27,6 +32,7 @@ import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.WeightedRandom; import net.minecraft.util.WeightedRandom;
import net.minecraft.util.WeightedRandomItem; import net.minecraft.util.WeightedRandomItem;
import net.minecraft.world.EnumGameType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.event.Event; import net.minecraftforge.event.Event;
import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeEventFactory;
@ -41,6 +47,7 @@ import net.minecraftforge.event.entity.living.LivingFallEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
import net.minecraftforge.event.entity.player.PlayerOpenContainerEvent; import net.minecraftforge.event.entity.player.PlayerOpenContainerEvent;
import net.minecraftforge.event.world.BlockEvent;
public class ForgeHooks public class ForgeHooks
{ {
@ -440,4 +447,49 @@ public class ForgeHooks
MinecraftForge.EVENT_BUS.post(event); MinecraftForge.EVENT_BUS.post(event);
return event.getResult() == Event.Result.DEFAULT ? event.canInteractWith : event.getResult() == Event.Result.ALLOW ? true : false; return event.getResult() == Event.Result.DEFAULT ? event.canInteractWith : event.getResult() == Event.Result.ALLOW ? true : false;
} }
public static BlockEvent.BreakEvent onBlockBreakEvent(World world, EnumGameType gameType, EntityPlayerMP entityPlayer, int x, int y, int z)
{
// Logic from tryHarvestBlock for pre-canceling the event
boolean preCancelEvent = false;
if (gameType.isAdventure() && !entityPlayer.isCurrentToolAdventureModeExempt(x, y, z))
{
preCancelEvent = true;
}
else if (gameType.isCreative() && entityPlayer.getHeldItem() != null && entityPlayer.getHeldItem().getItem() instanceof ItemSword)
{
preCancelEvent = true;
}
// Tell client the block is gone immediately then process events
if (world.getBlockTileEntity(x, y, z) == null)
{
Packet53BlockChange packet = new Packet53BlockChange(x, y, z, world);
packet.type = 0;
packet.metadata = 0;
entityPlayer.playerNetServerHandler.sendPacketToPlayer(packet);
}
// Post the block break event
Block block = Block.blocksList[world.getBlockId(x, y, z)];
int blockMetadata = world.getBlockMetadata(x, y, z);
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(x, y, z, world, block, blockMetadata, entityPlayer);
event.setCanceled(preCancelEvent);
MinecraftForge.EVENT_BUS.post(event);
// Handle if the event is canceled
if (event.isCanceled())
{
// Let the client know the block still exists
entityPlayer.playerNetServerHandler.sendPacketToPlayer(new Packet53BlockChange(x, y, z, world));
// Update any tile entity data for this block
TileEntity tileentity = world.getBlockTileEntity(x, y, z);
if (tileentity != null)
{
entityPlayer.playerNetServerHandler.sendPacketToPlayer(tileentity.getDescriptionPacket());
}
}
return event;
}
} }

View file

@ -3,9 +3,11 @@ package net.minecraftforge.event.world;
import java.util.ArrayList; import java.util.ArrayList;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.event.Cancelable;
import net.minecraftforge.event.Event; import net.minecraftforge.event.Event;
public class BlockEvent extends Event { public class BlockEvent extends Event {
@ -53,5 +55,59 @@ public class BlockEvent extends Event {
this.harvester = harvester; this.harvester = harvester;
} }
} }
/**
* Event that is fired when an Block is about to be broken by a player
* Canceling this event will prevent the Block from being broken.
*/
@Cancelable
public static class BreakEvent extends BlockEvent
{
/** Reference to the Player who broke the block. If no player is available, use a EntityFakePlayer */
private final EntityPlayer player;
private int exp;
public BreakEvent(int x, int y, int z, World world, Block block, int blockMetadata, EntityPlayer player)
{
super(x, y, z, world, block, blockMetadata);
this.player = player;
if (block == null || !player.canHarvestBlock(block) || // Handle empty block or player unable to break block scenario
block.canSilkHarvest(world, player, x, y, z, blockMetadata) && EnchantmentHelper.getSilkTouchModifier(player)) // If the block is being silk harvested, the exp dropped is 0
{
this.exp = 0;
}
else
{
int meta = block.getDamageValue(world, x, y, z);
int bonusLevel = EnchantmentHelper.getFortuneModifier(player);
this.exp = block.getExpDrop(world, meta, bonusLevel);
}
}
public EntityPlayer getPlayer()
{
return player;
}
/**
* Get the experience dropped by the block after the event has processed
*
* @return The experience to drop or 0 if the event was canceled
*/
public int getExpToDrop()
{
return this.isCanceled() ? 0 : exp;
}
/**
* Set the amount of experience dropped by the block after the event has processed
*
* @param exp 1 or higher to drop experience, else nothing will drop
*/
public void setExpToDrop(int exp)
{
this.exp = exp;
}
}
} }

View file

@ -198,7 +198,7 @@
} }
/** /**
@@ -1457,4 +1491,993 @@ @@ -1457,4 +1491,1001 @@
canBlockGrass[0] = true; canBlockGrass[0] = true;
StatList.initBreakableStats(); StatList.initBreakableStats();
} }
@ -1151,6 +1151,14 @@
+ } + }
+ return false; + return false;
+ } + }
+
+ /**
+ * @return the amount of XP that this block should drop when it is broken
+ */
+ public int getExpDrop(World world, int data, int enchantmentLevel)
+ {
+ return 0;
+ }
+ +
+ /** + /**
+ * Called when a tile entity on a side of this block changes is created or is destroyed. + * Called when a tile entity on a side of this block changes is created or is destroyed.

View file

@ -0,0 +1,17 @@
--- ../src_base/minecraft/net/minecraft/block/BlockMobSpawner.java
+++ ../src_work/minecraft/net/minecraft/block/BlockMobSpawner.java
@@ -45,8 +45,12 @@
public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7)
{
super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
- int j1 = 15 + par1World.rand.nextInt(15) + par1World.rand.nextInt(15);
- this.dropXpOnBlockBreak(par1World, par2, par3, par4, j1);
+ }
+
+ @Override
+ public int getExpDrop(World world, int data, int enchantmentLevel)
+ {
+ return 15 + world.rand.nextInt(15) + world.rand.nextInt(15);
}
/**

View file

@ -0,0 +1,27 @@
--- ../src_base/minecraft/net/minecraft/block/BlockOre.java
+++ ../src_work/minecraft/net/minecraft/block/BlockOre.java
@@ -60,6 +60,11 @@
{
super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+ }
+
+ @Override
+ public int getExpDrop(World par1World, int par5, int par7)
+ {
if (this.idDropped(par5, par1World.rand, par7) != this.blockID)
{
int j1 = 0;
@@ -84,9 +89,10 @@
{
j1 = MathHelper.getRandomIntegerInRange(par1World.rand, 2, 5);
}
+ return j1;
+ }
- this.dropXpOnBlockBreak(par1World, par2, par3, par4, j1);
- }
+ return 0;
}
/**

View file

@ -0,0 +1,22 @@
--- ../src_base/minecraft/net/minecraft/block/BlockRedstoneOre.java
+++ ../src_work/minecraft/net/minecraft/block/BlockRedstoneOre.java
@@ -116,11 +116,17 @@
{
super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, par7);
+ }
+
+ @Override
+ public int getExpDrop(World par1World, int par5, int par7)
+ {
if (this.idDropped(par5, par1World.rand, par7) != this.blockID)
{
int j1 = 1 + par1World.rand.nextInt(5);
- this.dropXpOnBlockBreak(par1World, par2, par3, par4, j1);
- }
+ return j1;
+ }
+ return 0;
}
@SideOnly(Side.CLIENT)

View file

@ -1,6 +1,11 @@
--- ../src_base/minecraft/net/minecraft/item/ItemInWorldManager.java --- ../src_base/minecraft/net/minecraft/item/ItemInWorldManager.java
+++ ../src_work/minecraft/net/minecraft/item/ItemInWorldManager.java +++ ../src_work/minecraft/net/minecraft/item/ItemInWorldManager.java
@@ -8,8 +8,19 @@ @@ -4,12 +4,25 @@
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.packet.Packet53BlockChange;
+import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.EnumGameType;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
@ -11,6 +16,7 @@
+import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; +import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action; +import net.minecraftforge.event.entity.player.PlayerInteractEvent.Action;
+import net.minecraftforge.event.world.BlockEvent;
+ +
public class ItemInWorldManager public class ItemInWorldManager
{ {
@ -20,7 +26,7 @@
/** The world object that this object is connected to. */ /** The world object that this object is connected to. */
public World theWorld; public World theWorld;
@@ -145,6 +156,13 @@ @@ -145,6 +158,13 @@
{ {
if (!this.gameType.isAdventure() || this.thisPlayerMP.isCurrentToolAdventureModeExempt(par1, par2, par3)) if (!this.gameType.isAdventure() || this.thisPlayerMP.isCurrentToolAdventureModeExempt(par1, par2, par3))
{ {
@ -34,7 +40,7 @@
if (this.isCreative()) if (this.isCreative())
{ {
if (!this.theWorld.extinguishFire((EntityPlayer)null, par1, par2, par3, par4)) if (!this.theWorld.extinguishFire((EntityPlayer)null, par1, par2, par3, par4))
@@ -154,15 +172,33 @@ @@ -154,15 +174,33 @@
} }
else else
{ {
@ -73,7 +79,7 @@
} }
if (i1 > 0 && f >= 1.0F) if (i1 > 0 && f >= 1.0F)
@@ -236,7 +272,7 @@ @@ -236,7 +274,7 @@
block.onBlockHarvested(this.theWorld, par1, par2, par3, l, this.thisPlayerMP); block.onBlockHarvested(this.theWorld, par1, par2, par3, l, this.thisPlayerMP);
} }
@ -82,8 +88,20 @@
if (block != null && flag) if (block != null && flag)
{ {
@@ -261,19 +297,30 @@ @@ -251,29 +289,37 @@
*/
public boolean tryHarvestBlock(int par1, int par2, int par3)
{
- if (this.gameType.isAdventure() && !this.thisPlayerMP.isCurrentToolAdventureModeExempt(par1, par2, par3))
+ BlockEvent.BreakEvent event = ForgeHooks.onBlockBreakEvent(theWorld, gameType, thisPlayerMP, par1, par2, par3);
+ if (event.isCanceled())
{
return false;
} }
- else if (this.gameType.isCreative() && this.thisPlayerMP.getHeldItem() != null && this.thisPlayerMP.getHeldItem().getItem() instanceof ItemSword)
- {
- return false;
- }
else else
{ {
+ ItemStack stack = thisPlayerMP.getCurrentEquippedItem(); + ItemStack stack = thisPlayerMP.getCurrentEquippedItem();
@ -115,7 +133,7 @@
if (itemstack != null) if (itemstack != null)
{ {
@@ -285,6 +332,7 @@ @@ -285,11 +331,18 @@
} }
} }
@ -123,7 +141,18 @@
if (flag && flag1) if (flag && flag1)
{ {
Block.blocksList[l].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, i1); Block.blocksList[l].harvestBlock(this.theWorld, this.thisPlayerMP, par1, par2, par3, i1);
@@ -325,6 +373,7 @@ }
}
+
+ // Drop experience
+ if (!this.isCreative() && flag && event != null)
+ {
+ Block.blocksList[l].dropXpOnBlockBreak(this.theWorld, par1, par2, par3, event.getExpToDrop());
+ }
return flag;
}
@@ -325,6 +378,7 @@
if (itemstack1.stackSize == 0) if (itemstack1.stackSize == 0)
{ {
par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null; par1EntityPlayer.inventory.mainInventory[par1EntityPlayer.inventory.currentItem] = null;
@ -131,7 +160,7 @@
} }
if (!par1EntityPlayer.isUsingItem()) if (!par1EntityPlayer.isUsingItem())
@@ -342,35 +391,56 @@ @@ -342,35 +396,56 @@
*/ */
public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack, int par4, int par5, int par6, int par7, float par8, float par9, float par10) public boolean activateBlockOrUseItem(EntityPlayer par1EntityPlayer, World par2World, ItemStack par3ItemStack, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{ {
@ -215,7 +244,7 @@
} }
/** /**
@@ -380,4 +450,13 @@ @@ -380,4 +455,13 @@
{ {
this.theWorld = par1WorldServer; this.theWorld = par1WorldServer;
} }