Event auto starting, Terrain Finder, Scoreboard Tweaks, Event idle, other random tweaks

This commit is contained in:
Shaun Bennett 2015-06-22 20:34:13 -05:00
parent 71da87a5ae
commit 50ddd23251
11 changed files with 361 additions and 22 deletions

View File

@ -1,6 +1,5 @@
package mineplex.game.clans;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_7_R4.CraftWorld;
import org.bukkit.plugin.java.JavaPlugin;
@ -32,7 +31,6 @@ import mineplex.core.teleport.Teleport;
import mineplex.core.updater.FileUpdater;
import mineplex.core.updater.Updater;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.worldevent.WorldEventManager;
import mineplex.game.clans.items.GearManager;
import mineplex.game.clans.shop.building.BuildingShop;
import mineplex.game.clans.shop.pvp.PvpShop;
@ -43,7 +41,8 @@ public class Clans extends JavaPlugin
//Modules
private CoreClientManager _clientManager;
private DonationManager _donationManager;
private DonationManager _donationManager;
private ClansManager _clansManager;
@Override
@ -97,11 +96,11 @@ public class Clans extends JavaPlugin
new FriendManager(this, _clientManager, preferenceManager, portal);
new InventoryManager(this, _clientManager);
ClansManager clans = new ClansManager(this, serverStatusManager.getCurrentServerName(), _clientManager, _donationManager, blockRestore, teleport, webServerAddress);
_clansManager = new ClansManager(this, serverStatusManager.getCurrentServerName(), _clientManager, _donationManager, blockRestore, teleport, webServerAddress);
new Recipes(this);
new Farming(this);
new BuildingShop(clans, _clientManager, _donationManager);
new PvpShop(clans, _clientManager, _donationManager);
new BuildingShop(_clansManager, _clientManager, _donationManager);
new PvpShop(_clansManager, _clientManager, _donationManager);
// Disable spigot item merging
for (World world : getServer().getWorlds())
@ -119,4 +118,11 @@ public class Clans extends JavaPlugin
MinecraftServer.getServer().getPropertyManager().setProperty("debug", true);
}
@Override
public void onDisable()
{
// Need to notify WorldEventManager of server shutdown, this seemed like the only decent way to do it
_clansManager.onDisable();
}
}

View File

@ -586,4 +586,12 @@ public class ClansManager extends MiniClientPlugin<ClientClan> implements IRelat
{
return TIME_ZONE;
}
@Override
public void disable()
{
// Kind of confusing, Clans.java calls this so that we can pass the disable event to WorldEventManager
// This is so that we can prevent any permanent world changes with events
_worldEvent.onDisable();
}
}

View File

@ -36,8 +36,6 @@ public class ClansScoreboardManager extends MiniPlugin
ScoreboardData data = _scoreboardManager.getData("default", true);
data.writeEmpty();
data.writeElement(new ScoreboardElementClan(_clansManager));
data.writeEmpty();

View File

