From 22baa13894264fad9584a10bcdf7427588c07989 Mon Sep 17 00:00:00 2001 From: EvilSeph Date: Sat, 1 Oct 2011 13:31:28 -0400 Subject: [PATCH] Painting improvements. Thanks CelticMinstrel! Implement get/setArt and facing direction for paintings; expanded painting break causes; added painting support to World.spawn --- .../net/minecraft/server/EntityPainting.java | 54 ++++++++- .../org/bukkit/craftbukkit/CraftWorld.java | 33 +++++- .../craftbukkit/entity/CraftPainting.java | 112 +++++++++++++++++- 3 files changed, 190 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/minecraft/server/EntityPainting.java b/src/main/java/net/minecraft/server/EntityPainting.java index d94fe56c87..c0441a8e1e 100644 --- a/src/main/java/net/minecraft/server/EntityPainting.java +++ b/src/main/java/net/minecraft/server/EntityPainting.java @@ -4,8 +4,11 @@ import java.util.ArrayList; import java.util.List; // CraftBukkit start +import org.bukkit.Bukkit; +import org.bukkit.entity.Painting; import org.bukkit.event.painting.PaintingBreakByEntityEvent; -import org.bukkit.event.painting.PaintingBreakByWorldEvent; +import org.bukkit.event.painting.PaintingBreakEvent.RemoveCause; +import org.bukkit.event.painting.PaintingBreakEvent; // CraftBukkit end public class EntityPainting extends Entity { @@ -123,7 +126,17 @@ public class EntityPainting extends Entity { this.f = 0; if (!this.i()) { // CraftBukkit start - PaintingBreakByWorldEvent event = new PaintingBreakByWorldEvent((org.bukkit.entity.Painting) this.getBukkitEntity()); + Material material = this.world.getMaterial((int)this.locX, (int)this.locY, (int)this.locZ); + RemoveCause cause; + if (material.equals(Material.WATER)) { + cause = RemoveCause.WATER; + } else if (!material.equals(Material.AIR)) { + // TODO: This feels insufficient to catch 100% of suffocation cases + cause = RemoveCause.OBSTRUCTION; + } else { + cause = RemoveCause.PHYSICS; + } + PaintingBreakEvent event = new PaintingBreakEvent((Painting) this.getBukkitEntity(), cause); this.world.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -204,11 +217,21 @@ public class EntityPainting extends Entity { public boolean damageEntity(DamageSource damagesource, int i) { if (!this.dead && !this.world.isStatic) { // CraftBukkit start - PaintingBreakByEntityEvent event = new PaintingBreakByEntityEvent((org.bukkit.entity.Painting) this.getBukkitEntity(), damagesource.getEntity() == null ? null : damagesource.getEntity().getBukkitEntity()); - this.world.getServer().getPluginManager().callEvent(event); + PaintingBreakEvent event = null; + if (damagesource.getEntity() != null) { + event = new PaintingBreakByEntityEvent((Painting) this.getBukkitEntity(), damagesource.getEntity() == null ? null : damagesource.getEntity().getBukkitEntity()); + } else { + if (damagesource == DamageSource.FIRE) { + event = new PaintingBreakEvent((Painting) this.getBukkitEntity(), RemoveCause.FIRE); + } + // TODO: Could put other stuff here? + } + if (event != null) { + this.world.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - return true; + if (event.isCancelled()) { + return true; + } } if(!dead) { @@ -222,6 +245,25 @@ public class EntityPainting extends Entity { return true; } + // CraftBukkit start - copy of a method in Entity except for the CraftBukkit-specific code + // TODO: Better way? + public void a(EntityWeatherStorm entityweatherstorm) { + // CraftBukkit start + PaintingBreakByEntityEvent event = new PaintingBreakByEntityEvent((Painting) this.getBukkitEntity(), entityweatherstorm.getBukkitEntity()); + Bukkit.getServer().getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return; + } + // CraftBukkit end + + ++this.fireTicks; + if (this.fireTicks == 0) { + this.fireTicks = 300; + } + } + // CraftBukkit end + public void b(NBTTagCompound nbttagcompound) { nbttagcompound.a("Dir", (byte) this.a); nbttagcompound.setString("Motive", this.e.A); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 63ecd69908..d4c23515f9 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -20,6 +20,7 @@ import org.bukkit.event.weather.WeatherChangeEvent; import org.bukkit.event.weather.ThunderChangeEvent; import org.bukkit.event.world.SpawnChangeEvent; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.entity.Boat; import org.bukkit.Chunk; import org.bukkit.inventory.ItemStack; @@ -755,7 +756,37 @@ public class CraftWorld implements World { } } else if (Painting.class.isAssignableFrom(clazz)) { - // negative + Block block = getBlockAt(location); + BlockFace face = BlockFace.SELF; + if (block.getRelative(BlockFace.EAST).getTypeId() == 0) { + face = BlockFace.EAST; + } else if (block.getRelative(BlockFace.NORTH).getTypeId() == 0) { + face = BlockFace.NORTH; + } else if (block.getRelative(BlockFace.WEST).getTypeId() == 0) { + face = BlockFace.WEST; + } else if (block.getRelative(BlockFace.SOUTH).getTypeId() == 0) { + face = BlockFace.SOUTH; + } + int dir; + switch(face) { + case EAST: + default: + dir = 0; + break; + case NORTH: + dir = 1; + break; + case WEST: + dir = 2; + break; + case SOUTH: + dir = 3;; + break; + } + entity = new EntityPainting(world, (int) x, (int) y, (int) z, dir); + if (!((EntityPainting)entity).i()) { + entity = null; + } } else if (TNTPrimed.class.isAssignableFrom(clazz)) { entity = new EntityTNTPrimed(world, x, y, z); } else if (ExperienceOrb.class.isAssignableFrom(clazz)) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java index 68b2191572..69647d7bb3 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPainting.java @@ -1,8 +1,16 @@ package org.bukkit.craftbukkit.entity; import net.minecraft.server.EntityPainting; +import net.minecraft.server.EnumArt; +import net.minecraft.server.Packet25EntityPainting; +import net.minecraft.server.Packet29DestroyEntity; +import net.minecraft.server.WorldServer; +import org.bukkit.Art; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.entity.Painting; public class CraftPainting extends CraftEntity implements Painting { @@ -12,8 +20,108 @@ public class CraftPainting extends CraftEntity implements Painting { } @Override - public String toString() { - return "CraftPainting"; + public EntityPainting getHandle() { + return (EntityPainting) super.getHandle(); } + @Override + public String toString() { + return "CraftPainting[art=" + getArt() + "]"; + } + + public Art getArt() { + EnumArt art = getHandle().e; + // Since both EnumArt and Art have exactly the same enum constants, this works + return Art.getByName(art.toString()); + } + + public boolean setArt(Art art) { + return setArt(art, false); + } + + public boolean setArt(Art art, boolean force) { + EntityPainting painting = getHandle(); + EnumArt oldArt = painting.e; + EnumArt newArt = EnumArt.valueOf(art.toString()); + painting.e = newArt; + painting.b(painting.a); + if(!force && !painting.i()) { + // Revert painting since it doesn't fit + painting.e = oldArt; + painting.b(painting.a); + return false; + } + this.update(); + return true; + } + + public BlockFace getAttachedFace() { + return getFacing().getOppositeFace(); + } + + public void setFacingDirection(BlockFace face) { + setFacingDirection(face, false); + } + + public boolean setFacingDirection(BlockFace face, boolean force) { + Block block = getLocation().getBlock().getRelative(getAttachedFace()).getRelative(face.getOppositeFace()).getRelative(getFacing()); + EntityPainting painting = getHandle(); + int x = painting.b, y = painting.c, z = painting.d, dir = painting.a; + painting.b = block.getX(); + painting.c = block.getY(); + painting.d = block.getZ(); + switch(face) { + case EAST: + default: + getHandle().b(0); + break; + case NORTH: + getHandle().b(1); + break; + case WEST: + getHandle().b(2); + break; + case SOUTH: + getHandle().b(3); + break; + } + if(!force && !painting.i()) { + // Revert painting since it doesn't fit + painting.b = x; + painting.c = y; + painting.d = z; + painting.b(dir); + return false; + } + this.update(); + return true; + } + + public BlockFace getFacing() { + switch(getHandle().a) { + case 0: + default: + return BlockFace.EAST; + case 1: + return BlockFace.NORTH; + case 2: + return BlockFace.WEST; + case 3: + return BlockFace.SOUTH; + } + } + + private void update() { + WorldServer world = ((CraftWorld)getWorld()).getHandle(); + EntityPainting painting = new EntityPainting(world); + painting.b = getHandle().b; + painting.c = getHandle().c; + painting.d = getHandle().d; + painting.e = getHandle().e; + painting.b(getHandle().a); + getHandle().die(); + getHandle().velocityChanged = true; // because this occurs when the painting is broken, so it might be important + world.addEntity(painting); + this.entity = painting; + } }