Skip to content
This repository has been archived by the owner on Dec 7, 2022. It is now read-only.

Commit

Permalink
Implement renewables
Browse files Browse the repository at this point in the history
  • Loading branch information
Pablete1234 committed Jun 25, 2016
1 parent 17d97ae commit e923dd2
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/main/java/in/twizmwaz/cardinal/module/ModuleFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import in.twizmwaz.cardinal.module.modules.rage.RageBuilder;
import in.twizmwaz.cardinal.module.modules.rank.RankModuleBuilder;
import in.twizmwaz.cardinal.module.modules.regions.RegionModuleBuilder;
import in.twizmwaz.cardinal.module.modules.renewables.RenewablesBuilder;
import in.twizmwaz.cardinal.module.modules.respawn.RespawnModuleBuilder;
import in.twizmwaz.cardinal.module.modules.score.ScoreModuleBuilder;
import in.twizmwaz.cardinal.module.modules.scoreboard.ScoreboardModuleBuilder;
Expand Down Expand Up @@ -185,7 +186,8 @@ private void addBuilders() {
PostBuilder.class,
FlagBuilder.class,
NetBuilder.class,
StatsBuilder.class
StatsBuilder.class,
RenewablesBuilder.class
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import in.twizmwaz.cardinal.module.modules.filter.parsers.BlockFilterParser;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.material.MaterialData;

import static in.twizmwaz.cardinal.module.modules.filter.FilterState.ABSTAIN;
import static in.twizmwaz.cardinal.module.modules.filter.FilterState.ALLOW;
Expand All @@ -23,7 +24,6 @@ public BlockFilter(final BlockFilterParser parser) {

@Override
public FilterState evaluate(final Object... objects) {

for (Object object : objects) {
if (object instanceof Block) {
if (((Block) object).getType().equals(material) && (damageValue == -1 || (int) ((Block) object).getState().getData().getData() == damageValue))
Expand All @@ -33,6 +33,10 @@ public FilterState evaluate(final Object... objects) {
if ((object).equals(material))
return ALLOW;
else return DENY;
} else if (object instanceof MaterialData) {
if (((MaterialData) object).getItemType().equals(material) && (damageValue == -1 || (int) ((MaterialData) object).getData() == damageValue))
return ALLOW;
else return DENY;
}
}
return (getParent() == null ? ABSTAIN : getParent().evaluate(objects));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
package in.twizmwaz.cardinal.module.modules.renewables;

import com.google.common.collect.Lists;
import in.twizmwaz.cardinal.Cardinal;
import in.twizmwaz.cardinal.GameHandler;
import in.twizmwaz.cardinal.event.MatchEndEvent;
import in.twizmwaz.cardinal.module.TaskedModule;
import in.twizmwaz.cardinal.module.modules.filter.FilterModule;
import in.twizmwaz.cardinal.module.modules.filter.FilterState;
import in.twizmwaz.cardinal.module.modules.regions.RegionModule;
import in.twizmwaz.cardinal.module.modules.team.TeamModule;
import in.twizmwaz.cardinal.util.Teams;
import net.minecraft.server.SoundCategory;
import net.minecraft.server.SoundEffectType;
import net.minecraft.server.World;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import org.bukkit.event.player.PlayerBucketFillEvent;
import org.bukkit.material.MaterialData;
import org.bukkit.util.BlockVector;
import org.bukkit.util.Vector;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class Renewable implements TaskedModule {

private RegionModule region;
private FilterModule renewFilter;
private FilterModule replaceFilter;
private FilterModule shuffleFilter;
private RenewMode mode;
private double ratePerTick;
private double intervalTicks;
private boolean grow;
private boolean particles;
private boolean sound;
private int avoidPlayers;

private Random random = new Random();
private double renewals;

private Map<BlockVector, MaterialData> blocks = new HashMap<>();
private List<BlockVector> toRenew = Lists.newArrayList();
private List<Integer> tasks = Lists.newArrayList();

private static BlockFace[] faces = {BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN};

Renewable(RegionModule region,
FilterModule renewFilter,
FilterModule replaceFilter,
FilterModule shuffleFilter,
double rate,
double interval,
boolean grow,
boolean particles,
boolean sound,
int avoidPlayers) {
this.region = region;
this.renewFilter = renewFilter;
this.replaceFilter = replaceFilter;
this.shuffleFilter = shuffleFilter;
this.mode = interval < 0 ? RenewMode.RATE : RenewMode.INTERVAL;
this.intervalTicks = (int) interval * 20;
this.ratePerTick = rate / 20;
this.grow = grow;
this.particles = particles;
this.sound = sound;
this.avoidPlayers = avoidPlayers * avoidPlayers;
}

@Override
public void unload() {
HandlerList.unregisterAll(this);
}

@Override
public void run() {
if (GameHandler.getGameHandler().getMatch().isRunning() && mode.equals(RenewMode.RATE)) {
renewals += ratePerTick;

int fails = 0, maxFails = 5 + (toRenew.size() / 4);

while(fails < maxFails && toRenew.size() > 0 && renewals > 1) {
BlockVector loc = toRenew.get(random.nextInt(toRenew.size()));

Boolean renew = attemptRenew(loc);
if (renew != null) {
if (renew) renewals--;
else fails++;
}

}
if (renewals > 1) renewals -= (int) renewals;
}
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
editedBlock(event.getBlock().getLocation(), event.getBlock().getState().getMaterialData());
}


@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event) {
editedBlock(event.getBlock().getLocation(), event.getBlockReplacedState().getMaterialData());
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBucketFill(PlayerBucketFillEvent event) {
editedBlock(event.getBlockClicked().getLocation(), event.getBlockClicked().getState().getMaterialData());
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
Block relative = event.getBlockClicked().getRelative(event.getBlockFace());
editedBlock(relative.getLocation(), relative.getState().getMaterialData());
}

@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBlow(EntityExplodeEvent event) {
for (Block block : event.blockList()) {
editedBlock(block.getLocation(), block.getState().getMaterialData());
}
}

@EventHandler
public void onMatchEnd(MatchEndEvent event) {
for (int id : tasks) {
Bukkit.getScheduler().cancelTask(id);
}
tasks.clear();
}

public void stopTask(int id) {
Bukkit.getScheduler().cancelTask(id);
tasks.remove((Integer) id);
}

private void editedBlock(Vector loc, MaterialData save) {
if (isInRegion(loc)) {
BlockVector block = loc.toBlockVector();
if (!blocks.containsKey(block)) {
blocks.put(block, save);
}
if (!toRenew.contains(block) && renewFilter.evaluate(save).equals(FilterState.ALLOW)) {
toRenew.add(block);
if (mode.equals(RenewMode.INTERVAL)) {
RenewRunnable renewRunnable = new RenewRunnable(this, block);
int taskId = Bukkit.getScheduler().scheduleSyncRepeatingTask(Cardinal.getInstance(), renewRunnable, (long) intervalTicks, (long) intervalTicks);
renewRunnable.setTask(taskId);
tasks.add(taskId);
}
}
}
}

public Boolean attemptRenew(BlockVector loc) {
Block block = loc.toLocation(GameHandler.getGameHandler().getMatchWorld()).getBlock();

if (isRenewed(block)) {
toRenew.remove(loc);
return null;
} else if (canRenew(block)) {
resetBlock(block);
toRenew.remove(loc);
return true;
} else {
return false;
}
}

private void resetBlock(Block block) {
MaterialData original = blocks.get(block.getLocation().toBlockVector());

block.setTypeIdAndData(original.getItemTypeId(), original.getData(), true);

World nmsWorld = ((CraftWorld) GameHandler.getGameHandler().getMatchWorld()).getHandle();
if (sound) {
SoundEffectType sound = CraftMagicNumbers.getBlock(original.getItemType()).getSoundEffects();
nmsWorld.playSoundEffect(null, block.getX(), block.getY(), block.getZ(), sound.breakSound(), SoundCategory.BLOCKS, sound.b(), sound.a());
}
/*if (particles) {
PacketPlayOutWorldParticles packet = new PacketPlayOutWorldParticles(EnumParticle.ITEM_CRACK, true, (float)block.getX(), (float)block.getY(), (float)block.getZ(), 0.15f, 24.0f, 0.15f, 0.0f, 40, 35, (int)color.getWoolData());
PacketUtils.broadcastPacket(packet);
}*/
}

private boolean hasAdjacentBlocks(Block block) {
for (BlockFace face : faces) {
Block relative = block.getRelative(face);
if (!relative.getType().equals(Material.AIR) && isRenewed(relative)) return true;
}
return false;
}

private boolean isRenewed(Block block) {
if (!isInRegion(block.getLocation())) return false;
BlockVector loc = block.getLocation().toBlockVector();
if (!blocks.containsKey(loc)) {
return true;
} else if (shuffleFilter.evaluate(blocks.get(loc)).equals(FilterState.ALLOW)) {
return shuffleFilter.evaluate(block).equals(FilterState.ALLOW);
} else {
return blocks.get(loc).equals(block.getState().getMaterialData());
}
}

public boolean canRenew(Block block) {
BlockVector pos = block.getLocation().toVector().toBlockVector();

if(isInRegion(pos) && blocks.containsKey(pos) && !blocks.get(pos).getItemType().equals(Material.AIR)
&& replaceFilter.evaluate(block).equals(FilterState.ALLOW) && (!grow || hasAdjacentBlocks(block))) {
if (avoidPlayers != 0) {
for (TeamModule team : Teams.getTeams()) {
if (team.isObserver()) continue;
for (Player player : (List<Player>) team) {
if (player.getLocation().plus(0, 0.5, 0).distanceSquared(block.getLocation().plus(0.5, 0.5, 0.5)) < avoidPlayers) {
return false;
}
}
}
}
return true;
}
return false;
}

private boolean isInRegion(Vector pos) {
Vector vec = new Vector(pos.getBlockX() + 0.5, pos.getBlockY() + 0.5, pos.getBlockZ() + 0.5);
return region.contains(vec);
}

enum RenewMode {
RATE(),
INTERVAL();
}

private class RenewRunnable implements Runnable {

private Renewable renewable;
private BlockVector toRenew;
private int taskId;

public RenewRunnable(Renewable renewable, BlockVector block) {
this.renewable = renewable;
this.toRenew = block;
}

public void setTask(int taskId) {
this.taskId = taskId;
}

@Override
public void run() {
Boolean renew = renewable.attemptRenew(toRenew);
if (renew == null || renew) {
renewable.stopTask(taskId);
}
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package in.twizmwaz.cardinal.module.modules.renewables;

import in.twizmwaz.cardinal.match.Match;
import in.twizmwaz.cardinal.module.ModuleBuilder;
import in.twizmwaz.cardinal.module.ModuleCollection;
import in.twizmwaz.cardinal.module.modules.filter.FilterModule;
import in.twizmwaz.cardinal.module.modules.filter.FilterModuleBuilder;
import in.twizmwaz.cardinal.module.modules.filter.parsers.BlockFilterParser;
import in.twizmwaz.cardinal.module.modules.filter.type.BlockFilter;
import in.twizmwaz.cardinal.module.modules.regions.RegionModule;
import in.twizmwaz.cardinal.module.modules.regions.RegionModuleBuilder;
import in.twizmwaz.cardinal.util.Numbers;
import in.twizmwaz.cardinal.util.Parser;
import in.twizmwaz.cardinal.util.Proto;
import in.twizmwaz.cardinal.util.Strings;
import org.bukkit.Bukkit;
import org.jdom2.Element;

public class RenewablesBuilder implements ModuleBuilder {

@Override
public ModuleCollection<Renewable> load(Match match) {
ModuleCollection<Renewable> results = new ModuleCollection<>();
for (Element renewables : match.getDocument().getRootElement().getChildren("renewables")) {
for (Element renewable : renewables.getChildren("renewable")) {
results.add(getRenewable(match.getProto(), renewable, renewables));
}
for (Element renewables2 : renewables.getChildren("renewables")) {
for (Element renewable : renewables2.getChildren("renewable")) {
results.add(getRenewable(match.getProto(), renewable, renewables2, renewable));
}
}
}
return results;
}

private Renewable getRenewable(Proto proto, Element... elements) {
RegionModule region = RegionModuleBuilder.getAttributeOrChild("region", elements);

FilterModule renewFilter, replaceFilter, shuffleFilter;

if (proto.greaterOrEqualTo(Proto.parseProto("1.4.0"))) {
Bukkit.broadcastMessage("Proto 1.4");
renewFilter = FilterModuleBuilder.getAttributeOrChild("renew-filter", "always", elements);
replaceFilter = FilterModuleBuilder.getAttributeOrChild("replace-filter", "always", elements);
shuffleFilter = FilterModuleBuilder.getAttributeOrChild("shuffle-filter", "never", elements);
} else {
Bukkit.broadcastMessage("Proto <1.4");
renewFilter = new BlockFilter(new BlockFilterParser(elements[0].getChild("renew")));
replaceFilter = new BlockFilter(new BlockFilterParser(elements[0].getChild("replace")));
shuffleFilter = FilterModuleBuilder.getAttributeOrChild("shuffle", "never", elements);
}

double rate = Numbers.parseDouble(Parser.getOrderedAttribute("rate", elements), 1);
double interval = Strings.timeStringToExactSeconds(Strings.fallback(Parser.getOrderedAttribute("interval", elements), "-1s"));

boolean grow = Numbers.parseBoolean(Parser.getOrderedAttribute("grow", elements), true);
boolean particles = Numbers.parseBoolean(Parser.getOrderedAttribute("particles", elements), true);
boolean sound = Numbers.parseBoolean(Parser.getOrderedAttribute("sound", elements), true);
int avoidPlayers = Numbers.parseInt(Parser.getOrderedAttribute("avoid-players", elements), 2);

return new Renewable(region, renewFilter, replaceFilter, shuffleFilter, rate, interval, grow, particles, sound, avoidPlayers);
}

}
5 changes: 5 additions & 0 deletions src/main/java/in/twizmwaz/cardinal/util/Strings.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,9 @@ public static String getCurrentChatColor(String str, int index) {
}
return color;
}

public static String fallback(String string, String fallback) {
return string == null ? fallback : string;
}

}

0 comments on commit e923dd2

Please sign in to comment.