mirror of
https://github.com/TotalFreedomMC/TF-ProjectKorra.git
synced 2025-02-11 11:40:40 +00:00
Merge pull request #91 from nathank33/master
Performance Block Cache, AirBlast bug fix, Lightning Water Arc Fix
This commit is contained in:
commit
36df22c107
7 changed files with 177 additions and 25 deletions
|
@ -77,6 +77,7 @@ public class ConfigManager {
|
|||
config.addDefault("Properties.RegionProtection.RespectTowny", true);
|
||||
config.addDefault("Properties.RegionProtection.RespectPreciousStones", true);
|
||||
config.addDefault("Properties.RegionProtection.RespectLWC", true);
|
||||
config.addDefault("Properties.RegionProtection.CacheBlockTime", 5000);
|
||||
|
||||
config.addDefault("Properties.TagAPI.Enabled", true);
|
||||
|
||||
|
@ -307,6 +308,7 @@ public class ConfigManager {
|
|||
+ "Additionally, you can click while channeling to attack things near you, dealing damage and knocking them back. "
|
||||
+ "Releasing shift at any time will dissipate the form.");
|
||||
config.addDefault("Abilities.Water.OctopusForm.Range", 10);
|
||||
config.addDefault("Abilities.Water.OctopusForm.AttackRange", 2.5);
|
||||
config.addDefault("Abilities.Water.OctopusForm.Radius", 3);
|
||||
config.addDefault("Abilities.Water.OctopusForm.Damage", 3);
|
||||
config.addDefault("Abilities.Water.OctopusForm.Knockback", 1.75);
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Collection;
|
|||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
@ -43,6 +44,7 @@ import org.bukkit.World.Environment;
|
|||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.FallingSand;
|
||||
|
@ -55,6 +57,7 @@ import org.bukkit.inventory.ItemStack;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.griefcraft.lwc.LWC;
|
||||
|
@ -143,14 +146,18 @@ import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
|
|||
public class Methods {
|
||||
|
||||
static ProjectKorra plugin;
|
||||
private static FileConfiguration config = ProjectKorra.plugin.getConfig();
|
||||
|
||||
public static Random rand = new Random();
|
||||
public static double CACHE_TIME = config.getDouble("Properties.RegionProtection.CacheBlockTime");
|
||||
|
||||
private static final ItemStack pickaxe = new ItemStack(Material.DIAMOND_PICKAXE);
|
||||
|
||||
public static ConcurrentHashMap<Block, Information> movedearth = new ConcurrentHashMap<Block, Information>();
|
||||
public static ConcurrentHashMap<Integer, Information> tempair = new ConcurrentHashMap<Integer, Information>();
|
||||
public static ConcurrentHashMap<String, Long> cooldowns = new ConcurrentHashMap<String, Long>();
|
||||
// Represents PlayerName, previously checked blocks, and whether they were true or false
|
||||
public static ConcurrentHashMap<String, ConcurrentHashMap<Block, BlockCacheElement>> blockProtectionCache = new ConcurrentHashMap<String, ConcurrentHashMap<Block, BlockCacheElement>>();
|
||||
public static ArrayList<Block> tempnophysics = new ArrayList<Block>();
|
||||
public static HashSet<Block> tempNoEarthbending = new HashSet<Block>();
|
||||
private static Integer[] plantIds = { 6, 18, 31, 32, 37, 38, 39, 40, 59, 81, 83, 86, 99, 100, 103, 104, 105, 106, 111, 161, 175};
|
||||
|
@ -1096,7 +1103,7 @@ public class Methods {
|
|||
return 1;
|
||||
}
|
||||
} else {
|
||||
Bukkit.getServer().broadcastMessage("RPG NOT DETECTED");
|
||||
//Bukkit.getServer().broadcastMessage("RPG NOT DETECTED");
|
||||
|
||||
if (isNight(world) && BendingManager.events.get(world).equalsIgnoreCase("FullMoon")) return plugin.getConfig().getDouble("Properties.Water.FullMoonFactor");
|
||||
if (isNight(world)) return plugin.getConfig().getDouble("Properties.Water.NightFactor");
|
||||
|
@ -1437,7 +1444,27 @@ public class Methods {
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* isRegionProtectedFromBuild is one of the most server intensive methods in the
|
||||
* plugin. It uses a blockCache that keeps track of recent blocks that may have already been checked.
|
||||
* Abilities like TremorSense call this ability 5 times per tick even though it only needs to check a single block,
|
||||
* instead of doing all 5 of those checks this method will now look in the map first.
|
||||
*/
|
||||
public static boolean isRegionProtectedFromBuild(Player player, String ability, Location loc) {
|
||||
if(!blockProtectionCache.containsKey(player.getName()))
|
||||
blockProtectionCache.put(player.getName(), new ConcurrentHashMap<Block, BlockCacheElement>());
|
||||
|
||||
ConcurrentHashMap<Block, BlockCacheElement> blockMap = blockProtectionCache.get(player.getName());
|
||||
Block block = loc.getBlock();
|
||||
if(blockMap.containsKey(block))
|
||||
return blockMap.get(block).isAllowed();
|
||||
|
||||
boolean value = isRegionProtectedFromBuildPostCache(player, ability, loc);
|
||||
blockMap.put(block, new BlockCacheElement(player, block, value, System.currentTimeMillis()));
|
||||
return value;
|
||||
}
|
||||
|
||||
private static boolean isRegionProtectedFromBuildPostCache(Player player, String ability, Location loc) {
|
||||
|
||||
boolean allowharmless = plugin.getConfig().getBoolean("Properties.RegionProtection.AllowHarmlessAbilities");
|
||||
boolean respectWorldGuard = plugin.getConfig().getBoolean("Properties.RegionProtection.RespectWorldGuard");
|
||||
|
@ -2638,8 +2665,69 @@ public class Methods {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static class BlockCacheElement {
|
||||
private Player player;
|
||||
private Block block;
|
||||
private boolean allowed;
|
||||
private long time;
|
||||
|
||||
public BlockCacheElement(Player player, Block block, boolean allowed, long time) {
|
||||
this.player = player;
|
||||
this.block = block;
|
||||
this.allowed = allowed;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public void setPlayer(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public Block getBlock() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public void setBlock(Block block) {
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public boolean isAllowed() {
|
||||
return allowed;
|
||||
}
|
||||
|
||||
public void setAllowed(boolean allowed) {
|
||||
this.allowed = allowed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void startCacheCleaner(final double period) {
|
||||
new BukkitRunnable() {
|
||||
public void run() {
|
||||
for(ConcurrentHashMap<Block, BlockCacheElement> map : blockProtectionCache.values()) {
|
||||
for(Iterator<Block> i = map.keySet().iterator(); i.hasNext();) {
|
||||
Block key = i.next();
|
||||
BlockCacheElement value = map.get(key);
|
||||
|
||||
if(System.currentTimeMillis() - value.getTime() > period) {
|
||||
map.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.runTaskTimer(ProjectKorra.plugin, 0, (long) (period / 20));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public class ProjectKorra extends JavaPlugin {
|
|||
}
|
||||
|
||||
Methods.deserializeFile();
|
||||
|
||||
Methods.startCacheCleaner(Methods.CACHE_TIME);
|
||||
new CraftingRecipes(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package com.projectkorra.ProjectKorra.airbending;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Effect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
@ -191,7 +193,14 @@ public class AirBlast {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (location.distance(origin) > range) {
|
||||
/*
|
||||
* If a player presses shift and AirBlasts straight down then
|
||||
* the AirBlast's location gets messed up and reading the distance
|
||||
* returns Double.NaN. If we don't remove this instance then
|
||||
* the AirBlast will never be removed.
|
||||
*/
|
||||
double dist = location.distance(origin);
|
||||
if (Double.isNaN(dist) || dist > range) {
|
||||
instances.remove(id);
|
||||
return false;
|
||||
}
|
||||
|
@ -255,6 +264,9 @@ public class AirBlast {
|
|||
if (Commands.invincible.contains(((Player) entity).getName())) return;
|
||||
}
|
||||
|
||||
if(Double.isNaN(velocity.length()))
|
||||
return;
|
||||
|
||||
Methods.setVelocity(entity, velocity);
|
||||
entity.setFallDistance(0);
|
||||
if (!isUser && entity instanceof Player) {
|
||||
|
|
|
@ -2,12 +2,14 @@ package com.projectkorra.ProjectKorra.firebending;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -57,6 +59,7 @@ public class Lightning {
|
|||
private ArrayList<Entity> affectedEntities = new ArrayList<Entity>();
|
||||
private ArrayList<Arc> arcs = new ArrayList<Arc>();
|
||||
private ArrayList<BukkitRunnable> tasks = new ArrayList<BukkitRunnable>();
|
||||
private HashMap<Block, Boolean> isTransparentCache = new HashMap<Block, Boolean>();
|
||||
|
||||
public Lightning(Player player) {
|
||||
this.player = player;
|
||||
|
@ -162,17 +165,13 @@ public class Lightning {
|
|||
for(int j = 0; j < arc.getAnimLocs().size() - 1; j++) {
|
||||
final Location iterLoc = arc.getAnimLocs().get(j).getLoc().clone();
|
||||
final Location dest = arc.getAnimLocs().get(j + 1).getLoc().clone();
|
||||
|
||||
if(!isTransparent(player, iterLoc.getBlock())) {
|
||||
if(SELF_HIT_CLOSE && player.getLocation().distance(iterLoc) < 3) {
|
||||
if(!affectedEntities.contains(player)) {
|
||||
if(SELF_HIT_CLOSE
|
||||
&& player.getLocation().distance(iterLoc) < 3
|
||||
&& !isTransparent(player, iterLoc.getBlock())
|
||||
&& !affectedEntities.contains(player)) {
|
||||
affectedEntities.add(player);
|
||||
electrocute(player);
|
||||
}
|
||||
}
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
|
||||
while(iterLoc.distance(dest) > 0.15) {
|
||||
BukkitRunnable task = new LightningParticle(arc, iterLoc.clone());
|
||||
|
@ -192,15 +191,23 @@ public class Lightning {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isTransparent(Player player, Block block) {
|
||||
public boolean isTransparent(Player player, Block block) {
|
||||
if(isTransparentCache.containsKey(block))
|
||||
return isTransparentCache.get(block);
|
||||
|
||||
boolean value = false;
|
||||
if (Arrays.asList(Methods.transparentToEarthbending).contains(block.getTypeId())) {
|
||||
if(Methods.isRegionProtectedFromBuild(player, "Lightning", block.getLocation()))
|
||||
return false;
|
||||
value = false;
|
||||
else if(isIce(block.getLocation()))
|
||||
return ARC_ON_ICE;
|
||||
return true;
|
||||
value = ARC_ON_ICE;
|
||||
else
|
||||
value = true;
|
||||
}
|
||||
return false;
|
||||
else
|
||||
value = false;
|
||||
isTransparentCache.put(block, new Boolean(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
public void electrocute(LivingEntity lent) {
|
||||
|
@ -285,6 +292,8 @@ public class Lightning {
|
|||
public class Arc {
|
||||
private ArrayList<Location> points;
|
||||
private ArrayList<AnimLocation> animLocs;
|
||||
private ArrayList<LightningParticle> particles;
|
||||
private ArrayList<Arc> subArcs;
|
||||
private Vector direction;
|
||||
private int animCounter;
|
||||
|
||||
|
@ -293,6 +302,8 @@ public class Lightning {
|
|||
points.add(startPoint.clone());
|
||||
points.add(endPoint.clone());
|
||||
direction = Methods.getDirection(startPoint, endPoint);
|
||||
particles = new ArrayList<LightningParticle>();
|
||||
subArcs = new ArrayList<Arc>();
|
||||
animLocs = new ArrayList<AnimLocation>();
|
||||
animCounter = 0;
|
||||
}
|
||||
|
@ -329,6 +340,7 @@ public class Lightning {
|
|||
double randRange = (Math.random() * range) + (range / 3.0);
|
||||
Location loc2 = loc.clone().add(dir.normalize().multiply(randRange));
|
||||
Arc arc = new Arc(loc, loc2);
|
||||
subArcs.add(arc);
|
||||
arc.setAnimCounter(animLocs.get(i).getAnimCounter());
|
||||
arc.generatePoints(POINT_GENERATION);
|
||||
arcs.add(arc);
|
||||
|
@ -338,6 +350,16 @@ public class Lightning {
|
|||
return arcs;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
for(int i = 0; i < particles.size(); i++) {
|
||||
particles.get(i).cancel();
|
||||
}
|
||||
|
||||
for(Arc subArc : subArcs) {
|
||||
subArc.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<Location> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
@ -369,6 +391,15 @@ public class Lightning {
|
|||
public void setAnimLocs(ArrayList<AnimLocation> animLocs) {
|
||||
this.animLocs = animLocs;
|
||||
}
|
||||
|
||||
public ArrayList<LightningParticle> getParticles() {
|
||||
return particles;
|
||||
}
|
||||
|
||||
public void setParticles(ArrayList<LightningParticle> particles) {
|
||||
this.particles = particles;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AnimLocation {
|
||||
|
@ -405,6 +436,7 @@ public class Lightning {
|
|||
public LightningParticle(Arc arc, Location loc) {
|
||||
this.arc = arc;
|
||||
this.loc = loc;
|
||||
arc.particles.add(this);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
|
@ -418,6 +450,10 @@ public class Lightning {
|
|||
if(count > 5)
|
||||
this.cancel();
|
||||
else if(count == 1) {
|
||||
if(!isTransparent(player, loc.getBlock())) {
|
||||
arc.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Water electrocution
|
||||
if(!hitWater && (isWater(loc) || (ARC_ON_ICE && isIce(loc)))) {
|
||||
|
|
|
@ -22,6 +22,7 @@ public class OctopusForm {
|
|||
public static ConcurrentHashMap<Player, OctopusForm> instances = new ConcurrentHashMap<Player, OctopusForm>();
|
||||
|
||||
private static int RANGE = ProjectKorra.plugin.getConfig().getInt("Abilities.Water.OctopusForm.Range");
|
||||
private static double ATTACK_RANGE = ProjectKorra.plugin.getConfig().getInt("Abilities.Water.OctopusForm.AttackRange");
|
||||
private static int DAMAGE = ProjectKorra.plugin.getConfig().getInt("Abilities.Water.OctopusForm.Damage");
|
||||
private static long INTERVAL = ProjectKorra.plugin.getConfig().getLong("Abilities.Water.OctopusForm.FormDelay");
|
||||
private static double KNOCKBACK = ProjectKorra.plugin.getConfig().getDouble("Abilities.Water.OctopusForm.Knockback");
|
||||
|
@ -46,6 +47,7 @@ public class OctopusForm {
|
|||
private boolean forming = false;
|
||||
private boolean formed = false;
|
||||
private int range = RANGE;
|
||||
private double attackRange = ATTACK_RANGE;
|
||||
private int damage = DAMAGE;
|
||||
private long interval = INTERVAL;
|
||||
private double knockback = KNOCKBACK;
|
||||
|
@ -128,7 +130,7 @@ public class OctopusForm {
|
|||
}
|
||||
|
||||
private void affect(Location location) {
|
||||
for (Entity entity : Methods.getEntitiesAroundPoint(location, range)) {
|
||||
for (Entity entity : Methods.getEntitiesAroundPoint(location, attackRange)) {
|
||||
if (entity.getEntityId() == player.getEntityId())
|
||||
continue;
|
||||
if (Methods.isRegionProtectedFromBuild(player, "OctopusForm", entity.getLocation()))
|
||||
|
@ -500,4 +502,14 @@ public class OctopusForm {
|
|||
this.radius = radius;
|
||||
}
|
||||
|
||||
public double getAttackRange() {
|
||||
return attackRange;
|
||||
}
|
||||
|
||||
public void setAttackRange(double attackRange) {
|
||||
this.attackRange = attackRange;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ Properties:
|
|||
RespectTowny: true
|
||||
RespectPreciousStones: true
|
||||
RespectLWC: true
|
||||
CacheBlockTime: 5000
|
||||
Air:
|
||||
CanBendWithWeapons: false
|
||||
Particles: smoke
|
||||
|
@ -233,6 +234,7 @@ Abilities:
|
|||
Enabled: true
|
||||
Description: "This ability allows the waterbender to manipulate a large quantity of water into a form resembling that of an octopus. To use, click to select a water source. Then, hold sneak to channel this ability. While channleing, the water will form itself around you and has a chance to block incoming attacks. Additionally, you can click while channeling to attack things near you, dealing damage and knocking the target back. Releasing shift at any time will dissipate the form."
|
||||
Range: 10
|
||||
AttackRange: 2.5
|
||||
Damage: 3
|
||||
Radius: 3
|
||||
FormDelay: 50
|
||||
|
|
Loading…
Reference in a new issue