mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-22 21:26:46 +01:00
Version 1.1.17
This commit is contained in:
parent
12e7277f6f
commit
bb276209b5
@ -1,7 +1,16 @@
|
|||||||
Changelog:
|
Changelog:
|
||||||
#Versions without changelogs probably had very small misc fixes, like tweaks to the source code
|
#Versions without changelogs probably had very small misc fixes, like tweaks to the source code
|
||||||
Version 1.1.17
|
Version 1.1.17
|
||||||
|
XP gained in combat is now softcapped by the remaining health of the entity you are damaging, preventing many exploits.
|
||||||
|
Compiled against latest Spout & CraftBukkit
|
||||||
|
Added World PVP check to Ignition, should no longer ignore PVP settings
|
||||||
|
Enemies should no longer grant XP when hit during their death
|
||||||
|
Fixed an exploit that led to unlimited ability use
|
||||||
|
Possibly fixed a bug where the same player would be listed multiple times in mctop
|
||||||
|
Added author and description to plugin.yml
|
||||||
|
|
||||||
/mmoedit and /addxp are useable from the console now
|
/mmoedit and /addxp are useable from the console now
|
||||||
|
Swearword's statistics tracking removed (He stopped the service, so its gone now.. On a positive note, I did find out 1000-1500 servers installed mcMMO a day)
|
||||||
|
|
||||||
Version 1.1.16
|
Version 1.1.16
|
||||||
Added Melons to Herbalism xp tables
|
Added Melons to Herbalism xp tables
|
||||||
|
@ -102,48 +102,69 @@ public class Combat
|
|||||||
&& ((PPd.getLastLogin()+5)*1000) < System.currentTimeMillis()
|
&& ((PPd.getLastLogin()+5)*1000) < System.currentTimeMillis()
|
||||||
&& defender.getHealth() >= 1)
|
&& defender.getHealth() >= 1)
|
||||||
{
|
{
|
||||||
int xp = (int) (event.getDamage() * 2 * LoadProperties.pvpxprewardmodifier);
|
//Prevent a ridiculous amount of XP being granted by capping it at the remaining health of the mob
|
||||||
|
int hpLeft = defender.getHealth(), xpinc = 0;
|
||||||
|
|
||||||
|
if(hpLeft < event.getDamage())
|
||||||
|
xpinc = event.getDamage();
|
||||||
|
else
|
||||||
|
xpinc = hpLeft;
|
||||||
|
|
||||||
|
int xp = (int) (xpinc * 2 * LoadProperties.pvpxprewardmodifier);
|
||||||
|
|
||||||
if(m.isAxes(attacker.getItemInHand()) && mcPermissions.getInstance().axes(attacker))
|
if(m.isAxes(attacker.getItemInHand()) && mcPermissions.getInstance().axes(attacker))
|
||||||
PPa.addXP(SkillType.AXES, xp*10);
|
PPa.addXP(SkillType.AXES, xp*10, attacker);
|
||||||
if(m.isSwords(attacker.getItemInHand()) && mcPermissions.getInstance().swords(attacker))
|
if(m.isSwords(attacker.getItemInHand()) && mcPermissions.getInstance().swords(attacker))
|
||||||
PPa.addXP(SkillType.SWORDS, xp*10);
|
PPa.addXP(SkillType.SWORDS, xp*10, attacker);
|
||||||
if(attacker.getItemInHand().getTypeId() == 0 && mcPermissions.getInstance().unarmed(attacker))
|
if(attacker.getItemInHand().getTypeId() == 0 && mcPermissions.getInstance().unarmed(attacker))
|
||||||
PPa.addXP(SkillType.UNARMED, xp*10);
|
PPa.addXP(SkillType.UNARMED, xp*10, attacker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event.getEntity() instanceof Monster && !pluginx.misc.mobSpawnerList.contains(event.getEntity()))
|
if(event.getEntity() instanceof Monster && !pluginx.misc.mobSpawnerList.contains(event.getEntity()))
|
||||||
{
|
{
|
||||||
|
//Prevent XP from being handed out if the Monster is dead
|
||||||
|
Monster monster = (Monster)event.getEntity();
|
||||||
|
if(monster.getHealth() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Prevent a ridiculous amount of XP being granted by capping it at the remaining health of the mob
|
||||||
|
int hpLeft = monster.getHealth(), xpinc = 0;
|
||||||
|
|
||||||
|
if(hpLeft < event.getDamage())
|
||||||
|
xpinc = event.getDamage();
|
||||||
|
else
|
||||||
|
xpinc = hpLeft;
|
||||||
|
|
||||||
int xp = 0;
|
int xp = 0;
|
||||||
if(event.getEntity() instanceof Enderman)
|
if(event.getEntity() instanceof Enderman)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Creeper)
|
if(event.getEntity() instanceof Creeper)
|
||||||
xp = (event.getDamage() * 4);
|
xp = (xpinc * 4);
|
||||||
if(event.getEntity() instanceof Silverfish)
|
if(event.getEntity() instanceof Silverfish)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof CaveSpider)
|
if(event.getEntity() instanceof CaveSpider)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Spider)
|
if(event.getEntity() instanceof Spider)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Skeleton)
|
if(event.getEntity() instanceof Skeleton)
|
||||||
xp = (event.getDamage() * 2);
|
xp = (xpinc * 2);
|
||||||
if(event.getEntity() instanceof Zombie)
|
if(event.getEntity() instanceof Zombie)
|
||||||
xp = (event.getDamage() * 2);
|
xp = (xpinc * 2);
|
||||||
if(event.getEntity() instanceof PigZombie)
|
if(event.getEntity() instanceof PigZombie)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Slime)
|
if(event.getEntity() instanceof Slime)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Ghast)
|
if(event.getEntity() instanceof Ghast)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
|
|
||||||
if(m.isSwords(attacker.getItemInHand()) && mcPermissions.getInstance().swords(attacker))
|
if(m.isSwords(attacker.getItemInHand()) && mcPermissions.getInstance().swords(attacker))
|
||||||
PPa.addXP(SkillType.SWORDS, xp*10);
|
PPa.addXP(SkillType.SWORDS, xp*10, attacker);
|
||||||
else if(m.isAxes(attacker.getItemInHand()) && mcPermissions.getInstance().axes(attacker))
|
else if(m.isAxes(attacker.getItemInHand()) && mcPermissions.getInstance().axes(attacker))
|
||||||
PPa.addXP(SkillType.AXES, xp*10);
|
PPa.addXP(SkillType.AXES, xp*10, attacker);
|
||||||
else if(attacker.getItemInHand().getTypeId() == 0 && mcPermissions.getInstance().unarmed(attacker))
|
else if(attacker.getItemInHand().getTypeId() == 0 && mcPermissions.getInstance().unarmed(attacker))
|
||||||
PPa.addXP(SkillType.UNARMED, xp*10);
|
PPa.addXP(SkillType.UNARMED, xp*10, attacker);
|
||||||
}
|
}
|
||||||
Skills.XpCheckAll(attacker);
|
Skills.XpCheckAll(attacker);
|
||||||
|
|
||||||
@ -214,32 +235,45 @@ public class Combat
|
|||||||
int xp = 0;
|
int xp = 0;
|
||||||
if(event.getEntity() instanceof Monster)
|
if(event.getEntity() instanceof Monster)
|
||||||
{
|
{
|
||||||
|
//Prevent XP from being handed out if the Monster is dead
|
||||||
|
Monster monster = (Monster)event.getEntity();
|
||||||
|
if(monster.getHealth() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Prevent a ridiculous amount of XP being granted by capping it at the remaining health of the mob
|
||||||
|
int hpLeft = monster.getHealth(), xpinc = 0;
|
||||||
|
|
||||||
|
if(hpLeft < event.getDamage())
|
||||||
|
xpinc = event.getDamage();
|
||||||
|
else
|
||||||
|
xpinc = hpLeft;
|
||||||
|
|
||||||
if(event.getEntity() instanceof Creeper)
|
if(event.getEntity() instanceof Creeper)
|
||||||
xp = (event.getDamage() * 6);
|
xp = (xpinc * 6);
|
||||||
if(event.getEntity() instanceof Enderman)
|
if(event.getEntity() instanceof Enderman)
|
||||||
xp = (event.getDamage() * 5);
|
xp = (xpinc * 5);
|
||||||
if(event.getEntity() instanceof Silverfish)
|
if(event.getEntity() instanceof Silverfish)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof CaveSpider)
|
if(event.getEntity() instanceof CaveSpider)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Spider)
|
if(event.getEntity() instanceof Spider)
|
||||||
xp = (event.getDamage() * 5);
|
xp = (xpinc * 5);
|
||||||
if(event.getEntity() instanceof Skeleton)
|
if(event.getEntity() instanceof Skeleton)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof Zombie)
|
if(event.getEntity() instanceof Zombie)
|
||||||
xp = (event.getDamage() * 3);
|
xp = (xpinc * 3);
|
||||||
if(event.getEntity() instanceof PigZombie)
|
if(event.getEntity() instanceof PigZombie)
|
||||||
xp = (event.getDamage() * 4);
|
xp = (xpinc * 4);
|
||||||
if(event.getEntity() instanceof Slime)
|
if(event.getEntity() instanceof Slime)
|
||||||
xp = (event.getDamage() * 4);
|
xp = (xpinc * 4);
|
||||||
if(event.getEntity() instanceof Ghast)
|
if(event.getEntity() instanceof Ghast)
|
||||||
xp = (event.getDamage() * 4);
|
xp = (xpinc * 4);
|
||||||
Users.getProfile(master).addXP(SkillType.TAMING, xp*10);
|
Users.getProfile(master).addXP(SkillType.TAMING, xp*10, master);
|
||||||
}
|
}
|
||||||
if(event.getEntity() instanceof Player)
|
if(event.getEntity() instanceof Player)
|
||||||
{
|
{
|
||||||
xp = (event.getDamage() * 2);
|
xp = (event.getDamage() * 2);
|
||||||
Users.getProfile(master).addXP(SkillType.TAMING, xp*10);
|
Users.getProfile(master).addXP(SkillType.TAMING, xp*10, master);
|
||||||
}
|
}
|
||||||
Skills.XpCheckSkill(SkillType.TAMING, master);
|
Skills.XpCheckSkill(SkillType.TAMING, master);
|
||||||
}
|
}
|
||||||
@ -348,27 +382,40 @@ public class Combat
|
|||||||
*/
|
*/
|
||||||
if(!pluginx.misc.mobSpawnerList.contains(x) && x instanceof Monster)
|
if(!pluginx.misc.mobSpawnerList.contains(x) && x instanceof Monster)
|
||||||
{
|
{
|
||||||
|
//Prevent XP from being handed out if the Monster is dead
|
||||||
|
Monster monster = (Monster)x;
|
||||||
|
if(monster.getHealth() < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//Prevent a ridiculous amount of XP being granted by capping it at the remaining health of the mob
|
||||||
|
int hpLeft = monster.getHealth(), xpinc = 0;
|
||||||
|
|
||||||
|
if(hpLeft < event.getDamage())
|
||||||
|
xpinc = event.getDamage();
|
||||||
|
else
|
||||||
|
xpinc = hpLeft;
|
||||||
|
|
||||||
//XP
|
//XP
|
||||||
if(x instanceof Creeper)
|
if(x instanceof Creeper)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 4)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 4)*10, attacker);
|
||||||
if(x instanceof Enderman)
|
if(x instanceof Enderman)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
if(x instanceof Silverfish)
|
if(x instanceof Silverfish)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 2)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 2)*10, attacker);
|
||||||
if(x instanceof CaveSpider)
|
if(x instanceof CaveSpider)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
if(x instanceof Spider)
|
if(x instanceof Spider)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
if(x instanceof Skeleton)
|
if(x instanceof Skeleton)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 2)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 2)*10, attacker);
|
||||||
if(x instanceof Zombie)
|
if(x instanceof Zombie)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 2)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 2)*10, attacker);
|
||||||
if(x instanceof PigZombie)
|
if(x instanceof PigZombie)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
if(x instanceof Slime)
|
if(x instanceof Slime)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
if(x instanceof Ghast)
|
if(x instanceof Ghast)
|
||||||
PPa.addXP(SkillType.ARCHERY, (event.getDamage() * 3)*10);
|
PPa.addXP(SkillType.ARCHERY, (xpinc * 3)*10, attacker);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Attacker is Player
|
* Attacker is Player
|
||||||
@ -394,7 +441,7 @@ public class Combat
|
|||||||
&& ((PPd.getLastLogin()+5)*1000) < System.currentTimeMillis() && !attacker.getName().equals(defender.getName()))
|
&& ((PPd.getLastLogin()+5)*1000) < System.currentTimeMillis() && !attacker.getName().equals(defender.getName()))
|
||||||
{
|
{
|
||||||
int xp = (int) ((event.getDamage() * 2) * 10);
|
int xp = (int) ((event.getDamage() * 2) * 10);
|
||||||
PPa.addXP(SkillType.ARCHERY, xp);
|
PPa.addXP(SkillType.ARCHERY, xp, attacker);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* DAZE PROC
|
* DAZE PROC
|
||||||
|
@ -21,6 +21,7 @@ import java.io.File;
|
|||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@ -59,11 +60,17 @@ public class Leaderboard
|
|||||||
FileReader file = new FileReader(location);
|
FileReader file = new FileReader(location);
|
||||||
BufferedReader in = new BufferedReader(file);
|
BufferedReader in = new BufferedReader(file);
|
||||||
String line = ""; //$NON-NLS-1$
|
String line = ""; //$NON-NLS-1$
|
||||||
|
ArrayList<String> players = new ArrayList<String>();
|
||||||
while((line = in.readLine()) != null)
|
while((line = in.readLine()) != null)
|
||||||
{
|
{
|
||||||
String[] character = line.split(":"); //$NON-NLS-1$
|
String[] character = line.split(":"); //$NON-NLS-1$
|
||||||
String p = character[0];
|
String p = character[0];
|
||||||
|
|
||||||
|
//Prevent the same player from being added multiple times
|
||||||
|
if(players.contains(p))
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
players.add(p);
|
||||||
|
|
||||||
int Plvl = 0;
|
int Plvl = 0;
|
||||||
|
|
||||||
|
@ -953,7 +953,7 @@ public class Commands
|
|||||||
if(isPlayer(split[1]) && m.isInt(split[3]) && Skills.isSkill(split[2]))
|
if(isPlayer(split[1]) && m.isInt(split[3]) && Skills.isSkill(split[2]))
|
||||||
{
|
{
|
||||||
int newvalue = Integer.valueOf(split[3]);
|
int newvalue = Integer.valueOf(split[3]);
|
||||||
Users.getProfile(getPlayer(split[1])).addXP(Skills.getSkillType(split[2]), newvalue);
|
Users.getProfile(getPlayer(split[1])).addXP(Skills.getSkillType(split[2]), newvalue, getPlayer(split[1]));
|
||||||
getPlayer(split[1]).sendMessage(ChatColor.GREEN+"Experience granted!");
|
getPlayer(split[1]).sendMessage(ChatColor.GREEN+"Experience granted!");
|
||||||
player.sendMessage(ChatColor.RED+split[2]+" has been modified.");
|
player.sendMessage(ChatColor.RED+split[2]+" has been modified.");
|
||||||
Skills.XpCheckAll(getPlayer(split[1]));
|
Skills.XpCheckAll(getPlayer(split[1]));
|
||||||
@ -962,7 +962,7 @@ public class Commands
|
|||||||
else if(split.length == 3 && m.isInt(split[2]) && Skills.isSkill(split[1]))
|
else if(split.length == 3 && m.isInt(split[2]) && Skills.isSkill(split[1]))
|
||||||
{
|
{
|
||||||
int newvalue = Integer.valueOf(split[2]);
|
int newvalue = Integer.valueOf(split[2]);
|
||||||
Users.getProfile(player).addXP(Skills.getSkillType(split[1]), newvalue);
|
Users.getProfile(player).addXP(Skills.getSkillType(split[1]), newvalue, player);
|
||||||
player.sendMessage(ChatColor.RED+split[1]+" has been modified.");
|
player.sendMessage(ChatColor.RED+split[1]+" has been modified.");
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(ChatColor.RED+"Usage is /"+LoadProperties.addxp+" playername skillname xp");
|
player.sendMessage(ChatColor.RED+"Usage is /"+LoadProperties.addxp+" playername skillname xp");
|
||||||
@ -977,7 +977,7 @@ public class Commands
|
|||||||
if(isPlayer(split[1]) && m.isInt(split[3]) && Skills.isSkill(split[2]))
|
if(isPlayer(split[1]) && m.isInt(split[3]) && Skills.isSkill(split[2]))
|
||||||
{
|
{
|
||||||
int newvalue = Integer.valueOf(split[3]);
|
int newvalue = Integer.valueOf(split[3]);
|
||||||
Users.getProfile(getPlayer(split[1])).addXP(Skills.getSkillType(split[2]), newvalue);
|
Users.getProfile(getPlayer(split[1])).addXP(Skills.getSkillType(split[2]), newvalue, getPlayer(split[1]));
|
||||||
getPlayer(split[1]).sendMessage(ChatColor.GREEN+"Experience granted!");
|
getPlayer(split[1]).sendMessage(ChatColor.GREEN+"Experience granted!");
|
||||||
System.out.println(split[2]+" has been modified for "+getPlayer(split[1]).getName()+".");
|
System.out.println(split[2]+" has been modified for "+getPlayer(split[1]).getName()+".");
|
||||||
Skills.XpCheckAll(getPlayer(split[1]));
|
Skills.XpCheckAll(getPlayer(split[1]));
|
||||||
|
@ -27,6 +27,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import com.gmail.nossr50.config.LoadProperties;
|
import com.gmail.nossr50.config.LoadProperties;
|
||||||
@ -949,8 +950,10 @@ public class PlayerProfile
|
|||||||
* @param skillType The skill to add XP to
|
* @param skillType The skill to add XP to
|
||||||
* @param newvalue The amount of XP to add
|
* @param newvalue The amount of XP to add
|
||||||
*/
|
*/
|
||||||
public void addXP(SkillType skillType, int newvalue)
|
public void addXP(SkillType skillType, int newvalue, Player thisplayer)
|
||||||
{
|
{
|
||||||
|
if(thisplayer.getGameMode() == GameMode.CREATIVE)
|
||||||
|
return;
|
||||||
if(skillType == SkillType.ALL)
|
if(skillType == SkillType.ALL)
|
||||||
{
|
{
|
||||||
for(SkillType x : SkillType.values())
|
for(SkillType x : SkillType.values())
|
||||||
|
@ -171,13 +171,13 @@ public class mcBlockListener extends BlockListener
|
|||||||
WoodCutting.woodCuttingProcCheck(player, block);
|
WoodCutting.woodCuttingProcCheck(player, block);
|
||||||
//Default
|
//Default
|
||||||
if(block.getData() == (byte)0)
|
if(block.getData() == (byte)0)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine, player);
|
||||||
//Spruce
|
//Spruce
|
||||||
if(block.getData() == (byte)1)
|
if(block.getData() == (byte)1)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mspruce);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mspruce, player);
|
||||||
//Birch
|
//Birch
|
||||||
if(block.getData() == (byte)2)
|
if(block.getData() == (byte)2)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mbirch);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mbirch, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -187,13 +187,13 @@ public class mcBlockListener extends BlockListener
|
|||||||
WoodCutting.woodCuttingProcCheck(player, block);
|
WoodCutting.woodCuttingProcCheck(player, block);
|
||||||
//Default
|
//Default
|
||||||
if(block.getData() == (byte)0)
|
if(block.getData() == (byte)0)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine, player);
|
||||||
//Spruce
|
//Spruce
|
||||||
if(block.getData() == (byte)1)
|
if(block.getData() == (byte)1)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mspruce);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mspruce, player);
|
||||||
//Birch
|
//Birch
|
||||||
if(block.getData() == (byte)2)
|
if(block.getData() == (byte)2)
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mbirch);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mbirch, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Skills.XpCheckSkill(SkillType.WOODCUTTING, player);
|
Skills.XpCheckSkill(SkillType.WOODCUTTING, player);
|
||||||
@ -226,7 +226,7 @@ public class mcBlockListener extends BlockListener
|
|||||||
if(!plugin.misc.blockWatchList.contains(block))
|
if(!plugin.misc.blockWatchList.contains(block))
|
||||||
{
|
{
|
||||||
WoodCutting.woodCuttingProcCheck(player, blockx);
|
WoodCutting.woodCuttingProcCheck(player, blockx);
|
||||||
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine);
|
PP.addXP(SkillType.WOODCUTTING, LoadProperties.mpine, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(blockx.getTypeId() == 18)
|
if(blockx.getTypeId() == 18)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.gmail.nossr50.listeners;
|
package com.gmail.nossr50.listeners;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
@ -259,6 +260,8 @@ public class mcPlayerListener extends PlayerListener
|
|||||||
{
|
{
|
||||||
ColouredConsoleSender ccs = (ColouredConsoleSender) Bukkit.getServer();
|
ColouredConsoleSender ccs = (ColouredConsoleSender) Bukkit.getServer();
|
||||||
ccs.sendMessage(ChatColor.AQUA+"[A]"+format); //Colors, woot!
|
ccs.sendMessage(ChatColor.AQUA+"[A]"+format); //Colors, woot!
|
||||||
|
} else {
|
||||||
|
log.log(Level.INFO, "[A]"+format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ import com.gmail.nossr50.party.Party;
|
|||||||
import com.gmail.nossr50.skills.*;
|
import com.gmail.nossr50.skills.*;
|
||||||
import com.nijikokun.bukkit.Permissions.Permissions;
|
import com.nijikokun.bukkit.Permissions.Permissions;
|
||||||
|
|
||||||
import org.blockface.bukkitstats.CallHome;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -190,7 +189,6 @@ public class mcMMO extends JavaPlugin
|
|||||||
System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!" );
|
System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!" );
|
||||||
|
|
||||||
Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(this, mcMMO_Timer, 0, 20);
|
Bukkit.getServer().getScheduler().scheduleAsyncRepeatingTask(this, mcMMO_Timer, 0, 20);
|
||||||
CallHome.load(this); //Swearword's blockface usage statistics, only dials home once
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerProfile getPlayerProfile(Player player)
|
public PlayerProfile getPlayerProfile(Player player)
|
||||||
|
@ -52,7 +52,7 @@ public class Acrobatics {
|
|||||||
*/
|
*/
|
||||||
if(player.getHealth() - newDamage >= 1){
|
if(player.getHealth() - newDamage >= 1){
|
||||||
if(!event.isCancelled())
|
if(!event.isCancelled())
|
||||||
PP.addXP(SkillType.ACROBATICS, (event.getDamage() * 8)*10);
|
PP.addXP(SkillType.ACROBATICS, (event.getDamage() * 8)*10, player);
|
||||||
Skills.XpCheckSkill(SkillType.ACROBATICS, player);
|
Skills.XpCheckSkill(SkillType.ACROBATICS, player);
|
||||||
event.setDamage(newDamage);
|
event.setDamage(newDamage);
|
||||||
if(event.getDamage() <= 0)
|
if(event.getDamage() <= 0)
|
||||||
@ -65,7 +65,7 @@ public class Acrobatics {
|
|||||||
}
|
}
|
||||||
} else if (!event.isCancelled()){
|
} else if (!event.isCancelled()){
|
||||||
if(player.getHealth() - event.getDamage() >= 1){
|
if(player.getHealth() - event.getDamage() >= 1){
|
||||||
PP.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*10);
|
PP.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*10, player);
|
||||||
Skills.XpCheckSkill(SkillType.ACROBATICS, player);
|
Skills.XpCheckSkill(SkillType.ACROBATICS, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ public class Acrobatics {
|
|||||||
if(Math.random() * 4000 <= PPd.getSkillLevel(SkillType.ACROBATICS)){
|
if(Math.random() * 4000 <= PPd.getSkillLevel(SkillType.ACROBATICS)){
|
||||||
defender.sendMessage(ChatColor.GREEN+"**DODGE**");
|
defender.sendMessage(ChatColor.GREEN+"**DODGE**");
|
||||||
if(System.currentTimeMillis() >= 5000 + PPd.getRespawnATS() && defender.getHealth() >= 1){
|
if(System.currentTimeMillis() >= 5000 + PPd.getRespawnATS() && defender.getHealth() >= 1){
|
||||||
PPd.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*1);
|
PPd.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*1, defender);
|
||||||
Skills.XpCheckSkill(SkillType.ACROBATICS, defender);
|
Skills.XpCheckSkill(SkillType.ACROBATICS, defender);
|
||||||
}
|
}
|
||||||
event.setDamage(event.getDamage() / 2);
|
event.setDamage(event.getDamage() / 2);
|
||||||
@ -91,7 +91,7 @@ public class Acrobatics {
|
|||||||
} else if(Math.random() * 4000 <= 800) {
|
} else if(Math.random() * 4000 <= 800) {
|
||||||
defender.sendMessage(ChatColor.GREEN+"**DODGE**");
|
defender.sendMessage(ChatColor.GREEN+"**DODGE**");
|
||||||
if(System.currentTimeMillis() >= 5000 + PPd.getRespawnATS() && defender.getHealth() >= 1){
|
if(System.currentTimeMillis() >= 5000 + PPd.getRespawnATS() && defender.getHealth() >= 1){
|
||||||
PPd.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*10);
|
PPd.addXP(SkillType.ACROBATICS, (event.getDamage() * 12)*10, defender);
|
||||||
Skills.XpCheckSkill(SkillType.ACROBATICS, defender);
|
Skills.XpCheckSkill(SkillType.ACROBATICS, defender);
|
||||||
}
|
}
|
||||||
event.setDamage(event.getDamage() / 2);
|
event.setDamage(event.getDamage() / 2);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package com.gmail.nossr50.skills;
|
package com.gmail.nossr50.skills;
|
||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
@ -58,6 +59,10 @@ public class Archery
|
|||||||
}
|
}
|
||||||
public static void ignitionCheck(Entity x, EntityDamageByEntityEvent event, Player attacker)
|
public static void ignitionCheck(Entity x, EntityDamageByEntityEvent event, Player attacker)
|
||||||
{
|
{
|
||||||
|
//Check to see if PVP for this world is disabled before executing
|
||||||
|
if(!x.getWorld().getPVP())
|
||||||
|
return;
|
||||||
|
|
||||||
PlayerProfile PPa = Users.getProfile(attacker);
|
PlayerProfile PPa = Users.getProfile(attacker);
|
||||||
if(Math.random() * 100 >= 75)
|
if(Math.random() * 100 >= 75)
|
||||||
{
|
{
|
||||||
|
@ -273,7 +273,7 @@ public class Excavation
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Handle XP related tasks
|
//Handle XP related tasks
|
||||||
PP.addXP(SkillType.EXCAVATION, xp);
|
PP.addXP(SkillType.EXCAVATION, xp, player);
|
||||||
Skills.XpCheckSkill(SkillType.EXCAVATION, player);
|
Skills.XpCheckSkill(SkillType.EXCAVATION, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public class Herbalism
|
|||||||
Material mat = Material.getMaterial(296);
|
Material mat = Material.getMaterial(296);
|
||||||
Location loc = block.getLocation();
|
Location loc = block.getLocation();
|
||||||
ItemStack is = new ItemStack(mat, 1, (byte)0, (byte)0);
|
ItemStack is = new ItemStack(mat, 1, (byte)0, (byte)0);
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mwheat);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mwheat, player);
|
||||||
loc.getWorld().dropItemNaturally(loc, is);
|
loc.getWorld().dropItemNaturally(loc, is);
|
||||||
|
|
||||||
//DROP SOME SEEDS
|
//DROP SOME SEEDS
|
||||||
@ -161,7 +161,7 @@ public class Herbalism
|
|||||||
{
|
{
|
||||||
mat = Material.getMaterial(296);
|
mat = Material.getMaterial(296);
|
||||||
is = new ItemStack(mat, 1, (byte)0, (byte)0);
|
is = new ItemStack(mat, 1, (byte)0, (byte)0);
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mwheat);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mwheat, player);
|
||||||
if(player != null)
|
if(player != null)
|
||||||
{
|
{
|
||||||
if(Math.random() * 1000 <= PP.getSkillLevel(SkillType.HERBALISM))
|
if(Math.random() * 1000 <= PP.getSkillLevel(SkillType.HERBALISM))
|
||||||
@ -235,7 +235,7 @@ public class Herbalism
|
|||||||
{
|
{
|
||||||
loc.getWorld().dropItemNaturally(target.getLocation(), is);
|
loc.getWorld().dropItemNaturally(target.getLocation(), is);
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mcactus);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mcactus, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x++;
|
x++;
|
||||||
@ -274,7 +274,7 @@ public class Herbalism
|
|||||||
{
|
{
|
||||||
loc.getWorld().dropItemNaturally(target.getLocation(), is);
|
loc.getWorld().dropItemNaturally(target.getLocation(), is);
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.msugar);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.msugar, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x++;
|
x++;
|
||||||
@ -293,7 +293,7 @@ public class Herbalism
|
|||||||
loc.getWorld().dropItemNaturally(loc, is);
|
loc.getWorld().dropItemNaturally(loc, is);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mpumpkin);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mpumpkin, player);
|
||||||
}
|
}
|
||||||
//Melon
|
//Melon
|
||||||
if(type == 103)
|
if(type == 103)
|
||||||
@ -305,7 +305,7 @@ public class Herbalism
|
|||||||
{
|
{
|
||||||
loc.getWorld().dropItemNaturally(loc, is);
|
loc.getWorld().dropItemNaturally(loc, is);
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mmelon);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mmelon, player);
|
||||||
}
|
}
|
||||||
//Mushroom
|
//Mushroom
|
||||||
if(type == 39 || type == 40)
|
if(type == 39 || type == 40)
|
||||||
@ -319,7 +319,7 @@ public class Herbalism
|
|||||||
loc.getWorld().dropItemNaturally(loc, is);
|
loc.getWorld().dropItemNaturally(loc, is);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mmushroom);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mmushroom, player);
|
||||||
}
|
}
|
||||||
//Flower
|
//Flower
|
||||||
if(type == 37 || type == 38){
|
if(type == 37 || type == 38){
|
||||||
@ -330,7 +330,7 @@ public class Herbalism
|
|||||||
loc.getWorld().dropItemNaturally(loc, is);
|
loc.getWorld().dropItemNaturally(loc, is);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.HERBALISM, LoadProperties.mflower);
|
PP.addXP(SkillType.HERBALISM, LoadProperties.mflower, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Skills.XpCheckSkill(SkillType.HERBALISM, player);
|
Skills.XpCheckSkill(SkillType.HERBALISM, player);
|
||||||
|
@ -233,7 +233,7 @@ public class Mining
|
|||||||
else
|
else
|
||||||
blockProcCheck(block, player);
|
blockProcCheck(block, player);
|
||||||
}
|
}
|
||||||
PP.addXP(SkillType.MINING, xp);
|
PP.addXP(SkillType.MINING, xp, player);
|
||||||
Skills.XpCheckSkill(SkillType.MINING, player);
|
Skills.XpCheckSkill(SkillType.MINING, player);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -422,7 +422,7 @@ public class Mining
|
|||||||
block.setType(Material.AIR);
|
block.setType(Material.AIR);
|
||||||
}
|
}
|
||||||
if(block.getData() != (byte) 5)
|
if(block.getData() != (byte) 5)
|
||||||
PP.addXP(SkillType.MINING, xp);
|
PP.addXP(SkillType.MINING, xp, player);
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
SpoutStuff.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
|
SpoutStuff.playSoundForPlayer(SoundEffect.POP, player, block.getLocation());
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ public class Repair {
|
|||||||
durabilityAfter = player.getItemInHand().getDurability();
|
durabilityAfter = player.getItemInHand().getDurability();
|
||||||
dif = (short) (durabilityBefore - durabilityAfter);
|
dif = (short) (durabilityBefore - durabilityAfter);
|
||||||
dif = (short) (dif * 6); //Boost XP
|
dif = (short) (dif * 6); //Boost XP
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
@ -85,7 +85,7 @@ public class Repair {
|
|||||||
durabilityAfter = player.getItemInHand().getDurability();
|
durabilityAfter = player.getItemInHand().getDurability();
|
||||||
dif = (short) (durabilityBefore - durabilityAfter);
|
dif = (short) (durabilityBefore - durabilityAfter);
|
||||||
dif = (short) (dif * 2); //Boost XP
|
dif = (short) (dif * 2); //Boost XP
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
@ -97,7 +97,7 @@ public class Repair {
|
|||||||
durabilityAfter = player.getItemInHand().getDurability();
|
durabilityAfter = player.getItemInHand().getDurability();
|
||||||
dif = (short) (durabilityBefore - durabilityAfter);
|
dif = (short) (durabilityBefore - durabilityAfter);
|
||||||
dif = (short) (dif * 4); //Boost XP of Gold to around Iron
|
dif = (short) (dif * 4); //Boost XP of Gold to around Iron
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
@ -135,7 +135,7 @@ public class Repair {
|
|||||||
//STONE NERF
|
//STONE NERF
|
||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
|
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
} else if(isWoodTools(is) && hasItem(player,rWood)){
|
} else if(isWoodTools(is) && hasItem(player,rWood)){
|
||||||
removeItem(player,rWood);
|
removeItem(player,rWood);
|
||||||
/*
|
/*
|
||||||
@ -153,7 +153,7 @@ public class Repair {
|
|||||||
//WOOD NERF
|
//WOOD NERF
|
||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
|
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
} else if(isIronTools(is) && hasItem(player, rIron)){
|
} else if(isIronTools(is) && hasItem(player, rIron)){
|
||||||
removeItem(player, rIron);
|
removeItem(player, rIron);
|
||||||
/*
|
/*
|
||||||
@ -168,7 +168,7 @@ public class Repair {
|
|||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
if(m.isHoe(is))
|
if(m.isHoe(is))
|
||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
@ -187,7 +187,7 @@ public class Repair {
|
|||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
if(m.isHoe(is))
|
if(m.isHoe(is))
|
||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
@ -204,7 +204,7 @@ public class Repair {
|
|||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
if(m.isHoe(is))
|
if(m.isHoe(is))
|
||||||
dif = (short) (dif / 2);
|
dif = (short) (dif / 2);
|
||||||
PP.addXP(SkillType.REPAIR, dif*10);
|
PP.addXP(SkillType.REPAIR, dif*10, player);
|
||||||
|
|
||||||
//CLANG CLANG
|
//CLANG CLANG
|
||||||
if(LoadProperties.spoutEnabled)
|
if(LoadProperties.spoutEnabled)
|
||||||
|
@ -226,7 +226,7 @@ public class Skills
|
|||||||
PlayerProfile PP = Users.getProfile(player);
|
PlayerProfile PP = Users.getProfile(player);
|
||||||
if(PP != null)
|
if(PP != null)
|
||||||
{
|
{
|
||||||
if(!PP.getAbilityUse())
|
if(!PP.getAbilityUse() || PP.getSuperBreakerMode() || PP.getSerratedStrikesMode() || PP.getTreeFellerMode() || PP.getGreenTerraMode() || PP.getBerserkMode() || PP.getGigaDrillBreakerMode())
|
||||||
return;
|
return;
|
||||||
if(mcPermissions.getInstance().miningAbility(player) && m.isMiningPick(player.getItemInHand()) && !PP.getPickaxePreparationMode())
|
if(mcPermissions.getInstance().miningAbility(player) && m.isMiningPick(player.getItemInHand()) && !PP.getPickaxePreparationMode())
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,7 @@ public class Taming
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: mcMMO
|
name: mcMMO
|
||||||
main: com.gmail.nossr50.mcMMO
|
main: com.gmail.nossr50.mcMMO
|
||||||
version: 1.1.17 ALPHA WIP #1
|
version: 1.1.17
|
||||||
softdepend: [Spout]
|
softdepend: [Spout]
|
||||||
author: nossr50
|
author: nossr50
|
||||||
description: mcMMO takes core Minecraft game mechanics and expands them to add an extensive RPG experience, the goal of the project has always been a quality RPG experience. Everything in mcMMO is carefully thought out and is constantly improving. mcMMO adds eleven skills to train in and level in, while also offering a high level of customization for server admins. There are countless features, including custom sounds, graphical elements, and more added when running mcMMO in conjunction with Spout. I carefully read feedback and evaluate the mechanics of mcMMO in every update to provide an ever-evolving experience.
|
description: mcMMO takes core Minecraft game mechanics and expands them to add an extensive RPG experience, the goal of the project has always been a quality RPG experience. Everything in mcMMO is carefully thought out and is constantly improving. mcMMO adds eleven skills to train in and level in, while also offering a high level of customization for server admins. There are countless features, including custom sounds, graphical elements, and more added when running mcMMO in conjunction with Spout. I carefully read feedback and evaluate the mechanics of mcMMO in every update to provide an ever-evolving experience.
|
||||||
|
Loading…
Reference in New Issue
Block a user