@ -1,7 +1,15 @@
package mineplex.game.clans.clans.worldevent;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.bukkit.Location;
import net.minecraft.server.v1_7_R4.World;
import mineplex.game.clans.clans.worldevent.event.WorldEvent;
import mineplex.game.clans.clans.worldevent.event.boss.slime.SlimeBoss;
import mineplex.game.clans.clans.worldevent.event.kinghill.KingHill;
@ -9,10 +17,17 @@ import mineplex.game.clans.clans.worldevent.event.kinghill.KingHill;
public class ConcreteWorldEventFactory implements WorldEventFactory
{
private WorldEventManager _eventManager;
private List<Class<? extends WorldEvent>> _eventClasses;
private Random _random;
public ConcreteWorldEventFactory(WorldEventManager eventManager)
{
_eventManager = eventManager;
_random = new Random();
_eventClasses = new ArrayList<Class<? extends WorldEvent>>();
_eventClasses.add(SlimeBoss.class);
_eventClasses.add(KingHill.class);
}
@Override
@ -20,10 +35,10 @@ public class ConcreteWorldEventFactory implements WorldEventFactory
{
if (name.equalsIgnoreCase("slime"))
{
return new SlimeBoss(_eventManager, _eventManager.getDamage(), location);
return new SlimeBoss(_eventManager, location);
} else if (name.equalsIgnoreCase("kinghill"))
{
return new KingHill(_eventManager, _eventManager.getDamage(), location);
return new KingHill(_eventManager, location);
}
else
{
@ -34,6 +49,18 @@ public class ConcreteWorldEventFactory implements WorldEventFactory
@Override
public WorldEvent random(Location location)
{
return null;
WorldEvent worldEvent = null;
Class<? extends WorldEvent> clazz = _eventClasses.get(_random.nextInt(_eventClasses.size()));
try
{
worldEvent = clazz.getConstructor(WorldEventManager.class, Location.class).newInstance(_eventManager, location);
}
catch (Exception e)
{
e.printStackTrace();
}
return worldEvent;
}
}

View File

@ -0,0 +1,179 @@
package mineplex.game.clans.clans.worldevent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilMath;
import mineplex.game.clans.clans.ClansManager;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
public class EventTerrainFinder
{
private WorldEventManager _eventManager;
private ClansManager _clansManager;
public EventTerrainFinder(WorldEventManager eventManager, ClansManager clansManager)
{
_eventManager = eventManager;
_clansManager = clansManager;
}
public double posNeg()
{
if (Math.random() > 0.5)
return -1;
return 1;
}
public Location findArea(World world, int size, int vert)
{
for (int i=0 ; i<20 ; i++)
{
int x = 0;
int z = 0;
//X Side
if (Math.random() > 0.5)
{
x = (int) (posNeg() * ((400 + size) + UtilMath.r(200 - (size*2))));
z = (int) (posNeg() * UtilMath.r(600 - size));
}
//Z Side
else
{
z = (int) (posNeg() * ((400 + size) + UtilMath.r(200 - (size*2))));
x = (int) (posNeg() * UtilMath.r(600 - size));
}
Location loc = UtilBlock.getHighest(world, x, z).getLocation();
int total = ((size*2)+1)*((size*2)+1);
int liquid = 0;
HashMap<Integer, Integer> heights = new HashMap<Integer, Integer>();
HashSet<Chunk> chunks = new HashSet<Chunk>();
boolean wilderness = true;
//Gather Data
for (x=-size ; x<=size && wilderness ; x++)
for (z=-size ; z<=size && wilderness ; z++)
{
Block block = UtilBlock.getHighest(world, loc.getBlockX()+x, loc.getBlockZ()+z);
if (!chunks.contains(block.getChunk()))
if (_clansManager.getClanUtility().isClaimed(block.getLocation()))
{
chunks.add(block.getChunk());
wilderness = false;
break;
}
//Liquid
if (block.getRelative(BlockFace.DOWN).isLiquid() || block.isLiquid())
liquid++;
//Height
int heightDiff = block.getY() - loc.getBlockY();
if (!heights.containsKey(heightDiff)) heights.put(heightDiff, 1);
else heights.put(heightDiff, heights.get(heightDiff) + 1);
}
if (!wilderness)
continue;
//Too Watery
if ((double)liquid/(double)total > 0.25)
continue;
//Too Height Variable
int withinHeight = 0;
for (int h=-vert ; h<=vert ; h++)
{
if (!heights.containsKey(h))
continue;
withinHeight += heights.get(h);
}
if ((double)withinHeight/(double)total < 0.9)
continue;
//Success
return loc;
}
return null;
}
public Location locateSpace(Location areaSource, int areaRadius, int xArea, int yArea, int zArea, boolean replaceBlocks, boolean aboveOther, Set<Block> otherBlock)
{
for (int i=0 ; i<20 ; i++)
{
int x = UtilMath.r(areaRadius*2) - areaRadius + areaSource.getBlockX();
int z = UtilMath.r(areaRadius*2) - areaRadius + areaSource.getBlockZ();
Block block = UtilBlock.getHighest(areaSource.getWorld(), x, z);
if (!aboveOther)
if (otherBlock.contains(block.getRelative(BlockFace.DOWN)))
continue;
boolean valid = true;
int overlaps = 0;
//Previous
for (x=-xArea ; x<=xArea ; x++)
{
for (z=-zArea ; z<=zArea ; z++)
{
for (int y=0 ; y<=yArea ; y++)
{
//Check Blocks
Block cur = areaSource.getWorld().getBlockAt(block.getX()+x, block.getY()+y, block.getZ()+z);
if (cur.getRelative(BlockFace.DOWN).isLiquid())
{
valid = false;
break;
}
if (otherBlock.contains(cur))
{
valid = false;
break;
}
//Check Area
if (!UtilBlock.airFoliage(cur))
overlaps += 1;
}
if (!valid)
break;
}
if (!valid)
break;
}
if (!replaceBlocks && overlaps > 0)
continue;
if (!valid)
continue;
return block.getLocation();
}
return null;
}
}

View File

@ -5,6 +5,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.bukkit.Bukkit;
@ -20,6 +21,9 @@ import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilWorld;
import mineplex.core.scoreboard.ScoreboardManager;
import mineplex.core.scoreboard.elements.ScoreboardElement;
import mineplex.core.updater.UpdateType;
@ -35,17 +39,26 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
private final WorldEventFactory _factory;
private final List<WorldEvent> _events;
private Random _random;
private ClansManager _clansManager;
private EventTerrainFinder _terrainFinder;
private DamageManager _damageManager;
private long _lastEventEnd;
private long _nextEventStart;
public WorldEventManager(JavaPlugin plugin, ClansManager clansManager, DamageManager damageManager)
{
super("World Event", plugin);
_random = new Random();
_terrainFinder = new EventTerrainFinder(this, clansManager);
_clansManager = clansManager;
_damageManager = damageManager;
_factory = new ConcreteWorldEventFactory(this);
_events = new LinkedList<WorldEvent>();
_lastEventEnd = System.currentTimeMillis();
_nextEventStart = System.currentTimeMillis() + 30000;
}
@Override
@ -63,6 +76,8 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
if (event.getType() != UpdateType.SEC)
return;
boolean removed = false;
Iterator<WorldEvent> iterator = _events.iterator();
while (iterator.hasNext())
{
@ -72,8 +87,44 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
worldEvent.cleanup();
HandlerList.unregisterAll(worldEvent);
iterator.remove();
removed = true;
_lastEventEnd = System.currentTimeMillis();
}
}
if (removed && _events.size() == 0)
{
_nextEventStart = generateNextEventTime();
}
}
@EventHandler
public void startEvent(UpdateEvent event)
{
if (event.getType() != UpdateType.SEC)
return;
if (_events.size() == 0 && System.currentTimeMillis() > _nextEventStart && UtilServer.getPlayers().length > 0)
{
Bukkit.broadcastMessage("Starting new event from random...");
startRandomEvent();
}
}
private void startRandomEvent()
{
Location location = _terrainFinder.findArea(Bukkit.getWorlds().get(0), 30, 30);
if (location != null)
{
WorldEvent event = _factory.random(location);
initializeEvent(event);
}
else
{
// Try again in 5 minutes
_nextEventStart = System.currentTimeMillis() + 300000;
}
}
private void initializeEvent(WorldEvent event)
@ -102,6 +153,8 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
HandlerList.unregisterAll(event);
iterator.remove();
}
_nextEventStart = generateNextEventTime();
}
public ClansManager getClans()
@ -120,19 +173,29 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
addCommand(new WorldEventCommand(this));
}
private long generateNextEventTime()
{
// 45 Minutes + 0 - 15 Minutes
long waitTime = 2700000L + _random.nextInt(900000);
return System.currentTimeMillis() + waitTime;
}
@Override
public ArrayList<String> getLines(ScoreboardManager manager, Player player)
{
ArrayList<String> output = new ArrayList<String>();
if (_events.size() > 0)
output.add(C.cAqua + C.Bold + "Event");
Iterator<WorldEvent> iterator = _events.iterator();
while (iterator.hasNext())
{
WorldEvent event = iterator.next();
Location eventLocation = event.getCenterLocation();
String locationString = eventLocation.getBlockX() + ", " + eventLocation.getBlockY() + ", " + eventLocation.getBlockZ();
output.add(C.cGreen + "Event: " + C.cWhite + event.getName());
output.add(C.cGreen + "Location: " + C.cWhite + locationString);
output.add(" " + C.cWhite + event.getName());
output.add(" " + C.cWhite + locationString);
ArrayList<String> scoreboardLines = event.getScoreboardLines();
if (scoreboardLines != null) output.addAll(event.getScoreboardLines());
@ -146,6 +209,7 @@ public class WorldEventManager extends MiniPlugin implements ScoreboardElement
@EventHandler
public void gear(PlayerCommandPreprocessEvent event)
{
// TODO: Remove
if (event.getMessage().equalsIgnoreCase("/dgear"))
{
PlayerInventory i = event.getPlayer().getInventory();

View File

@ -246,5 +246,7 @@ public abstract class EventCreature<T extends LivingEntity> implements Listener
updateEntityHealth();
applyDamage(event.GetDamage());
_event.updateLastActive();
}
}

View File

@ -26,6 +26,9 @@ import mineplex.minecraft.game.core.damage.DamageManager;
public abstract class WorldEvent implements Listener
{
// 20 Minutes
private static final int ACTIVE_TIMEOUT = 1200000;
private WorldEventManager _eventManager;
private DamageManager _damageManager;
@ -35,16 +38,17 @@ public abstract class WorldEvent implements Listener
private EventMap _map;
private Random _random;
private int _ticks;
private long _lastActive;
// Creatures
private List<EventCreature> _creatures;
// Block Restore
private HashMap<Block, BlockData> _blocks;
public WorldEvent(WorldEventManager eventManager, DamageManager damageManager, String name, Location cornerLocation)
public WorldEvent(WorldEventManager eventManager, String name, Location cornerLocation)
{
_eventManager = eventManager;
_damageManager = damageManager;
_damageManager = eventManager.getDamage();
_name = name;
_state = EventState.PREPARE;
@ -55,6 +59,7 @@ public abstract class WorldEvent implements Listener
_creatures = new ArrayList<EventCreature>();
_blocks = new HashMap<Block, BlockData>();
_lastActive = System.currentTimeMillis();
}
public final void start()
@ -176,6 +181,16 @@ public abstract class WorldEvent implements Listener
_blocks.clear();
}
public long getLastActive()
{
return _lastActive;
}
public void updateLastActive()
{
_lastActive = System.currentTimeMillis();
}
public void setMap(EventMap map, final Runnable onComplete)
{
_map = map;
@ -211,6 +226,11 @@ public abstract class WorldEvent implements Listener
return null;
}
public int getRandomRange(int min, int max)
{
return min + _random.nextInt(max - min);
}
@EventHandler
public void tick(UpdateEvent event)
{
@ -220,4 +240,15 @@ public abstract class WorldEvent implements Listener
_ticks++;
customTick();
}
@EventHandler
public void endInactive(UpdateEvent event)
{
if (event.getType() != UpdateType.SEC)
return;
long diff = System.currentTimeMillis() - getLastActive();
if (diff > ACTIVE_TIMEOUT)
setState(EventState.END);
}
}

View File

@ -23,9 +23,9 @@ public class SlimeBoss extends WorldEvent
private static final int MAX_SIZE = 10;
private static final int MIN_SIZE = 1;
public SlimeBoss(WorldEventManager eventManager, DamageManager damageManager, Location corner)
public SlimeBoss(WorldEventManager eventManager, Location corner)
{
super(eventManager, damageManager, "Slime King", corner);
super(eventManager, "Slime King", corner);
Schematic schematic = null;

View File

@ -95,7 +95,7 @@ public class RocketAbility extends SlimeAbility implements IThrown
private void fireRocket(Player target)
{
Location loc = getSlime().getEntity().getEyeLocation();
loc.add(loc.getDirection().normalize().multiply(2));
loc.add(UtilAlg.getTrajectory2d(loc, target.getLocation()).multiply(2));
Slime projectile = loc.getWorld().spawn(loc, Slime.class);
projectile.setSize(1);
_shots.add(new ShotData(projectile, target));

View File

@ -6,13 +6,16 @@ import java.util.HashMap;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import mineplex.core.common.data.BlockData;
import mineplex.core.common.schematic.SchematicRunnable;
import mineplex.core.common.util.C;
import mineplex.core.common.util.Callback;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.game.clans.clans.ClanInfo;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.worldevent.WorldEventManager;
@ -43,25 +46,26 @@ public class KingHill extends WorldEvent
private HashMap<ClanInfo, CaptureData> _scoreMap;
private HillData _hill;
private List<BlockData> _restoreData;
private long _nextLootDrop;
private int _lootDropCount;
public KingHill(WorldEventManager eventManager, DamageManager damageManager, Location centerLocation)
public KingHill(WorldEventManager eventManager, Location centerLocation)
{
super(eventManager, damageManager, "King of the Hill", centerLocation);
super(eventManager, "King of the Hill", centerLocation);
_clansManager = eventManager.getClans();
_scoreMap = new HashMap<ClanInfo, CaptureData>();
_hill = LOADED_HILLS.get(0);
_nextLootDrop = System.currentTimeMillis() + getRandomRange(300000, 600000);
}
@Override
protected void customStart()
{
Bukkit.broadcastMessage("attempting to spawn in hill... please wait!");
SchematicRunnable runnable = new SchematicRunnable(_clansManager.getPlugin(), _hill.getSchematic(), getCenterLocation().getBlock(), new Callback<List<BlockData>>()
{
@Override
public void run(List<BlockData> data)
{
System.out.println("CALLBACK");
setState(EventState.LIVE);
_restoreData = data;
}
@ -85,6 +89,16 @@ public class KingHill extends WorldEvent
if (getTicks() % 1 == 0)
tickHill();
if (System.currentTimeMillis() > _nextLootDrop)
{
// Drop Loot!
_lootDropCount++;
_nextLootDrop = System.currentTimeMillis() + getRandomRange(300000, 600000);
if (_lootDropCount >= 4)
setState(EventState.END);
}
}
private void tickHill()
@ -102,6 +116,8 @@ public class KingHill extends WorldEvent
clanCount++;
lastClan = playerClan;
}
updateLastActive();
}
}
@ -122,6 +138,14 @@ public class KingHill extends WorldEvent
}
}
@Override
public ArrayList<String> getScoreboardLines()
{
ArrayList<String> list = new ArrayList<String>(1);
list.add(" Loot in " + UtilTime.convertString(_nextLootDrop - System.currentTimeMillis(), 1, UtilTime.TimeUnit.FIT));
return list;
}
private static class CaptureData
{
public int TicksOnHill;