Fix memory leak in carl, server
This commit is contained in:
parent
bd9aa38afa
commit
6f80e21372
@ -158,6 +158,7 @@ public class AnimationCarl extends Animation
|
||||
@Override
|
||||
protected void onFinish() {
|
||||
_isDone = true;
|
||||
_player = null;
|
||||
setTicks(0);
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,13 @@ import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import net.minecraft.server.v1_8_R3.CraftingManager;
|
||||
import net.minecraft.server.v1_8_R3.Enchantment;
|
||||
import net.minecraft.server.v1_8_R3.EnchantmentManager;
|
||||
import net.minecraft.server.v1_8_R3.EntityInsentient;
|
||||
import net.minecraft.server.v1_8_R3.IInventory;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.PathfinderGoal;
|
||||
import net.minecraft.server.v1_8_R3.PathfinderGoalNearestAttackableTarget;
|
||||
import net.minecraft.server.v1_8_R3.PathfinderGoalSelector;
|
||||
import net.minecraft.server.v1_8_R3.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
@ -22,7 +25,6 @@ import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByBlockEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
@ -52,8 +54,7 @@ public class MemoryFix extends MiniPlugin
|
||||
// Sanity check
|
||||
if (worlds.size() != worldList.size())
|
||||
throw new RuntimeException("Error: Duplicated worlds?!?!");
|
||||
|
||||
|
||||
|
||||
for (World world : worlds)
|
||||
{
|
||||
WorldServer worldServer = ((CraftWorld) world).getHandle();
|
||||
@ -96,15 +97,139 @@ public class MemoryFix extends MiniPlugin
|
||||
}
|
||||
}
|
||||
|
||||
private static Field PATHFINDER_GOAL_SELECTOR_B;
|
||||
private static boolean PATHFINDER_GOAL_SELECTOR_B_SUCCESSFUL;
|
||||
|
||||
private static Field PATHFINDER_GOAL_SELECTOR_C;
|
||||
private static boolean PATHFINDER_GOAL_SELECTOR_C_SUCCESSFUL;
|
||||
|
||||
private static Field PATHFINDER_GOAL_SELECTOR_ITEM_A;
|
||||
private static boolean PATHFINDER_GOAL_SELECTOR_ITEM_A_SUCCESSFUL;
|
||||
|
||||
private static Field PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D;
|
||||
private static boolean PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D_SUCCESSFUL;
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
PATHFINDER_GOAL_SELECTOR_ITEM_A = Class.forName(PathfinderGoalSelector.class.getName() + "$PathfinderGoalSelectorItem").getDeclaredField("a");
|
||||
PATHFINDER_GOAL_SELECTOR_ITEM_A.setAccessible(true);
|
||||
PATHFINDER_GOAL_SELECTOR_ITEM_A_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
try
|
||||
{
|
||||
PATHFINDER_GOAL_SELECTOR_B = PathfinderGoalSelector.class.getDeclaredField("b");
|
||||
PATHFINDER_GOAL_SELECTOR_B.setAccessible(true);
|
||||
PATHFINDER_GOAL_SELECTOR_B_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
try
|
||||
{
|
||||
PATHFINDER_GOAL_SELECTOR_C = PathfinderGoalSelector.class.getDeclaredField("c");
|
||||
PATHFINDER_GOAL_SELECTOR_C.setAccessible(true);
|
||||
PATHFINDER_GOAL_SELECTOR_C_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
try
|
||||
{
|
||||
PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D = PathfinderGoalNearestAttackableTarget.class.getDeclaredField("d");
|
||||
PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D.setAccessible(true);
|
||||
PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@EventHandler
|
||||
public void fixPathfinderGoalLeaks(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() != UpdateType.SLOW)
|
||||
return;
|
||||
|
||||
List<World> worldList = Bukkit.getWorlds();
|
||||
Set<World> worlds = new HashSet<>(worldList);
|
||||
|
||||
// Sanity check
|
||||
if (worlds.size() != worldList.size())
|
||||
throw new RuntimeException("Error: Duplicated worlds?!?!");
|
||||
|
||||
for (World world : worlds)
|
||||
{
|
||||
WorldServer worldServer = ((CraftWorld) world).getHandle();
|
||||
|
||||
for (net.minecraft.server.v1_8_R3.Entity nmsentity : worldServer.entityList)
|
||||
{
|
||||
if (nmsentity instanceof EntityInsentient)
|
||||
{
|
||||
EntityInsentient ei = (EntityInsentient) nmsentity;
|
||||
if (PATHFINDER_GOAL_SELECTOR_ITEM_A_SUCCESSFUL)
|
||||
{
|
||||
if (PATHFINDER_GOAL_SELECTOR_B_SUCCESSFUL)
|
||||
{
|
||||
try
|
||||
{
|
||||
PathfinderGoalSelector targetSelector = ei.targetSelector;
|
||||
List<Object> list = (List<Object>) PATHFINDER_GOAL_SELECTOR_B.get(targetSelector);
|
||||
for (Object object : list)
|
||||
{
|
||||
try
|
||||
{
|
||||
PathfinderGoal goal = (PathfinderGoal) PATHFINDER_GOAL_SELECTOR_ITEM_A.get(object);
|
||||
if (goal instanceof PathfinderGoalNearestAttackableTarget && PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D_SUCCESSFUL)
|
||||
{
|
||||
net.minecraft.server.v1_8_R3.Entity original = (net.minecraft.server.v1_8_R3.Entity) PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D.get(goal);
|
||||
boolean shouldClear = false;
|
||||
|
||||
if (original != null)
|
||||
{
|
||||
if (!original.valid)
|
||||
shouldClear = true;
|
||||
}
|
||||
|
||||
if (shouldClear)
|
||||
PATHFINDER_GOAL_NEAREST_ATTACKABLE_TARGET_D.set(goal, null);
|
||||
}
|
||||
}
|
||||
catch (ReflectiveOperationException ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Object ENCHANTMENTMANAGER_D;
|
||||
private static Field ENCHANTMENT_MODIFIER_THORNS_A;
|
||||
private static Field ENCHANTMENT_MODIFIER_THORNS_B;
|
||||
private static boolean ENCHANTMENTMANAGER_D_SUCCESFUL;
|
||||
private static boolean ENCHANTMENTMANAGER_D_SUCCESSFUL;
|
||||
|
||||
private static Object ENCHANTMENTMANAGER_E;
|
||||
private static Field ENCHANTMENT_MODIFIER_ARTHROPODS_A;
|
||||
private static Field ENCHANTMENT_MODIFIER_ARTHROPODS_B;
|
||||
private static boolean ENCHANTMENTMANAGER_E_SUCCESFUL;
|
||||
private static boolean ENCHANTMENTMANAGER_E_SUCCESSFUL;
|
||||
|
||||
static
|
||||
{
|
||||
@ -117,7 +242,7 @@ public class MemoryFix extends MiniPlugin
|
||||
ENCHANTMENT_MODIFIER_THORNS_A.setAccessible(true);
|
||||
ENCHANTMENT_MODIFIER_THORNS_B = ENCHANTMENTMANAGER_D.getClass().getDeclaredField("b");
|
||||
ENCHANTMENT_MODIFIER_THORNS_B.setAccessible(true);
|
||||
ENCHANTMENTMANAGER_D_SUCCESFUL = true;
|
||||
ENCHANTMENTMANAGER_D_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
@ -132,7 +257,7 @@ public class MemoryFix extends MiniPlugin
|
||||
ENCHANTMENT_MODIFIER_ARTHROPODS_A.setAccessible(true);
|
||||
ENCHANTMENT_MODIFIER_ARTHROPODS_B = ENCHANTMENTMANAGER_E.getClass().getDeclaredField("b");
|
||||
ENCHANTMENT_MODIFIER_ARTHROPODS_B.setAccessible(true);
|
||||
ENCHANTMENTMANAGER_E_SUCCESFUL = true;
|
||||
ENCHANTMENTMANAGER_E_SUCCESSFUL = true;
|
||||
}
|
||||
catch (ReflectiveOperationException e)
|
||||
{
|
||||
@ -146,7 +271,7 @@ public class MemoryFix extends MiniPlugin
|
||||
if (event.getType() != UpdateType.SLOW)
|
||||
return;
|
||||
|
||||
if (ENCHANTMENTMANAGER_D_SUCCESFUL)
|
||||
if (ENCHANTMENTMANAGER_D_SUCCESSFUL)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -165,7 +290,7 @@ public class MemoryFix extends MiniPlugin
|
||||
}
|
||||
}
|
||||
|
||||
if (ENCHANTMENTMANAGER_E_SUCCESFUL)
|
||||
if (ENCHANTMENTMANAGER_E_SUCCESSFUL)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user