Added proper repairing of containers and signs

This commit is contained in:
Garbage Mule 2011-08-15 01:34:14 +02:00
parent 8d234a50e9
commit a3d1b4bb80
12 changed files with 442 additions and 53 deletions

Binary file not shown.

View File

@ -7,6 +7,7 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@ -25,6 +26,8 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.ContainerBlock;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Creature;
@ -40,6 +43,9 @@ import org.bukkit.inventory.PlayerInventory;
import org.bukkit.util.config.Configuration;
import com.garbagemule.MobArena.MAMessages.Msg;
import com.garbagemule.MobArena.repairable.Repairable;
import com.garbagemule.MobArena.repairable.RepairableComparator;
import com.garbagemule.MobArena.repairable.RepairableContainer;
import com.garbagemule.MobArena.util.WaveUtils;
import com.garbagemule.MobArena.waves.BossWave;
import com.garbagemule.MobArena.waves.Wave;
@ -74,8 +80,6 @@ public class Arena
// Player sets
protected Set<Player> arenaPlayers, lobbyPlayers, readyPlayers, specPlayers;
// Wave stuff
//protected TreeSet<SingleWave> singleWaves;
//protected TreeSet<RecurrentWave> recurrentWaves;
protected TreeSet<Wave> singleWaves, singleWavesInstance;
protected TreeSet<Wave> recurrentWaves;
protected BossWave bossWave;
@ -84,12 +88,13 @@ public class Arena
// NEW IMPLEMENTATION
// Arena sets/maps
protected Set<Player> hasPaid, rewardedPlayers, notifyPlayers, randoms;
protected Set<LivingEntity> monsters, explodingSheep, plaguedPigs, madCows;
protected Set<Block> blocks;
protected Set<Wolf> pets;
protected Map<Player,Integer> petMap;
protected List<int[]> repairList;
protected Set<Player> hasPaid, rewardedPlayers, notifyPlayers, randoms;
protected Set<LivingEntity> monsters, explodingSheep, plaguedPigs, madCows;
protected Set<Block> blocks;
protected Set<Wolf> pets;
protected Map<Player,Integer> petMap;
//protected List<int[]> repairList;
protected LinkedList<Repairable> repairables;
// Spawn overriding
protected int spawnMonsters;
@ -134,7 +139,8 @@ public class Arena
petMap = new HashMap<Player,Integer>();
classMap = new HashMap<Player,String>();
randoms = new HashSet<Player>();
repairList = new LinkedList<int[]>();
//repairList = new LinkedList<int[]>();
repairables = new LinkedList<Repairable>();
running = false;
edit = false;
@ -153,6 +159,8 @@ public class Arena
return false;
if (!softRestore && forceRestore && !serializeRegion())
return false;
saveContainerContents();
// Populate arenaPlayers and clear the lobby.
arenaPlayers.addAll(lobbyPlayers);
@ -223,9 +231,13 @@ public class Arena
cleanup();
// Restore region.
/*
if (softRestore)
for (int[] buffer : repairList)
world.getBlockAt(buffer[0], buffer[1], buffer[2]).setTypeIdAndData(buffer[3], (byte) buffer[4], false);
*/
if (softRestore)
restoreRegion();
else if (forceRestore)
deserializeRegion();
@ -502,6 +514,29 @@ public class Arena
healthMap.put(p, p.getHealth());
}
public void saveContainerContents()
{
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
new Runnable()
{
public void run()
{
long start = System.nanoTime();
LinkedList<RepairableContainer> list = new LinkedList<RepairableContainer>();
for (int x = p1.getBlockX(); x <= p2.getBlockX(); x++)
for (int y = p1.getBlockY(); y <= p2.getBlockY(); y++)
for (int z = p1.getBlockZ(); z <= p2.getBlockZ(); z++)
{
BlockState bs = world.getBlockAt(x,y,z).getState();
if (bs instanceof ContainerBlock)
list.add(new RepairableContainer(bs));
}
list.clear();
System.out.println("Iteration took: " + (System.nanoTime() - start) + " ns");
}
});
}
public void movePlayerToLobby(Player p)
{
updateChunk(lobbyLoc);
@ -776,6 +811,14 @@ public class Arena
lobbySetup = MAUtils.verifyLobby(this);
}
public void restoreRegion()
{
Collections.sort(repairables, new RepairableComparator());
for (Repairable r : repairables)
r.repair();
}
public void serializeConfig()
{
String coords = "arenas." + configName() + ".coords.";

View File

@ -1,6 +1,5 @@
package com.garbagemule.MobArena;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface Arenaz

View File

@ -1,12 +1,15 @@
package com.garbagemule.MobArena;
import java.util.HashMap;
import java.util.Map;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.ContainerBlock;
import org.bukkit.block.Sign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@ -19,7 +22,6 @@ import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockIgniteEvent.IgniteCause;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
@ -39,8 +41,14 @@ import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.material.Attachable;
import com.garbagemule.MobArena.MAMessages.Msg;
import com.garbagemule.MobArena.repairable.Repairable;
import com.garbagemule.MobArena.repairable.RepairableBlock;
import com.garbagemule.MobArena.repairable.RepairableComparator;
import com.garbagemule.MobArena.repairable.RepairableContainer;
import com.garbagemule.MobArena.repairable.RepairableSign;
public class MAListener implements ArenaListener
{
@ -58,26 +66,38 @@ public class MAListener implements ArenaListener
if (!arena.inRegion(event.getBlock().getLocation()) || arena.edit || (!arena.protect && arena.running))
return;
BlockState statez = event.getBlock().getState();
if (statez.getData() instanceof Attachable)
{
System.out.println(statez.getData());
event.setCancelled(true);
}
Block b = event.getBlock();
if (arena.blocks.remove(b) || b.getType() == Material.TNT)
return;
if (arena.softRestore && arena.running)
{
int[] buffer = new int[5];
buffer[0] = b.getX();
buffer[1] = b.getY();
buffer[2] = b.getZ();
buffer[3] = b.getTypeId();
buffer[4] = (int) b.getData();
arena.repairList.add(buffer);
if (!arena.softRestoreDrops) event.getBlock().setTypeId(0);
BlockState state = b.getState();
if (state instanceof ContainerBlock)
arena.repairables.add(new RepairableContainer(state));
else if (state instanceof Sign)
arena.repairables.add(new RepairableSign(state));
else
arena.repairables.add(new RepairableBlock(state));
if (!arena.softRestoreDrops)
b.setTypeId(0);
return;
}
event.setCancelled(true);
}
public void onBlockPlace(BlockPlaceEvent event)
{
if (!arena.inRegion(event.getBlock().getLocation()) || arena.edit)
@ -109,13 +129,13 @@ public class MAListener implements ArenaListener
public void onCreatureSpawn(CreatureSpawnEvent event)
{
if (!arena.inRegion(event.getLocation()) || event.getSpawnReason() == SpawnReason.CUSTOM)
if (!arena.inRegion(event.getLocation())) // || event.getSpawnReason() == SpawnReason.CUSTOM)
return;
// If running == true, setCancelled(false), and vice versa.
event.setCancelled(!arena.running);
}
public void onEntityExplode(EntityExplodeEvent event)
{
if (!arena.monsters.contains(event.getEntity()) && !arena.inRegionRadius(event.getLocation(), 10))
@ -124,6 +144,71 @@ public class MAListener implements ArenaListener
event.setYield(0);
arena.monsters.remove(event.getEntity());
// Cancel if the arena isn't running or if the repair delay is 0
if (!arena.running || arena.repairDelay == 0)
{
event.setCancelled(true);
return;
}
// Uncancel, just in case.
event.setCancelled(false);
// Initialize the repair list.
final List<Repairable> toRepair = new LinkedList<Repairable>();
// Handle all the blocks in the block list.
for (Block b : event.blockList())
{
BlockState state = b.getState();
// Create a Repairable from the block.
Repairable r = null;
if (state instanceof ContainerBlock)
r = new RepairableContainer(state);
else if (state instanceof Sign)
r = new RepairableSign(state);
else
r = new RepairableBlock(state);
Material mat = state.getType();
if (mat == Material.WOODEN_DOOR || mat == Material.IRON_DOOR_BLOCK || mat == Material.FIRE || mat == Material.CAKE_BLOCK || mat == Material.WATER || mat == Material.LAVA)
arena.blocks.remove(b);
else if (arena.blocks.remove(b))
arena.world.dropItemNaturally(b.getLocation(), new ItemStack(state.getTypeId(), 1));
else if (arena.softRestore)
arena.repairables.add(r);
else
toRepair.add(r);
}
// If the arena isn't protected, or soft-restore is on, return.
if (!arena.protect || arena.softRestore)
return;
// Otherwise, schedule repairs!
Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(plugin,
new Runnable()
{
public void run()
{
Collections.sort(toRepair, new RepairableComparator());
for (Repairable r : toRepair)
r.repair();
}
}, arena.repairDelay);
}
/*
public void onEntityExplodez(EntityExplodeEvent event)
{
if (!arena.monsters.contains(event.getEntity()) && !arena.inRegionRadius(event.getLocation(), 10))
return;
event.setYield(0);
arena.monsters.remove(event.getEntity());
// If the arena isn't running
if (!arena.running || arena.repairDelay == 0)
{
@ -143,7 +228,7 @@ public class MAListener implements ArenaListener
// Uncancel, just in case.
event.setCancelled(false);
int[] buffer;
final HashMap<Block,Integer> blockMap = new HashMap<Block,Integer>();
for (Block b : event.blockList())
@ -186,6 +271,7 @@ public class MAListener implements ArenaListener
{
public void run()
{
long start = System.nanoTime();
for (Map.Entry<Block,Integer> entry : blockMap.entrySet())
{
Block b = entry.getKey();
@ -196,9 +282,11 @@ public class MAListener implements ArenaListener
if (type > 1000)
b.getLocation().getBlock().setData((byte) (type / 1000));
}
System.out.println("Repair took: " + (System.nanoTime() - start) + " ns");
}
}, arena.repairDelay);
}
*/
public void onEntityDeath(EntityDeathEvent event)
{
@ -394,20 +482,38 @@ public class MAListener implements ArenaListener
public void onPlayerDropItem(PlayerDropItemEvent event)
{
if (arena.running && arena.shareInArena) return;
Player p = event.getPlayer();
if (p.getLocation().equals(arena.spectatorLoc))
// Player is in the lobby
if (arena.lobbyPlayers.contains(p))
{
event.getItemDrop().setItemStack(new ItemStack(1, 0));
MAUtils.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
event.setCancelled(true);
}
if (!arena.arenaPlayers.contains(p) && !arena.lobbyPlayers.contains(p))
return;
// Player is in the arena
else if (arena.arenaPlayers.contains(p))
{
if (!arena.shareInArena)
{
MAUtils.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
event.setCancelled(true);
}
}
MAUtils.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
event.setCancelled(true);
// Player died/left
else if (p.getLocation().equals(arena.spectatorLoc) || p.getLocation().equals(arena.locations.get(p)))
{
MobArena.warning("Player '" + p.getName() + "' tried to steal item " + event.getItemDrop().getItemStack().getType());
event.getItemDrop().remove();
}
// Player is in the spectator area
else if (arena.specPlayers.contains(p))
{
MAUtils.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
event.setCancelled(true);
}
}
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event)

View File

@ -476,7 +476,8 @@ public class MAUtils
// If these are rewards, don't tamper with them.
if (rewards)
{
inv.addItem(stack);
//inv.addItem(stack);
giveItem(inv, stack);
continue;
}
@ -491,19 +492,36 @@ public class MAUtils
if (WEAPONS_TYPE.contains(stack.getType()))
stack.setDurability((short) -32768);
inv.addItem(stack);
giveItem(inv, stack);
//inv.addItem(stack);
}
}
public static void giveRewards(Player p, List<ItemStack> stacks, MobArena plugin)
{
giveItems(p, stacks, false, true, plugin);
}
public static void giveItems(Player p, List<ItemStack> stacks, boolean autoEquip, MobArena plugin)
{
giveItems(p, stacks, autoEquip, false, plugin);
}
public static void giveItem(PlayerInventory inv, ItemStack stack)
{
int id = stack.getTypeId();
int amount = stack.getAmount();
int times = amount / 64;
int remainder = amount % 64;
for (int i = 0; i < times; i++)
inv.addItem(new ItemStack(id, 64));
if (remainder > 0)
inv.addItem(new ItemStack(id, remainder));
}
public static void giveRewards(Player p, List<ItemStack> stacks, MobArena plugin)
{
giveItems(p, stacks, false, true, plugin);
}
public static int getPetAmount(Player p)
{
int result = 0;

View File

@ -1,6 +1,7 @@
package com.garbagemule.MobArena;
import java.io.File;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
@ -40,6 +41,7 @@ public class MobArena extends JavaPlugin
// Global variables
public static PluginDescriptionFile desc;
public static File dir, arenaDir;
public static List<String> permissionOps;
public static final double MIN_PLAYER_DISTANCE = 256.0;
public static final int ECONOMY_MONEY_ID = -29;
@ -60,7 +62,6 @@ public class MobArena extends JavaPlugin
FileUtils.fetchLibs(config);
// Set up permissions and economy
//setupSuperPerms();
setupPermissions();
setupRegister();
@ -85,7 +86,6 @@ public class MobArena extends JavaPlugin
am.arenaMap.clear();
// Permissions & Economy
//permissionHandler = null;
if (Methods != null && Methods.hasMethod())
{
Methods = null;
@ -136,14 +136,13 @@ public class MobArena extends JavaPlugin
pm.registerEvent(Event.Type.ENTITY_COMBUST, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_TARGET, entityListener, Priority.Normal, this);
pm.registerEvent(Event.Type.CREATURE_SPAWN, entityListener, Priority.Highest, this);
pm.registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, playerListener, Priority.Monitor, this);
pm.registerEvent(Event.Type.PLAYER_COMMAND_PREPROCESS, playerListener, Priority.Monitor, this); // I know Monitor is bad, but other plugins suck! :(
}
// Permissions stuff
public boolean has(Player p, String s)
{
//return (permissionHandler == null || permissionHandler.has(p, s));
return hasSuperPerms(p, s) || hasNijikoPerms(p, s);
return hasSuperPerms(p, s) || hasNijikoPerms(p, s) || hasOpPerms(p, s);
}
public boolean hasSuperPerms(Player p, String s)
@ -156,19 +155,16 @@ public class MobArena extends JavaPlugin
return permissionHandler != null && permissionHandler.has(p, s);
}
public boolean hasOpPerms (Player p, String node)
{
return permissionOps == null || permissionOps.contains(node) == false || p.isOp();
}
// Console printing
public static void info(String msg) { Bukkit.getServer().getLogger().info("[MobArena] " + msg); }
public static void warning(String msg) { Bukkit.getServer().getLogger().warning("[MobArena] " + msg); }
public static void error(String msg) { Bukkit.getServer().getLogger().severe("[MobArena] " + msg); }
/*
private void setupSuperPerms()
{
getServer().getPluginManager().addPermission(new Permission("mobarena.classes"));
getServer().getPluginManager().addPermission(new Permission("mobarena.arenas"));
}
*/
private void setupPermissions()
{
if (permissionHandler != null)

View File

@ -0,0 +1,21 @@
package com.garbagemule.MobArena.repairable;
//import java.io.Serializable;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockState;
public interface Repairable// extends Serializable
{
public void repair();
public BlockState getState();
public World getWorld();
public Material getType();
public int getId();
public byte getData();
public int getX();
public int getY();
public int getZ();
}

View File

@ -0,0 +1,112 @@
package com.garbagemule.MobArena.repairable;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.BlockState;
public class RepairableBlock implements Repairable
{
private BlockState state;
private World world;
private int id, x, y, z;
private Material type;
private byte data;
public RepairableBlock(BlockState state)
{
this.state = state;
world = state.getWorld();
x = state.getX();
y = state.getY();
z = state.getZ();
id = state.getTypeId();
type = state.getType();
data = state.getRawData();
}
/**
* Repairs the block by setting the type and data
*/
public void repair()
{
getWorld().getBlockAt(x,y,z).setTypeIdAndData(id, data, false);
}
public BlockState getState()
{
return state;
}
public World getWorld()
{
return world;
}
public void setWorld(World world)
{
this.world = world;
}
public Material getType()
{
return type;
}
public void setType(Material type)
{
this.type = type;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public byte getData()
{
return data;
}
public void setData(byte data)
{
this.data = data;
}
public int getX()
{
return x;
}
public void setX(int x)
{
this.x = x;
}
public int getY()
{
return y;
}
public void setY(int y)
{
this.y = y;
}
public int getZ()
{
return z;
}
public void setZ(int z)
{
this.z = z;
}
}

View File

@ -0,0 +1,31 @@
package com.garbagemule.MobArena.repairable;
import java.util.Comparator;
import org.bukkit.material.Attachable;
import org.bukkit.material.Door;
import org.bukkit.material.MaterialData;
import org.bukkit.material.Redstone;
public class RepairableComparator implements Comparator<Repairable>
{
public int compare(Repairable r1, Repairable r2)
{
if (restoreLast(r1))
{
if (restoreLast(r2))
return 0;
return 1;
}
else if (restoreLast(r2))
return -1;
return 0;
}
private boolean restoreLast(Repairable r)
{
MaterialData m = r.getState().getData();
return (m instanceof Attachable || m instanceof Redstone || m instanceof Door);
}
}

View File

@ -0,0 +1,31 @@
package com.garbagemule.MobArena.repairable;
import org.bukkit.block.BlockState;
import org.bukkit.block.ContainerBlock;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public class RepairableContainer extends RepairableBlock
{
private ItemStack[] contents;
public RepairableContainer(BlockState state)
{
super(state);
Inventory inv = ((ContainerBlock) state).getInventory();
contents = inv.getContents();
inv.clear();
}
/**
* Repairs the container block by adding all the contents back in.
*/
public void repair()
{
super.repair();
ContainerBlock cb = (ContainerBlock) getWorld().getBlockAt(getX(),getY(),getZ()).getState();
cb.getInventory().setContents(contents);
}
}

View File

@ -0,0 +1,32 @@
package com.garbagemule.MobArena.repairable;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
public class RepairableSign extends RepairableBlock
{
private String[] lines = new String[4];
public RepairableSign(BlockState state)
{
super(state);
Sign s = (Sign) state;
lines = s.getLines();
}
/**
* Repairs the sign block by restoring all the lines
*/
public void repair()
{
super.repair();
Sign s = (Sign) getWorld().getBlockAt(getX(),getY(),getZ()).getState();
s.setLine(0, lines[0]);
s.setLine(1, lines[1]);
s.setLine(2, lines[2]);
s.setLine(3, lines[3]);
}
}

View File

@ -123,7 +123,7 @@ public interface Wave
{
public void run(final Arena arena, LivingEntity boss)
{
System.out.println("Intimidate target");
System.out.println("Root target");
final LivingEntity target = getTarget(boss);
if (target == null) return;