mirror of
https://github.com/Zrips/Jobs.git
synced 2024-11-25 20:16:13 +01:00
Optimizations
This commit is contained in:
parent
b6bf2ad4b6
commit
6fd4cc90cf
@ -20,6 +20,7 @@ package com.gamingmesh.jobs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -88,43 +89,34 @@ public class PermissionHandler {
|
||||
|
||||
for (JobConditions Condition : job.getConditions()) {
|
||||
boolean ok = true;
|
||||
for (String oneReq : Condition.getRequires()) {
|
||||
if (oneReq.toLowerCase().contains("j:")) {
|
||||
String jobName = oneReq.toLowerCase().replace("j:", "").split("-")[0];
|
||||
int jobLevel = Integer.valueOf(oneReq.toLowerCase().replace("j:", "").split("-")[1]);
|
||||
boolean found = false;
|
||||
for (JobProgression oneJob : jPlayer.getJobProgression()) {
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName))
|
||||
found = true;
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName) && oneJob.getLevel() < jobLevel) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
ok = false;
|
||||
}
|
||||
if (ok == false)
|
||||
for (String oneReq : Condition.getRequiredPerm()) {
|
||||
if (!player.hasPermission(oneReq)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (oneReq.toLowerCase().contains("p:")) {
|
||||
if (!player.hasPermission(oneReq.replace(":p", ""))) {
|
||||
for (Entry<String, Integer> oneReq : Condition.getRequiredJobs().entrySet()) {
|
||||
String jobName = oneReq.getKey();
|
||||
int jobLevel = oneReq.getValue();
|
||||
boolean found = false;
|
||||
for (JobProgression oneJob : jPlayer.getJobProgression()) {
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName))
|
||||
found = true;
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName) && oneJob.getLevel() < jobLevel) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
for (String one : Condition.getPerform()) {
|
||||
if (!one.toLowerCase().contains("p:"))
|
||||
continue;
|
||||
|
||||
String perm = one.toLowerCase().replace("p:", "").split("-")[0];
|
||||
boolean node = Boolean.getBoolean(one.toLowerCase().replace("p:", "").split("-")[1]);
|
||||
|
||||
for (Entry<String, Boolean> one : Condition.getPerformPerm().entrySet()) {
|
||||
String perm = one.getKey();
|
||||
boolean node = one.getValue();
|
||||
if (node) {
|
||||
permissions.put(perm, true);
|
||||
} else {
|
||||
@ -136,7 +128,6 @@ public class PermissionHandler {
|
||||
permissions.put(perm, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -162,43 +153,33 @@ public class PermissionHandler {
|
||||
|
||||
for (JobConditions Condition : prog.getJob().getConditions()) {
|
||||
boolean ok = true;
|
||||
for (String oneReq : Condition.getRequires()) {
|
||||
if (oneReq.toLowerCase().contains("j:")) {
|
||||
String jobName = oneReq.toLowerCase().replace("j:", "").split("-")[0];
|
||||
int jobLevel = Integer.valueOf(oneReq.toLowerCase().replace("j:", "").split("-")[1]);
|
||||
boolean found = false;
|
||||
for (JobProgression oneJob : jPlayer.getJobProgression()) {
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName))
|
||||
found = true;
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName) && oneJob.getLevel() < jobLevel) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
ok = false;
|
||||
|
||||
}
|
||||
if (ok == false)
|
||||
for (String oneReq : Condition.getRequiredPerm()) {
|
||||
if (!player.hasPermission(oneReq)) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (oneReq.toLowerCase().contains("p:")) {
|
||||
if (!player.hasPermission(oneReq.replace("p:", ""))) {
|
||||
for (Entry<String, Integer> oneReq : Condition.getRequiredJobs().entrySet()) {
|
||||
String jobName = oneReq.getKey();
|
||||
int jobLevel = oneReq.getValue();
|
||||
boolean found = false;
|
||||
for (JobProgression oneJob : jPlayer.getJobProgression()) {
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName))
|
||||
found = true;
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName) && oneJob.getLevel() < jobLevel) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
continue;
|
||||
for (String one : Condition.getPerform()) {
|
||||
if (!one.toLowerCase().contains("p:"))
|
||||
continue;
|
||||
String perm = one.toLowerCase().replace("p:", "").split("-")[0];
|
||||
String nodeString = one.toLowerCase().replace("p:", "").split("-")[1];
|
||||
boolean node = nodeString.equalsIgnoreCase("true") ? true : false;
|
||||
|
||||
for (Entry<String, Boolean> one : Condition.getPerformPerm().entrySet()) {
|
||||
String perm = one.getKey();
|
||||
boolean node = one.getValue();
|
||||
if (node) {
|
||||
permissions.put(perm, true);
|
||||
} else {
|
||||
|
@ -40,7 +40,6 @@ import com.gamingmesh.jobs.api.JobsLevelUpEvent;
|
||||
import com.gamingmesh.jobs.container.BoostMultiplier;
|
||||
import com.gamingmesh.jobs.container.Job;
|
||||
import com.gamingmesh.jobs.container.JobCommands;
|
||||
import com.gamingmesh.jobs.container.JobConditions;
|
||||
import com.gamingmesh.jobs.container.JobItems;
|
||||
import com.gamingmesh.jobs.container.JobProgression;
|
||||
import com.gamingmesh.jobs.container.JobsPlayer;
|
||||
@ -49,7 +48,6 @@ import com.gamingmesh.jobs.dao.JobsDAO;
|
||||
import com.gamingmesh.jobs.dao.JobsDAOData;
|
||||
import com.gamingmesh.jobs.economy.PointsData;
|
||||
import com.gamingmesh.jobs.stuff.ChatColor;
|
||||
import com.gamingmesh.jobs.stuff.Debug;
|
||||
import com.gamingmesh.jobs.stuff.PerformCommands;
|
||||
import com.gamingmesh.jobs.stuff.Perm;
|
||||
|
||||
@ -120,8 +118,8 @@ public class PlayerManager {
|
||||
JobsPlayer jPlayer = playersCache.get(player.getName().toLowerCase());
|
||||
if (jPlayer == null) {
|
||||
jPlayer = JobsPlayer.loadFromDao(Jobs.getJobsDAO(), player);
|
||||
|
||||
JobsPlayer.loadLogFromDao(jPlayer);
|
||||
if (player.hasPlayedBefore())
|
||||
JobsPlayer.loadLogFromDao(jPlayer);
|
||||
playersCache.put(player.getName().toLowerCase(), jPlayer);
|
||||
}
|
||||
|
||||
@ -527,56 +525,6 @@ public class PlayerManager {
|
||||
Jobs.getSignUtil().SignUpdate("gtoplist");
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs command on level up
|
||||
* @param jPlayer
|
||||
* @param job
|
||||
* @param oldLevel
|
||||
*/
|
||||
public void CheckConditions(JobsPlayer jPlayer, Job job) {
|
||||
Player player = Bukkit.getServer().getPlayer(jPlayer.getPlayerUUID());
|
||||
JobProgression prog = jPlayer.getJobProgression(job);
|
||||
if (prog == null)
|
||||
return;
|
||||
for (JobConditions Condition : job.getConditions()) {
|
||||
boolean ok = true;
|
||||
for (String oneReq : Condition.getRequires()) {
|
||||
if (oneReq.toLowerCase().contains("j:")) {
|
||||
String jobName = oneReq.toLowerCase().replace("j:", "").split("-")[0];
|
||||
int jobLevel = Integer.valueOf(oneReq.toLowerCase().replace("j:", "").split("-")[1]);
|
||||
boolean found = false;
|
||||
for (JobProgression oneJob : jPlayer.getJobProgression()) {
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName))
|
||||
found = true;
|
||||
if (oneJob.getJob().getName().equalsIgnoreCase(jobName) && oneJob.getLevel() != jobLevel) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
ok = false;
|
||||
}
|
||||
if (ok = false)
|
||||
break;
|
||||
|
||||
if (oneReq.toLowerCase().contains("p:")) {
|
||||
if (!player.hasPermission(oneReq.replace(":p", ""))) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
for (String one : Condition.getPerform()) {
|
||||
if (one.toLowerCase().contains("c:")) {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), one.replace("c:", "").replace("[name]", jPlayer.getUserName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs command on level up
|
||||
* @param jPlayer
|
||||
|
@ -501,25 +501,42 @@ public class ConfigManager {
|
||||
Jobs.getGCManager().setBreederFinder(true);
|
||||
}
|
||||
|
||||
// Just to recognize wither skeleton
|
||||
if (key.equalsIgnoreCase("WitherSkeleton")) {
|
||||
type = "WitherSkeleton";
|
||||
switch (key.toLowerCase()) {
|
||||
case "skeletonwither":
|
||||
type = "SkeletonWither";
|
||||
id = 51;
|
||||
meta = "1";
|
||||
}
|
||||
|
||||
// Just to recognize Zombie Villager
|
||||
if (key.equalsIgnoreCase("ZombieVillager")) {
|
||||
break;
|
||||
case "skeletonstray":
|
||||
type = "SkeletonStray";
|
||||
id = 51;
|
||||
meta = "2";
|
||||
break;
|
||||
case "zombievillager":
|
||||
type = "ZombieVillager";
|
||||
id = 54;
|
||||
meta = "1";
|
||||
}
|
||||
|
||||
// Just to recognize Elder Guardian
|
||||
if (key.equalsIgnoreCase("ElderGuardian")) {
|
||||
type = "ElderGuardian";
|
||||
break;
|
||||
case "zombiehusk":
|
||||
type = "ZombieHusk";
|
||||
id = 54;
|
||||
meta = "2";
|
||||
break;
|
||||
case "horseskeleton":
|
||||
type = "HorseSkeleton";
|
||||
id = 100;
|
||||
meta = "1";
|
||||
break;
|
||||
case "horsezombie":
|
||||
type = "HorseZombie";
|
||||
id = 100;
|
||||
meta = "2";
|
||||
break;
|
||||
case "guardianelder":
|
||||
type = "GuardianElder";
|
||||
id = 68;
|
||||
meta = "1";
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (actionType == ActionType.ENCHANT && material == null) {
|
||||
|
Binary file not shown.
@ -18,28 +18,56 @@
|
||||
|
||||
package com.gamingmesh.jobs.container;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class JobConditions {
|
||||
private String node;
|
||||
private List<String> requires;
|
||||
private List<String> perform;
|
||||
private List<String> requiresPerm = new ArrayList<String>();
|
||||
private HashMap<String, Integer> requiresJobs = new HashMap<String, Integer>();
|
||||
private HashMap<String, Boolean> performPerm = new HashMap<String, Boolean>();
|
||||
|
||||
public JobConditions(String node, List<String> requires, List<String> perform) {
|
||||
this.node = node;
|
||||
this.requires = requires;
|
||||
this.perform = perform;
|
||||
|
||||
for (String one : requires) {
|
||||
if (one.toLowerCase().contains("j:")) {
|
||||
String jobName = one.toLowerCase().replace("j:", "").split("-")[0];
|
||||
int jobLevel = 0;
|
||||
try {
|
||||
jobLevel = Integer.valueOf(one.toLowerCase().replace("j:", "").split("-")[1]);
|
||||
} catch (Exception e) {
|
||||
continue;
|
||||
}
|
||||
requiresJobs.put(jobName, jobLevel);
|
||||
}
|
||||
if (one.toLowerCase().contains("p:")) {
|
||||
requiresPerm.add(one.replace("p:", ""));
|
||||
}
|
||||
}
|
||||
for (String one : perform) {
|
||||
if (!one.toLowerCase().contains("p:"))
|
||||
continue;
|
||||
String perm = one.toLowerCase().replace("p:", "").split("-")[0];
|
||||
boolean n = one.toLowerCase().replace("p:", "").split("-")[1].equalsIgnoreCase("true") ? true : false;
|
||||
performPerm.put(perm, n);
|
||||
}
|
||||
}
|
||||
|
||||
public String getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
public List<String> getRequires() {
|
||||
return requires;
|
||||
public List<String> getRequiredPerm() {
|
||||
return requiresPerm;
|
||||
}
|
||||
|
||||
public List<String> getPerform() {
|
||||
return perform;
|
||||
public HashMap<String, Integer> getRequiredJobs() {
|
||||
return requiresJobs;
|
||||
}
|
||||
|
||||
public HashMap<String, Boolean> getPerformPerm() {
|
||||
return performPerm;
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +101,37 @@ public class JobsPlayer {
|
||||
return jPlayer;
|
||||
}
|
||||
|
||||
public static JobsPlayer loadFromDao(JobsDAO dao, Player player) {
|
||||
|
||||
JobsPlayer jPlayer = new JobsPlayer(player.getName(), player);
|
||||
jPlayer.playerUUID = player.getUniqueId();
|
||||
List<JobsDAOData> list = new ArrayList<JobsDAOData>();
|
||||
list = dao.getAllJobs(player);
|
||||
// synchronized (jPlayer.saveLock) {
|
||||
jPlayer.progression.clear();
|
||||
for (JobsDAOData jobdata : list) {
|
||||
if (Jobs.getJob(jobdata.getJobName()) == null)
|
||||
continue;
|
||||
// add the job
|
||||
Job job = Jobs.getJob(jobdata.getJobName());
|
||||
if (job == null)
|
||||
continue;
|
||||
|
||||
// create the progression object
|
||||
JobProgression jobProgression = new JobProgression(job, jPlayer, jobdata.getLevel(), jobdata.getExperience(), -1, -1, -1);
|
||||
// calculate the max level
|
||||
// add the progression level.
|
||||
jPlayer.progression.add(jobProgression);
|
||||
|
||||
}
|
||||
jPlayer.reloadMaxExperience();
|
||||
jPlayer.reloadLimits();
|
||||
jPlayer.setUserId(Jobs.getPlayerManager().getPlayerMap().get(player.getUniqueId().toString()).getID());
|
||||
Jobs.getJobsDAO().loadPoints(jPlayer);
|
||||
// }
|
||||
return jPlayer;
|
||||
}
|
||||
|
||||
public void setPlayer(Player p) {
|
||||
this.player = p;
|
||||
}
|
||||
@ -517,7 +548,7 @@ public class JobsPlayer {
|
||||
int numJobs = progression.size();
|
||||
boolean gotTitle = false;
|
||||
|
||||
if (numJobs > 0)
|
||||
if (numJobs > 0) {
|
||||
for (JobProgression prog : progression) {
|
||||
DisplayMethod method = prog.getJob().getDisplayMethod();
|
||||
if (method.equals(DisplayMethod.NONE))
|
||||
@ -571,7 +602,7 @@ public class JobsPlayer {
|
||||
gotTitle = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Job nonejob = Jobs.getNoneJob();
|
||||
if (nonejob != null) {
|
||||
DisplayMethod metod = nonejob.getDisplayMethod();
|
||||
|
@ -143,12 +143,14 @@ public abstract class JobsDAO {
|
||||
else
|
||||
userData = Jobs.getPlayerManager().getPlayerMap().get(uuid.toString());
|
||||
|
||||
ArrayList<JobsDAOData> jobs = new ArrayList<JobsDAOData>();
|
||||
|
||||
if (userData == null) {
|
||||
id = recordNewPlayer(playerName, uuid);
|
||||
recordNewPlayer(playerName, uuid);
|
||||
return jobs;
|
||||
} else
|
||||
id = userData.getID();
|
||||
|
||||
ArrayList<JobsDAOData> jobs = new ArrayList<JobsDAOData>();
|
||||
JobsConnection conn = getConnection();
|
||||
if (conn == null)
|
||||
return jobs;
|
||||
@ -166,45 +168,32 @@ public abstract class JobsDAO {
|
||||
return jobs;
|
||||
}
|
||||
|
||||
public int recordNewPlayer(Player player) {
|
||||
return recordNewPlayer((OfflinePlayer) player);
|
||||
public void recordNewPlayer(Player player) {
|
||||
recordNewPlayer((OfflinePlayer) player);
|
||||
}
|
||||
|
||||
public int recordNewPlayer(OfflinePlayer player) {
|
||||
return recordNewPlayer(player.getName(), player.getUniqueId());
|
||||
public void recordNewPlayer(OfflinePlayer player) {
|
||||
recordNewPlayer(player.getName(), player.getUniqueId());
|
||||
}
|
||||
|
||||
public int recordNewPlayer(String playerName, UUID uuid) {
|
||||
|
||||
int id = -1;
|
||||
|
||||
public void recordNewPlayer(String playerName, UUID uuid) {
|
||||
JobsConnection conn = getConnection();
|
||||
if (conn == null)
|
||||
return id;
|
||||
return;
|
||||
try {
|
||||
PreparedStatement prest = conn.prepareStatement("INSERT INTO `" + prefix + "users` (`player_uuid`, `username`) VALUES (?, ?);");
|
||||
prest.setString(1, uuid.toString());
|
||||
prest.setString(2, playerName);
|
||||
prest.executeUpdate();
|
||||
ResultSet keys = prest.getGeneratedKeys();
|
||||
if (keys.next()) {
|
||||
int id = keys.getInt(1);
|
||||
Jobs.getPlayerManager().getPlayerMap().put(uuid.toString(), new PlayerInfo(playerName, id));
|
||||
}
|
||||
prest.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
try {
|
||||
PreparedStatement prest = conn.prepareStatement("SELECT `id` FROM `" + prefix + "users` WHERE `player_uuid` = ?;");
|
||||
prest.setString(1, uuid.toString());
|
||||
ResultSet res = prest.executeQuery();
|
||||
res.next();
|
||||
id = res.getInt("id");
|
||||
Jobs.getPlayerManager().getPlayerMap().put(uuid.toString(), new PlayerInfo(playerName, id));
|
||||
res.close();
|
||||
prest.close();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,27 +158,28 @@ public class JobsListener implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
|
||||
// make sure plugin is enabled
|
||||
if (!plugin.isEnabled())
|
||||
return;
|
||||
Jobs.getPlayerManager().playerJoin(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerJoinMonitor(PlayerJoinEvent event) {
|
||||
// make sure plugin is enabled
|
||||
if (!plugin.isEnabled())
|
||||
return;
|
||||
|
||||
/*
|
||||
* We need to recalculate again to check for world permission and revoke permissions
|
||||
* if we don't have world permission (from some other permission manager). It's
|
||||
* necessary to call this twice in case somebody is relying on permissions from this
|
||||
* plugin on entry to the world.
|
||||
*/
|
||||
JobsPlayer jPlayer = Jobs.getPlayerManager().getJobsPlayer(event.getPlayer());
|
||||
Jobs.getPermissionHandler().recalculatePermissions(jPlayer);
|
||||
}
|
||||
// @EventHandler(priority = EventPriority.MONITOR)
|
||||
// public void onPlayerJoinMonitor(PlayerJoinEvent event) {
|
||||
// // make sure plugin is enabled
|
||||
// if (!plugin.isEnabled())
|
||||
// return;
|
||||
//
|
||||
// /*
|
||||
// * We need to recalculate again to check for world permission and revoke permissions
|
||||
// * if we don't have world permission (from some other permission manager). It's
|
||||
// * necessary to call this twice in case somebody is relying on permissions from this
|
||||
// * plugin on entry to the world.
|
||||
// */
|
||||
// JobsPlayer jPlayer = Jobs.getPlayerManager().getJobsPlayer(event.getPlayer());
|
||||
// Jobs.getPermissionHandler().recalculatePermissions(jPlayer);
|
||||
// }
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||
@ -547,7 +548,7 @@ public class JobsListener implements Listener {
|
||||
Map<Enchantment, Integer> enchants = new HashMap<Enchantment, Integer>();
|
||||
try {
|
||||
enchants = iih.getEnchantments();
|
||||
} catch (NullPointerException e) {
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
if (enchants.isEmpty())
|
||||
|
@ -14,6 +14,7 @@ import org.bukkit.entity.Skeleton;
|
||||
import org.bukkit.entity.Zombie;
|
||||
import org.bukkit.entity.Horse.Variant;
|
||||
import org.bukkit.entity.Skeleton.SkeletonType;
|
||||
import org.bukkit.entity.Villager.Profession;
|
||||
import org.bukkit.event.block.BlockPistonRetractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
@ -52,8 +53,10 @@ public class v1_10 implements NMS {
|
||||
break;
|
||||
case ZOMBIE:
|
||||
Zombie zombie = (Zombie) entity;
|
||||
if (zombie.isVillager())
|
||||
if (zombie.isVillager() && zombie.getVillagerProfession() != Profession.HUSK)
|
||||
return "ZombieVillager";
|
||||
if (zombie.isVillager() && zombie.getVillagerProfession() == Profession.HUSK)
|
||||
return "ZombieHusk";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
name: Jobs
|
||||
description: Jobs Plugin for the BukkitAPI
|
||||
main: com.gamingmesh.jobs.JobsPlugin
|
||||
version: 3.4.0
|
||||
version: 3.4.2
|
||||
author: phrstbrn
|
||||
depend: [Vault]
|
||||
softdepend: [CoreProtect, MythicMobs, McMMO]
|
||||
|
Loading…
Reference in New Issue
Block a user