first commit
This commit is contained in:
commit
90b5d50841
|
@ -0,0 +1,29 @@
|
|||
#----------------------------------
|
||||
# EntityTrackerFixer
|
||||
#
|
||||
# By: Esmorall
|
||||
#
|
||||
#----------------------------------
|
||||
|
||||
#Log when the plugin untrack entities
|
||||
log-to-console: true
|
||||
|
||||
#How many ticks between untrack process
|
||||
#The untrack process will check for untracked entities by players but still by the server, and untrack them.
|
||||
untrack-ticks: 1000
|
||||
|
||||
#if tps are not below this value, the task will not perform the untrack and it will wait for the next run
|
||||
tps-limit: 18.5
|
||||
|
||||
#frecuency in ticks to check untracked entities
|
||||
#It will check for players traking entities and will track it again (this is to prevent invisible entities)
|
||||
check-untracked-entities-frequency: 60
|
||||
|
||||
#Distance in blocks to check for players near untracked entities
|
||||
tracking-range: 25
|
||||
|
||||
#which worlds do you want the plugin to take effect?
|
||||
worlds:
|
||||
- world
|
||||
- world_nether
|
||||
- world_the_end
|
|
@ -0,0 +1,6 @@
|
|||
name: EntityTrackerFixer
|
||||
main: net.minemora.entitytrackerfixer.EntityTrackerFixer
|
||||
version: 1.0.8
|
||||
api-version: 1.14
|
||||
author: Esmorall
|
||||
commands:
|
|
@ -0,0 +1,104 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.minecraft.server.v1_14_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_14_R1.WorldServer;
|
||||
import net.minemora.entitytrackerfixer.config.ConfigMain;
|
||||
import net.minemora.entitytrackerfixer.util.Util;
|
||||
|
||||
public class CheckTask extends BukkitRunnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(UntrackerTask.isRunning()) {
|
||||
return;
|
||||
}
|
||||
for(String worldName : ConfigMain.getWorlds()) {
|
||||
if(Bukkit.getWorld(worldName) == null) {
|
||||
continue;
|
||||
}
|
||||
if(UntrackedEntitiesCache.getInstance().isEmpty(worldName)) {
|
||||
continue;
|
||||
}
|
||||
checkWorld(worldName);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkWorld(String worldName) {
|
||||
WorldServer ws = ((CraftWorld)Bukkit.getWorld(worldName)).getHandle();
|
||||
ChunkProviderServer cps = ws.getChunkProvider();
|
||||
|
||||
Set<UntrackedEntity> toRemove = new HashSet<>();
|
||||
Set<net.minecraft.server.v1_14_R1.Entity> trackAgain = new HashSet<>();
|
||||
|
||||
Iterator<UntrackedEntity> it = UntrackedEntitiesCache.getInstance().getCache(worldName).iterator();
|
||||
while (it.hasNext()) {
|
||||
UntrackedEntity ute = it.next();
|
||||
net.minecraft.server.v1_14_R1.Entity nmsEnt = ute.getEntity();
|
||||
if(cps.playerChunkMap.trackedEntities.containsKey(nmsEnt.getId())) {
|
||||
//System.out.println("removed (et contains): " + nmsEnt.getBukkitEntity().getType().name());
|
||||
toRemove.add(ute);
|
||||
continue;
|
||||
}
|
||||
World world = nmsEnt.getBukkitEntity().getWorld();
|
||||
Location loc = nmsEnt.getBukkitEntity().getLocation();
|
||||
if(!Util.isChunkLoaded(ws, loc.getBlockX() >> 4, loc.getBlockZ() >> 4)) {
|
||||
//System.out.println("removed (unloaded chunk x:"+(loc.getBlockX() >> 4)+" z:"+(loc.getBlockZ() >> 4)+"): " + nmsEnt.getBukkitEntity().getType().name());
|
||||
UntrackedEntitiesCache.getInstance().addUFC(worldName, nmsEnt.getId());
|
||||
toRemove.add(ute);
|
||||
continue;
|
||||
}
|
||||
if(!worldName.equals(world.getName())) {
|
||||
//System.out.println("removed (different world): " + nmsEnt.getBukkitEntity().getType().name());
|
||||
toRemove.add(ute);
|
||||
continue;
|
||||
}
|
||||
if(nmsEnt.getBukkitEntity().isDead()) {
|
||||
//System.out.println("removed (is dead): " + nmsEnt.getBukkitEntity().getType().name());
|
||||
toRemove.add(ute);
|
||||
continue;
|
||||
}
|
||||
boolean track = false;
|
||||
int d = ConfigMain.getTrackingRange();
|
||||
List<Entity> ents = nmsEnt.getBukkitEntity().getNearbyEntities(d, d, d);
|
||||
if(ents.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
for(Entity le : ents) {
|
||||
if(le == null) {
|
||||
continue;
|
||||
}
|
||||
if(le instanceof Player) {
|
||||
track = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(track) {
|
||||
//System.out.println("tracked again: " + nmsEnt.getBukkitEntity().getType().name());
|
||||
trackAgain.add(nmsEnt);
|
||||
}
|
||||
}
|
||||
|
||||
UntrackedEntitiesCache.getInstance().removeAll(toRemove, worldName);
|
||||
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NMSEntityTracker.trackEntities(cps, trackAgain);
|
||||
}
|
||||
}.runTask(EntityTrackerFixer.plugin);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import net.minemora.entitytrackerfixer.config.ConfigMain;
|
||||
import net.minemora.entitytrackerfixer.listener.ChunkEventListener;
|
||||
|
||||
public class EntityTrackerFixer extends JavaPlugin {
|
||||
|
||||
public static EntityTrackerFixer plugin;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
plugin = this;
|
||||
ConfigMain.getInstance().setup(this);
|
||||
new UntrackerTask().runTaskTimerAsynchronously(this, ConfigMain.getUntrackTicks(), ConfigMain.getUntrackTicks());
|
||||
new CheckTask().runTaskTimerAsynchronously(this, ConfigMain.getUntrackTicks() + 1, ConfigMain.getCheckFrequency());
|
||||
getServer().getPluginManager().registerEvents(new ChunkEventListener(), this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.server.v1_14_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_14_R1.PlayerChunkMap;
|
||||
import net.minemora.entitytrackerfixer.util.ReflectionUtils;
|
||||
|
||||
public final class NMSEntityTracker {
|
||||
|
||||
private NMSEntityTracker() {}
|
||||
|
||||
public static void trackEntities(ChunkProviderServer cps, Set<net.minecraft.server.v1_14_R1.Entity> trackList) {
|
||||
try {
|
||||
Method method = ReflectionUtils.getPrivateMethod(PlayerChunkMap.class, "addEntity",
|
||||
new Class[] {net.minecraft.server.v1_14_R1.Entity.class});
|
||||
for(net.minecraft.server.v1_14_R1.Entity entity : trackList) {
|
||||
if(cps.playerChunkMap.trackedEntities.containsKey(entity.getId())) {
|
||||
continue;
|
||||
}
|
||||
method.invoke(cps.playerChunkMap, entity);
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException
|
||||
| IllegalArgumentException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void untrackEntities(ChunkProviderServer cps, Set<net.minecraft.server.v1_14_R1.Entity> untrackList) {
|
||||
try {
|
||||
Method method = ReflectionUtils.getPrivateMethod(PlayerChunkMap.class, "removeEntity",
|
||||
new Class[] {net.minecraft.server.v1_14_R1.Entity.class});
|
||||
for(net.minecraft.server.v1_14_R1.Entity entity : untrackList) {
|
||||
method.invoke(cps.playerChunkMap, entity);
|
||||
}
|
||||
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class TrackedWorld {
|
||||
|
||||
private final String worldName;
|
||||
private Set<UntrackedEntity> cache = ConcurrentHashMap.newKeySet();
|
||||
private Set<Integer> unloadedFromChunkCache = ConcurrentHashMap.newKeySet();
|
||||
|
||||
public TrackedWorld(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
public void add(net.minecraft.server.v1_14_R1.Entity entity) {
|
||||
cache.add(new UntrackedEntity(entity));
|
||||
}
|
||||
|
||||
public void remove(UntrackedEntity ute) {
|
||||
cache.remove(ute);
|
||||
}
|
||||
|
||||
public void removeAll(Set<UntrackedEntity> toRemove) {
|
||||
cache.removeAll(toRemove);
|
||||
}
|
||||
|
||||
public boolean isEmpty(String worldName) {
|
||||
return cache.isEmpty();
|
||||
}
|
||||
|
||||
public Set<UntrackedEntity> getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public void addUFC(int i) {
|
||||
unloadedFromChunkCache.add(i);
|
||||
}
|
||||
|
||||
public void removeUFC(int i) {
|
||||
unloadedFromChunkCache.remove(i);
|
||||
}
|
||||
|
||||
public boolean containsUFC(int i) {
|
||||
return unloadedFromChunkCache.contains(i);
|
||||
}
|
||||
|
||||
public Set<Integer> getUnloadedFromChunkCache() {
|
||||
return unloadedFromChunkCache;
|
||||
}
|
||||
|
||||
public String getWorldName() {
|
||||
return worldName;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.minemora.entitytrackerfixer.config.ConfigMain;
|
||||
|
||||
public final class UntrackedEntitiesCache {
|
||||
|
||||
private static UntrackedEntitiesCache instance;
|
||||
|
||||
private Map<String,TrackedWorld> trackedWorlds = new ConcurrentHashMap<>();
|
||||
|
||||
private UntrackedEntitiesCache() {
|
||||
for(String worldName : ConfigMain.getWorlds()) {
|
||||
trackedWorlds.put(worldName, new TrackedWorld(worldName));
|
||||
}
|
||||
}
|
||||
|
||||
public void add(net.minecraft.server.v1_14_R1.Entity entity) {
|
||||
String worldName = entity.getBukkitEntity().getWorld().getName();
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return;
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
tw.add(entity);
|
||||
}
|
||||
|
||||
public void remove(UntrackedEntity ute) {
|
||||
String worldName = ute.getEntity().getBukkitEntity().getWorld().getName();
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return;
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
tw.remove(ute);
|
||||
}
|
||||
|
||||
public void removeAll(Set<UntrackedEntity> toRemove, String worldName) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return;
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
tw.removeAll(toRemove);
|
||||
}
|
||||
|
||||
public boolean isEmpty(String worldName) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return true;
|
||||
}
|
||||
return getCache(worldName).isEmpty();
|
||||
}
|
||||
|
||||
public Set<UntrackedEntity> getCache(String worldName) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return new HashSet<UntrackedEntity>();
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
return tw.getCache();
|
||||
}
|
||||
|
||||
public void addUFC(String worldName, int i) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return;
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
tw.addUFC(i);
|
||||
}
|
||||
|
||||
public void removeUFC(String worldName, int i) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return;
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
tw.removeUFC(i);
|
||||
}
|
||||
|
||||
public boolean containsUFC(String worldName, int i) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return true;
|
||||
}
|
||||
return getUnloadedFromChunkCache(worldName).contains(i);
|
||||
}
|
||||
|
||||
public Set<Integer> getUnloadedFromChunkCache(String worldName) {
|
||||
if(!trackedWorlds.containsKey(worldName)) {
|
||||
return new HashSet<Integer>();
|
||||
}
|
||||
TrackedWorld tw = trackedWorlds.get(worldName);
|
||||
return tw.getUnloadedFromChunkCache();
|
||||
}
|
||||
|
||||
public static UntrackedEntitiesCache getInstance() {
|
||||
if(instance == null) {
|
||||
instance = new UntrackedEntitiesCache();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Map<String,TrackedWorld> getTrackedWorlds() {
|
||||
return trackedWorlds;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
public class UntrackedEntity {
|
||||
|
||||
private final net.minecraft.server.v1_14_R1.Entity entity;
|
||||
private final int id;
|
||||
|
||||
public UntrackedEntity(net.minecraft.server.v1_14_R1.Entity entity) {
|
||||
this.entity = entity;
|
||||
this.id = entity.getId();
|
||||
}
|
||||
|
||||
public net.minecraft.server.v1_14_R1.Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if ((o instanceof UntrackedEntity) && (((UntrackedEntity) o).getId() == this.id)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package net.minemora.entitytrackerfixer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import net.minecraft.server.v1_14_R1.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_14_R1.EntityPlayer;
|
||||
import net.minecraft.server.v1_14_R1.MinecraftServer;
|
||||
import net.minecraft.server.v1_14_R1.WorldServer;
|
||||
import net.minecraft.server.v1_14_R1.PlayerChunkMap.EntityTracker;
|
||||
import net.minemora.entitytrackerfixer.config.ConfigMain;
|
||||
import net.minemora.entitytrackerfixer.util.ReflectionUtils;
|
||||
import net.minemora.entitytrackerfixer.util.Util;
|
||||
|
||||
public class UntrackerTask extends BukkitRunnable {
|
||||
|
||||
private static boolean running = false;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void run() {
|
||||
if(MinecraftServer.getServer().recentTps[0] > ConfigMain.getMinTps()) {
|
||||
//String tps = String.format("%.2f", MinecraftServer.getServer().recentTps[0]);
|
||||
//EntityTrackerFixer.plugin.getLogger().info("Not untraking because tps = " + tps);
|
||||
return;
|
||||
}
|
||||
running = true;
|
||||
for(String worldName : ConfigMain.getWorlds()) {
|
||||
untrackProcess(worldName);
|
||||
}
|
||||
running = false;
|
||||
}
|
||||
|
||||
private void untrackProcess(String worldName) {
|
||||
if(Bukkit.getWorld(worldName) == null) {
|
||||
return;
|
||||
}
|
||||
//Set<net.minecraft.server.v1_14_R1.Entity> toRemove = new HashSet<>();
|
||||
int removed = 0;
|
||||
WorldServer ws = ((CraftWorld)Bukkit.getWorld(worldName)).getHandle();
|
||||
ChunkProviderServer cps = ws.getChunkProvider();
|
||||
@SuppressWarnings("rawtypes")
|
||||
ObjectIterator objectiterator = cps.playerChunkMap.trackedEntities.values().iterator();
|
||||
try {
|
||||
while (objectiterator.hasNext()) {
|
||||
Object iterobj = objectiterator.next();
|
||||
if(iterobj == null) {
|
||||
objectiterator.remove();
|
||||
continue;
|
||||
}
|
||||
EntityTracker et = (EntityTracker) iterobj;
|
||||
net.minecraft.server.v1_14_R1.Entity nmsEnt = (net.minecraft.server.v1_14_R1.Entity)
|
||||
ReflectionUtils.getPrivateField(et.getClass(), et, "tracker");
|
||||
if(nmsEnt instanceof EntityPlayer) {
|
||||
continue;
|
||||
}
|
||||
if(nmsEnt.getBukkitEntity().getCustomName() != null) {
|
||||
continue;
|
||||
}
|
||||
boolean remove = false;
|
||||
if(et.trackedPlayers.size() == 0) {
|
||||
remove = true;
|
||||
}
|
||||
else if(et.trackedPlayers.size() == 1) {
|
||||
for(EntityPlayer ep : et.trackedPlayers) {
|
||||
if(!ep.getBukkitEntity().isOnline()) {
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
if(!remove) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Location loc = nmsEnt.getBukkitEntity().getLocation();
|
||||
if(!Util.isChunkLoaded(ws, loc.getBlockX() >> 4, loc.getBlockZ() >> 4)) {
|
||||
UntrackedEntitiesCache.getInstance().addUFC(worldName, nmsEnt.getId());
|
||||
}
|
||||
if(remove) {
|
||||
//System.out.println("untracked: " + nmsEnt.getBukkitEntity().getType().name());
|
||||
//toRemove.add(nmsEnt);
|
||||
objectiterator.remove();
|
||||
removed++;
|
||||
UntrackedEntitiesCache.getInstance().add(nmsEnt);
|
||||
}
|
||||
}
|
||||
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
/*
|
||||
new BukkitRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NMSEntityTracker.untrackEntities(cps, toRemove);
|
||||
}
|
||||
}.runTask(EntityTrackerFixer.plugin);
|
||||
*/
|
||||
|
||||
if(ConfigMain.isLogToConsole()) {
|
||||
EntityTrackerFixer.plugin.getLogger().info("Untracked " + removed + " entities in " + worldName);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isRunning() {
|
||||
return running;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package net.minemora.entitytrackerfixer.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
|
||||
public abstract class Config {
|
||||
|
||||
protected File pdfile;
|
||||
protected FileConfiguration config;
|
||||
protected String fileName;
|
||||
|
||||
protected Config(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void setup(Plugin plugin) {
|
||||
if (!plugin.getDataFolder().exists()) {
|
||||
plugin.getDataFolder().mkdir();
|
||||
}
|
||||
pdfile = new File(plugin.getDataFolder(), fileName);
|
||||
boolean firstCreate = false;
|
||||
if (!pdfile.exists()) {
|
||||
firstCreate = true;
|
||||
try {
|
||||
pdfile.createNewFile();
|
||||
try (InputStream is = plugin.getResource(fileName);
|
||||
OutputStream os = new FileOutputStream(pdfile)) {
|
||||
ByteStreams.copy(is, os);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Unable to create the file: " + fileName, e);
|
||||
}
|
||||
}
|
||||
config = YamlConfiguration.loadConfiguration(pdfile);
|
||||
load(firstCreate);
|
||||
update();
|
||||
}
|
||||
|
||||
public abstract void load(boolean firstCreate);
|
||||
|
||||
public abstract void update();
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
config.save(pdfile);
|
||||
} catch (IOException e) {
|
||||
Bukkit.getServer().getLogger().severe("Could not save " + fileName + "!");
|
||||
}
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
config = YamlConfiguration.loadConfiguration(pdfile);
|
||||
}
|
||||
|
||||
public FileConfiguration getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package net.minemora.entitytrackerfixer.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
||||
public final class ConfigMain extends Config {
|
||||
|
||||
private static ConfigMain instance;
|
||||
|
||||
private static int untrackTicks;
|
||||
private static int checkFrequency;
|
||||
private static int trackingRange;
|
||||
private static double minTps;
|
||||
private static boolean logToConsole = true;
|
||||
private static List<String> worlds = new ArrayList<>();
|
||||
|
||||
private ConfigMain() {
|
||||
super("config.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(boolean firstCreate) {
|
||||
untrackTicks = getConfig().getInt("untrack-ticks", 1000);
|
||||
checkFrequency = getConfig().getInt("check-untracked-entities-frequency", 60);
|
||||
trackingRange = getConfig().getInt("tracking-range", 25);
|
||||
minTps = getConfig().getDouble("tps-limit", 18.5);
|
||||
worlds = getConfig().getStringList("worlds");
|
||||
logToConsole = getConfig().getBoolean("log-to-console", true);
|
||||
}
|
||||
|
||||
public static FileConfiguration get() {
|
||||
return getInstance().config;
|
||||
}
|
||||
|
||||
public static ConfigMain getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ConfigMain();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
return;
|
||||
}
|
||||
|
||||
public static int getUntrackTicks() {
|
||||
return untrackTicks;
|
||||
}
|
||||
|
||||
public static int getCheckFrequency() {
|
||||
return checkFrequency;
|
||||
}
|
||||
|
||||
public static double getMinTps() {
|
||||
return minTps;
|
||||
}
|
||||
|
||||
public static List<String> getWorlds() {
|
||||
return worlds;
|
||||
}
|
||||
|
||||
public static int getTrackingRange() {
|
||||
return trackingRange;
|
||||
}
|
||||
|
||||
public static boolean isLogToConsole() {
|
||||
return logToConsole;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package net.minemora.entitytrackerfixer.listener;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
|
||||
import net.minemora.entitytrackerfixer.UntrackedEntitiesCache;
|
||||
import net.minemora.entitytrackerfixer.config.ConfigMain;
|
||||
|
||||
public class ChunkEventListener implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
Chunk ch = event.getChunk();
|
||||
if(!ConfigMain.getWorlds().contains(ch.getWorld().getName())) {
|
||||
return;
|
||||
}
|
||||
for(Entity entity : ch.getEntities()) {
|
||||
if(UntrackedEntitiesCache.getInstance().containsUFC(ch.getWorld().getName(), entity.getEntityId())) {
|
||||
UntrackedEntitiesCache.getInstance().add(((CraftEntity)entity).getHandle());
|
||||
UntrackedEntitiesCache.getInstance().removeUFC(ch.getWorld().getName(), entity.getEntityId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package net.minemora.entitytrackerfixer.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class ReflectionUtils {
|
||||
|
||||
private ReflectionUtils() {}
|
||||
|
||||
public static Object getPrivateField(Class<? extends Object> clazz, Object obj, String fieldName)
|
||||
throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
|
||||
Field field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
Object ret = field.get(obj);
|
||||
field.setAccessible(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Object invokePrivateMethod(Class<? extends Object> clazz, Object obj, String methodName)
|
||||
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
return invokePrivateMethod(clazz, obj, methodName, new Class[0]);
|
||||
}
|
||||
|
||||
public static Object invokePrivateMethod(Class<? extends Object> clazz, Object obj, String methodName,
|
||||
@SuppressWarnings("rawtypes") Class[] params, Object... args)
|
||||
throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
Method method = getPrivateMethod(clazz, methodName, params);
|
||||
return method.invoke(obj, args);
|
||||
}
|
||||
|
||||
public static Method getPrivateMethod(Class<? extends Object> clazz, String methodName, @SuppressWarnings("rawtypes") Class[] params)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
Method method = clazz.getDeclaredMethod(methodName, params);
|
||||
method.setAccessible(true);
|
||||
return method;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package net.minemora.entitytrackerfixer.util;
|
||||
|
||||
import net.minecraft.server.v1_14_R1.WorldServer;
|
||||
|
||||
public final class Util {
|
||||
|
||||
private Util() {}
|
||||
|
||||
public static boolean isChunkLoaded(WorldServer ws, int x, int z) {
|
||||
net.minecraft.server.v1_14_R1.Chunk chunk = ws.getChunkProvider().getChunkAt(x, z, false);
|
||||
return chunk != null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue