1
0
mirror of https://github.com/mcMMO-Dev/mcMMO.git synced 2026-02-18 01:42:32 +01:00

Compare commits

...

106 Commits

Author SHA1 Message Date
t00thpick1
8f1801bc4d To capfan - My biggest fan 2015-11-29 22:22:32 -05:00
t00thpick1
9718123292 Catchup the changelog 2015-11-12 19:19:57 -05:00
t00thpick1
420559efec Append to existing lore when crafting Flux Pickaxes. Fixes #2557 2015-11-12 19:13:27 -05:00
t00thpick1
f4b6d7845e Add config option to auto-truncate player skill levels that exceed the configured max level. Adds #2512
Also removes a good bit of magic numbering from FlatFileDatabaseManager
2015-11-12 19:10:30 -05:00
t00thpick1
b966529487 Merge pull request #2709 from JamieSinn/master
Strip colours from party chat when logging to console.
2015-11-12 17:43:34 -05:00
JamieSinn
9c7b83a52e Strip colours from party chat when logging to console. 2015-11-12 16:06:43 -05:00
t00thpick1
ac9447d439 This is actually not correct. 2015-11-04 16:31:30 -05:00
t00thpick1
a5bcc3ce58 Correctly identify tree species. Fixes #2667 2015-11-04 16:06:28 -05:00
t00thpick1
a020890244 Remove hardcoded nerf to treefeller. Fixes #2666 2015-11-04 15:53:38 -05:00
t00thpick1
616200f20f Fix compile 2015-11-04 15:48:42 -05:00
t00thpick1
1f9c3759e7 Merge pull request #2441 from wolfdate25/patch-2
Update locale_ko.properties.  Hope this is right, I cannot read it personally.
2015-11-04 15:46:55 -05:00
t00thpick1
9fb72cfea8 Merge pull request #2648 from EvilOlaf/patch-2
Update locale_de.properties
2015-11-04 15:46:13 -05:00
t00thpick1
dd84abe927 Merge pull request #2647 from EvilOlaf/patch-1
Missing bracket
2015-11-04 15:45:11 -05:00
t00thpick1
aaa69adb0c Merge pull request #2663 from MinelinkNetwork/fix-child-skill-level
Remove hardcoded limit for parent skill levels when calculating child…
2015-11-04 15:45:00 -05:00
t00thpick1
982ee13631 Merge pull request #2697 from SilverCory/master
Monitor falling blocks.
2015-11-04 15:44:45 -05:00
t00thpick1
8927e16b1f Fix skillreset argument validation. Fixes #2651 2015-11-04 15:43:07 -05:00
t00thpick1
dd01504111 Treat nether portal spawned mobs as spawner mobs. Fixes #2662 2015-11-04 15:37:17 -05:00
t00thpick1
50e727d591 Fix salvaging to return more than 1 item. Fixes #2627 2015-11-04 15:35:22 -05:00
t00thpick1
f84e98d836 Simulate block break for flux mining. Fixes #2668 2015-11-04 15:27:03 -05:00
t00thpick1
7e92905618 Comments so I don't forget why I did it like this again 2015-11-04 13:48:29 -05:00
t00thpick1
9b24dd306c Actually use Hylian Treasure config values. Fixes #2688 2015-11-04 13:35:25 -05:00
t00thpick1
aa796266a7 Don't remember what this is for, but it was in my repo so its probably important 2015-11-04 13:26:47 -05:00
Cory Redmond
a783d0dfc8 Monitor falling blocks. 2015-10-04 21:39:22 +01:00
Byteflux
5f21efb1cd Remove hardcoded limit for parent skill levels when calculating child skill level 2015-08-16 00:35:22 -07:00
Very Evil Olaf
8e2b8f111f Update locale_de.properties
Add missing space
`Fixen` can not be used in this context. `Reparatur` is slightly better.
2015-08-03 16:53:48 +02:00
Very Evil Olaf
08766a0ff7 Missing bracket 2015-08-03 15:17:52 +02:00
t00thpick1
5b19e2e9d2 Snapshot again for realz 2015-07-28 17:49:36 -04:00
t00thpick1
bef28583f3 Fix missed compile error. Re-release 1.5.03 2015-07-28 17:48:24 -04:00
t00thpick1
eff53d90ab We need to preserve block data with our double drops for silk touch. Fixes #2625 2015-07-25 22:30:22 -04:00
t00thpick1
2aade8b7ff Remove no longer needed DualSupport classes, we crossed that road long ago. 2015-07-25 22:29:19 -04:00
t00thpick1
de0ac51b3d This should ignore absorption damage for allied players. Fixes #2618 2015-07-25 21:59:10 -04:00
t00thpick1
b161a907a7 back to development 2015-07-25 16:53:38 -04:00
t00thpick1
397ec929aa Bump version for release 2015-07-25 16:52:26 -04:00
t00thpick1
f108de9ba2 Incorrect config key. 2015-07-25 16:32:44 -04:00
t00thpick1
e3a139f7bd Update website link 2015-07-18 11:51:53 -04:00
t00thpick1
90f8132030 Merge pull request #2540 from xion87/patch-2
Update locale_it.properties
2015-07-18 11:25:45 -04:00
t00thpick1
60d89c15e6 Merge pull request #2551 from lol768/patch-1
Escape apostrophes in localised strings
2015-07-18 11:24:59 -04:00
t00thpick1
58a0287be7 Merge pull request #2583 from lumis31/patch-1
Update locale_de.properties
2015-07-18 11:24:19 -04:00
t00thpick1
ac3b28da8b Merge pull request #2614 from ThundrRok/master
Fix for custom potions being missed in potion stage calculation. #2386
2015-07-18 11:22:48 -04:00
t00thpick1
12cb1e4161 Offload slightly more calculations to the async loading thread. kinda Fixes #2591 2015-07-18 11:18:42 -04:00
t00thpick1
4e013b44d8 Support offline player experience editing 2015-07-18 10:50:38 -04:00
t00thpick1
9934ab972e Clean up SQLDatabaseManager 2015-07-18 10:48:40 -04:00
t00thpick1
30adac5e63 Properly restore state when errors occur during uuid update 2015-07-18 10:41:55 -04:00
Stephen Jenkins
d3d7c254f4 Fix for custom potions being missed in potion stage calculation. #2386 2015-07-10 18:04:53 -04:00
t00thpick1
93ad040936 Syntax is important 2015-06-20 15:11:18 -04:00
t00thpick1
bfeac43f12 NULL uuids in flatfile should not be wiped as duplicates. Fixes #2594 2015-06-20 13:04:03 -04:00
t00thpick1
4388430491 When an older user no longer has a username that a new user now has, we will update the old entry to be _INVALID_OLD_USERNAME_, however we no longer strictly enforce name uniqueness, so people altering their DB's need to tweek with caution. Invalid old users will not display in the leaderboards. Fixes #2503 2015-06-20 12:57:01 -04:00
t00thpick1
b4e21a7817 Due to the unstable and volatile nature of pistons in the current versions of mc, we cannot reliably guarentee that we can track the position of blocks being moved by pistons, and therefore will no longer track piston moved blocks in the blockstore with 100% accuracy, and will instead just not refresh the potentially empty new blocks. This will not have any effect on regular usage of the plugin aside from 100% preventing any mcMMO related piston dupe bugs. Fixes #2565, #2582 2015-06-11 21:31:20 -04:00
t00thpick1
4fe41fe416 Check Item Type, not Material Type a second time. Fixes #2584 2015-06-11 21:15:40 -04:00
t00thpick1
d8184fb298 Properly calculate diff times for old user purge. Fixes #2541 2015-06-11 18:12:22 -04:00
lumis31
78dec51ad4 Update locale_de.properties
Major updates to the locale_de including:

Most important: added translations to ALL ABILITIES DESCRIPTIONS in german

Additionally:
-Adding a translation for the Alchemy skill
-Addition of translations for fishing
-removed salvage form repair
-added horses and holy hound to taming
->full translation to german except parties
For more changes please see the changelog at the beginnig of the file. No changes have been made to the existing translations except if the information was out of date due to the recent update to Minecraft 1.8. All translations are socially acceptable (usable for children).
2015-06-09 00:10:53 +02:00
lol768
de38826897 Escape apostrophes
"The java.text.MessageFormat class uses the apostrophe (\u0027) as an escape character. Consequently, you need to write two consecutive apostrophes in your translation if you wish to display a single apostrophe"
2015-04-25 22:59:33 +01:00
xion87
f63e793006 Update locale_it.properties
Fixed italian locale for use bow skill command
2015-04-21 09:46:51 +02:00
TfT_02
ecfdd75e36 This should be SNAPSHOT 2015-04-05 20:27:39 +02:00
TfT_02
90b31a29f5 We can simplify this!
Didn’t realize there was a event.getBlocks() method for
BlockPistonRetractEvent as well.
2015-03-22 14:49:51 +01:00
TfT_02
cfa0daefc5 Fix the issues with sticky pistons and slime blocks
This is a fix for issues #2419 and #2494
2015-03-21 19:24:06 +01:00
t00thpick1
4aeda6e9e8 Still not fully on track with the original event, but as we want them to see the potions we create, we can't be fully correct. However, correcting the behavior to decrement the ingredient after the event shouldn't harm anything. Fixes #2486 2015-03-18 16:23:07 -04:00
t00thpick1
4f1f10333f Use notification settings for critical hits Fixes #2498 2015-03-18 16:09:15 -04:00
t00thpick1
342c37a02c Merge pull request #2426 from zreed/master
Empty constructors don't take arguments  Sure why not.
2015-03-18 15:31:44 -04:00
t00thpick1
e347bc1c9e Short data, Fixed #1909 2015-03-18 15:28:57 -04:00
t00thpick1
42116f4467 Include license in builds 2015-03-18 03:56:46 -04:00
t00thpick1
7ce72bafb0 Merge pull request #2489 from isokissa3/master
Fixed duplication Bug #2489 
Tentatively pulling this as I assume its valid.
2015-03-18 03:51:35 -04:00
isokissa3
f76771f0a8 Fixed duplication bug #2419 (Correct fix) 2015-03-11 14:31:56 +02:00
isokissa3
6c29da94f3 Fixed duplication Bug #2419 2015-03-11 11:36:51 +02:00
t00thpick1
981523789e Add Debug and change a line 2015-03-09 14:20:52 -04:00
t00thpick1
d9aacfa059 Back to dev 2015-03-02 15:15:08 -05:00
t00thpick1
5efc5289f7 Version bump release 2015-03-02 15:14:16 -05:00
t00thpick1
1f68f4e654 More debug for rare cases where things don't work. 2015-02-23 20:37:03 -05:00
TfT_02
5670e6696a Archery distance XP bonus cannot exceed indefinitely anymore
Fixes #2465
2015-02-21 09:42:22 +01:00
t00thpick1
ca6dc5195d Properly convert SQL to Flatfile when UUIDs are null 2015-02-16 23:12:50 -05:00
t00thpick1
30ebe318e0 Since apparently we magically can no longer compile without these. 2015-02-16 22:13:32 -05:00
t00thpick1
a1c3f0d651 WHERE'S HARVEY DENT 2015-02-16 21:43:51 -05:00
t00thpick1
347e03d75e When did this break? It was working before. 2015-02-16 12:09:00 -05:00
t00thpick1
8543382bde We want answers for the issues. 2015-02-15 22:03:58 -05:00
t00thpick1
4f1004472c Possibly fix berserk bug 2015-02-15 22:03:58 -05:00
t00thpick1
7aee829b94 Merge pull request #2456 from ulumulu1510/patch-1
Resolve duplication Bug #2419
2015-02-15 12:34:08 -05:00
Benjamin
98701104d8 Resolve duplication Bug #2419
https://github.com/mcMMO-Dev/mcMMO/issues/2419
2015-02-11 20:17:08 +01:00
t00thpick1
7a14e61762 Fix flatfile UUID conversion I think. Fixes #2225, #2411 2015-01-31 14:38:49 -05:00
wolfwork
f42f5c31ed Update locale_ko.properties 2015-01-31 15:10:15 +09:00
t00thpick1
342662c944 Round 3: DeathMatch 2015-01-25 23:28:30 -05:00
t00thpick1
50088fe0bd Round 2 2015-01-25 23:04:02 -05:00
t00thpick1
687f87a748 No more opening inventories with ability tools. Fixes #2416 2015-01-25 22:55:18 -05:00
zreed
6815c66a0e Empty constructors don't take arguments 2015-01-22 07:14:14 -05:00
TfT_02
385fe1bb05 Added option for XP gained by killing bred animals
Fixes #2402
2015-01-10 12:31:13 +01:00
t00thpick1
eddadcc179 Properly allow searches by name without UUID 2015-01-01 23:56:30 -05:00
mjkaufer
9426f44cdd Added isUnarmed Method
Checks if the player is not holding a tool, as opposed to checking if
the player is holding air. This means that attacking with something such
as a dirt block would count as unarmed.
2014-12-29 16:31:18 +01:00
TfT_02
af7ff3df58 Make Archery distance multiplier configurable
Add #2385
2014-12-24 11:00:43 +01:00
TfT_02
7c0cc8794f Whoops, should've incremented these 2014-12-23 18:49:26 +01:00
TfT_02
eda18bc990 Only show the scoreboard tips a couple of times
We can assume a player knows how scoreboards work after showing them
the tips a few times across multiple login sessions

Adds #1833
2014-12-23 14:08:29 +01:00
TfT_02
a2c395db36 Fixed bug where MobHealthbarTypes were not saved 2014-12-23 14:07:10 +01:00
TfT_02
522b085499 Fix bug where no XP was granted when Flux Mining
Fixes #2359
2014-12-22 17:25:55 +01:00
TfT_02
3ea845cfd9 Changed Flux Mining mechanics
Previously, Flux Mining would get unlocked at a specified level with a
specified chance. Once unlocked, the player would have no control over
this ability and some players complained they would like to be able to
turn it on and off.

By adding a new furnace recipe, to craft a special pickaxe - a Flux
Pickaxe - this issue is solved. If a player doesn’t want to use Flux
Mining, they simply shouldn’t mine using a Flux Pickaxe.

Crafting a Flux Pickaxe is simple, just place one of the vanilla
pickaxes in a furnace and cook it up.

Every time the ability is successful, extra durability damage is dealt
to the tool. Just like with other abilities.

Adds #2320
2014-12-22 16:58:22 +01:00
TfT_02
93013b2db1 Fix an NPE when loading potion configs 2014-12-21 17:50:31 +01:00
TfT_02
d5a2dea06b Add option to shake items from player inventories 2014-12-20 23:55:49 +01:00
TfT_02
d188224c06 Make it possible to shake heads from players 2014-12-20 23:55:49 +01:00
TfT_02
3422c5d3eb Don't need this here 2014-12-20 19:14:52 +01:00
TfT_02
ebeebbde72 Randomize spawn location of Call of the Wild pets
So that when you’re spawning multiple pets at once, they don’t all
spawn at the same spot.
2014-12-20 19:14:52 +01:00
t00thpick1
e71eff852c Add ChatColor support for lore and custom item names. Add lore and custom item name support for potions and dyes. 2014-12-20 02:16:23 -05:00
t00thpick1
bfff5682b5 As a semi-temporary measure, lets move 1.8 specific objects into their own classes, so we can be 1.7 and 1.8 compatable. 2014-12-19 13:48:06 -05:00
t00thpick1
429a7d926a 1.8 changed the inheritance structure of Squids, this update resolves issues that cropped up from this change. 2014-12-18 18:15:02 -05:00
TfT_02
262e711bcc Add option for Chimaera Wings to ignore bed spawns
Adds #2365
2014-12-18 23:04:38 +01:00
t00thpick1
b44b1cc859 And back to development 2014-12-18 14:15:59 -05:00
t00thpick1
75dfec1236 Bump version for release build. 2014-12-18 14:14:58 -05:00
t00thpick1
8c2f3cff8f Silly me, prismarine isn't an ore. 2014-12-18 14:11:54 -05:00
t00thpick1
32336b712b Quick initial update for 1.8
Adds default configuration for new blocks and entities.
Updates a few hardcoded utilities to account for new blocks and entities.
2014-12-18 01:36:02 -05:00
t00thpick1
cfc51e9b96 use players for events 2014-12-17 22:34:42 -05:00
65 changed files with 2750 additions and 1613 deletions

View File

@@ -7,7 +7,50 @@ Key:
! Change
- Removal
Version 1.5.01-dev
Version 1.5.04-SNAPSHOT
+ Added option to config.yml to truncate existing player skill levels that exceed the skill level cap
+ Falling blocks persist mcMMO natural data
= Woodcutting double drops correctly identify acacia and dark oak logs
= Skill Reset command now correctly identifies arguments
= Hylian Treasure config options are now actually used
= Child skills now use parent skills configured skill caps properly
! Flux mining now simulates a block break event for other plugins to act upon
! Zombie Pigmen spawned from nether portals are now considered spawner mobs
! Flux Pickaxe lore now appends to existing lore as opposed to replacing it
! Party chat no longer displays colors when logged in server console
- Treefeller no longer lowers exp for big trees
Version 1.5.03
= Fixed bug where absorption hearts could be attacked by allied players
= Fixed bug where new forms of stone would drop the wrong type when mined with Silk Touch
= Fixed bug where blocks would not get tracked correctly when using sticky pistons and slime blocks in certain situations
= Fixed bug where config value for Daze damage was ignored
= Fixed UUID updater to not lose data on errors
= Fixed bug where uuid update could result in large amounts of user data being deleted
= Fixed bug where custom potions were missed in potion stage calculation
= Fixed piston dupe bugs permanently
= Fixed bug involving user name changes
= Fixed old user purge to properly calculate months
= Fixed bug where Repair would incorrectly check items
= Fixed bug where apostrophes in locale files would not read correctly
= Fixed bug where treasure data was limited to 255 instead of Short.MAX_VALUE
! Moved more user loading calculations to async loading thread to reduce lag on login
Version 1.5.02
+ Added option to config.yml for Chimaera Wings to stop using bed spawn points
+ Added option to config.yml to let non-tools in hand count as unarmed
+ Added option to experience.yml to control XP gained by killing bred animals
+ Added support for 1.8 mobs and features
= Fixed bug where no Mining XP was granted when Flux Mining was successful
= Fixed bug with UUID conversions in Flatfile
= Fixed a couple Dupe bugs that were introduced recently
= Fixed bug where MobHealthbarTypes were not saved between server restarts
! Changed Flux Mining mechanics. In order to use the ability, you need to infuse a pickaxe with furnace powers first.
! Scoreboard tips are only shown a couple of times to the player, instead of once per login session
! Changed Archery distance multiplier to be configurable
! Archery distance XP bonus cannot exceed indefinitely anymore
Version 1.5.01
+ Added new child skill; Salvage
+ Added UUID support!
+ Added SQL connection pooling and async loading!
@@ -56,6 +99,7 @@ Version 1.5.01-dev
! Changed Alchemy XP distribution. XP is granted based on the stage of the potion.
! Changed behavior of the Blast Mining ability "Demolition Expert"; now only decreases damage for the ability user
! Updated for new getOnlinePlayers() behavior
! Updated for new blocks and entities
! Changed McMMOPlayerDeathPenaltyEvent to get fired after hardcore penalty calculations, use McMMOPlayerPreDeathPenaltyEvent for old behavior
! Moved Refresh_Chunks setting from hidden.yml to config.yml
- Removed salvage ability from Repair, salvage has it's own (child) skill now

View File

@@ -10,11 +10,10 @@ The goal of mcMMO is to take core Minecraft game mechanics and expand them into
## About the Team
mcMMO is currently developed by a team of individuals from all over the world.
### Glorious Leader
[![gmcferrin](http://www.gravatar.com/avatar/b64c52daf25d206b27650788b5813b7b.png)]
(https://github.com/gmcferrin)
### Developers
[![gmcferrin](http://www.gravatar.com/avatar/b64c52daf25d206b27650788b5813b7b.png)]
(https://github.com/gmcferrin)
[![bm01](http://www.gravatar.com/avatar/ec8146f5358177f12e9a252271bbc391.png)]
(https://github.com/bm01)
[![Glitchfinder](http://www.gravatar.com/avatar/5aa4cce22f72ae9c002ecec30f061d00.png)]
@@ -48,4 +47,4 @@ Required Libraries:
* EMetrics
* Bukkit
http://dev.bukkit.org/server-mods/mcmmo for more up to date information.
http://www.spigotmc.org/resources/mcmmo.2445/ for more up to date information.

30
pom.xml
View File

@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId>
<version>1.5.01-SNAPSHOT</version>
<version>1.5.04-SNAPSHOT</version>
<name>mcMMO</name>
<url>https://github.com/mcMMO-Dev/mcMMO</url>
<issueManagement>
@@ -38,6 +38,14 @@
<include>*.yml</include>
</includes>
</resource>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>${basedir}</directory>
<includes>
<include>LICENSE</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
@@ -120,12 +128,8 @@
</build>
<repositories>
<repository>
<id>bukkit-repo</id>
<url>http://repo.bukkit.org/content/groups/public/</url>
</repository>
<repository>
<id>md_5-releases</id>
<url>http://repo.md-5.net/content/repositories/releases/</url>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>Plugin MetricsExtension</id>
@@ -136,7 +140,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.7.10-R0.1-SNAPSHOT</version>
<version>1.8-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
@@ -160,19 +164,15 @@
</dependencies>
<distributionManagement>
<repository>
<id>md_5-releases</id>
<url>http://repo.md-5.net/content/repositories/releases/</url>
<id>drtshock-releases</id>
<url>https://ci.drtshock.net/plugin/repository/everything/com/gmail/nossr50/mcMMO/</url>
</repository>
<snapshotRepository>
<id>md_5-snapshots</id>
<url>http://repo.md-5.net/content/repositories/snapshots/</url>
</snapshotRepository>
</distributionManagement>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<ciManagement>
<system>Jenkins</system>
<url>http://ci.ecocitycraft.com/job/mcMMO</url>
<url>https://ci.drtshock.net/job/mcmmo/</url>
</ciManagement>
</project>

View File

@@ -2,7 +2,9 @@ package com.gmail.nossr50.commands.experience;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@@ -16,7 +18,6 @@ import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.google.common.collect.ImmutableList;
public abstract class ExperienceCommand implements TabExecutor {
@@ -71,7 +72,12 @@ public abstract class ExperienceCommand implements TabExecutor {
// If the mcMMOPlayer doesn't exist, create a temporary profile and check if it's present in the database. If it's not, abort the process.
if (mcMMOPlayer == null) {
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, false);
UUID uuid = null;
OfflinePlayer player = mcMMO.p.getServer().getOfflinePlayer(playerName);
if (player != null) {
uuid = player.getUniqueId();
}
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, uuid, false);
if (CommandUtils.unloadedProfile(sender, profile)) {
return true;

View File

@@ -2,7 +2,9 @@ package com.gmail.nossr50.commands.experience;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
@@ -19,7 +21,6 @@ import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.commands.CommandUtils;
import com.gmail.nossr50.util.player.UserManager;
import com.google.common.collect.ImmutableList;
/**
@@ -29,6 +30,7 @@ import com.google.common.collect.ImmutableList;
public class SkillresetCommand implements TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
SkillType skill;
switch (args.length) {
case 1:
if (CommandUtils.noConsoleUsage(sender)) {
@@ -44,7 +46,14 @@ public class SkillresetCommand implements TabExecutor {
return true;
}
editValues((Player) sender, UserManager.getPlayer(sender.getName()).getProfile(), SkillType.getSkill(args[0]));
if (args[0].equalsIgnoreCase("all")) {
skill = null;
}
else {
skill = SkillType.getSkill(args[1]);
}
editValues((Player) sender, UserManager.getPlayer(sender.getName()).getProfile(), skill);
return true;
case 2:
@@ -57,7 +66,6 @@ public class SkillresetCommand implements TabExecutor {
return true;
}
SkillType skill;
if (args[1].equalsIgnoreCase("all")) {
skill = null;
}
@@ -70,7 +78,12 @@ public class SkillresetCommand implements TabExecutor {
// If the mcMMOPlayer doesn't exist, create a temporary profile and check if it's present in the database. If it's not, abort the process.
if (mcMMOPlayer == null) {
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, false);
UUID uuid = null;
OfflinePlayer player = mcMMO.p.getServer().getOfflinePlayer(playerName);
if (player != null) {
uuid = player.getUniqueId();
}
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(playerName, uuid, false);
if (CommandUtils.unloadedProfile(sender, profile)) {
return true;
@@ -134,7 +147,7 @@ public class SkillresetCommand implements TabExecutor {
}
private boolean validateArguments(CommandSender sender, String skillName) {
return !(CommandUtils.isInvalidSkill(sender, skillName) && !skillName.equalsIgnoreCase("all"));
return skillName.equalsIgnoreCase("all") || !CommandUtils.isInvalidSkill(sender, skillName);
}
protected static void handleSenderMessage(CommandSender sender, String playerName, SkillType skill) {

View File

@@ -280,6 +280,7 @@ public class Config extends AutoUpdateConfigLoader {
/* Scoreboards */
public boolean getPowerLevelTagsEnabled() { return config.getBoolean("Scoreboard.Power_Level_Tags", false); }
public boolean getAllowKeepBoard() { return config.getBoolean("Scoreboard.Allow_Keep", true); }
public int getTipsAmount() { return config.getInt("Scoreboard.Tips_Amount", 5); }
public boolean getShowStatsAfterLogin() { return config.getBoolean("Scoreboard.Show_Stats_After_Login", false); }
public boolean getScoreboardRainbows() { return config.getBoolean("Scoreboard.Rainbows", false); }
public boolean getShowAbilityNames() { return config.getBoolean("Scoreboard.Ability_Names", true); }
@@ -372,16 +373,21 @@ public class Config extends AutoUpdateConfigLoader {
public Material getChimaeraItem() { return Material.matchMaterial(config.getString("Items.Chimaera_Wing.Item_Name", "Feather")); }
public boolean getChimaeraEnabled() { return config.getBoolean("Items.Chimaera_Wing.Enabled", true); }
public boolean getChimaeraPreventUseUnderground() { return config.getBoolean("Items.Chimaera_Wing.Prevent_Use_Underground", true); }
public boolean getChimaeraUseBedSpawn() { return config.getBoolean("Items.Chimaera_Wing.Use_Bed_Spawn", true); }
public int getChimaeraCooldown() { return config.getInt("Items.Chimaera_Wing.Cooldown", 240); }
public int getChimaeraWarmup() { return config.getInt("Items.Chimaera_Wing.Warmup", 5); }
public int getChimaeraRecentlyHurtCooldown() { return config.getInt("Items.Chimaera_Wing.RecentlyHurt_Cooldown", 60); }
public boolean getChimaeraSoundEnabled() { return config.getBoolean("Items.Chimaera_Wing.Sound_Enabled", true); }
public boolean getFluxPickaxeEnabled() { return config.getBoolean("Items.Flux_Pickaxe.Enabled", true); }
public boolean getFluxPickaxeSoundEnabled() { return config.getBoolean("Items.Flux_Pickaxe.Sound_Enabled", true); }
/* Particles */
public boolean getAbilityActivationEffectEnabled() { return config.getBoolean("Particles.Ability_Activation", true); }
public boolean getAbilityDeactivationEffectEnabled() { return config.getBoolean("Particles.Ability_Deactivation", true); }
public boolean getDodgeEffectEnabled() { return config.getBoolean("Particles.Dodge", true); }
public boolean getBleedEffectEnabled() { return config.getBoolean("Particles.Bleed", true); }
public boolean getDodgeEffectEnabled() { return config.getBoolean("Particles.Dodge", true); }
public boolean getFluxEffectEnabled() { return config.getBoolean("Particles.Flux", true); }
public boolean getGreaterImpactEffectEnabled() { return config.getBoolean("Particles.Greater_Impact", true); }
public boolean getCallOfTheWildEffectEnabled() { return config.getBoolean("Particles.Call_of_the_Wild", true); }
public boolean getLevelUpEffectsEnabled() { return config.getBoolean("Particles.LevelUp_Enabled", true); }
@@ -492,6 +498,7 @@ public class Config extends AutoUpdateConfigLoader {
/* Unarmed */
public boolean getUnarmedBlockCrackerSmoothbrickToCracked() { return config.getBoolean("Skills.Unarmed.Block_Cracker.SmoothBrick_To_CrackedBrick", true); }
public boolean getUnarmedItemPickupDisabled() { return config.getBoolean("Skills.Unarmed.Item_Pickup_Disabled_Full_Inventory", true); }
public boolean getUnarmedItemsAsUnarmed() { return config.getBoolean("Skills.Unarmed.Items_As_Unarmed", false); }
/* Taming */
public Material getTamingCOTWMaterial(EntityType type) { return Material.matchMaterial(config.getString("Skills.Taming.Call_Of_The_Wild." + StringUtils.getPrettyEntityTypeString(type) + ".Item_Material")); }
@@ -521,6 +528,8 @@ public class Config extends AutoUpdateConfigLoader {
return (cap <= 0) ? Integer.MAX_VALUE : cap;
}
public boolean getTruncateSkills() { return config.getBoolean("General.TruncateSkills", false); }
/* PVP & PVE Settings */
public boolean getPVPEnabled(SkillType skill) { return config.getBoolean("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVP", true); }
public boolean getPVEEnabled(SkillType skill) { return config.getBoolean("Skills." + StringUtils.getCapitalized(skill.toString()) + ".Enabled_For_PVE", true); }

View File

@@ -72,6 +72,11 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
reason.add("Experience_Formula.Mobspawners.Multiplier should be at least 0!");
}
/* Bred Mob modifier */
if (getBredMobXpMultiplier() < 0) {
reason.add("Experience_Formula.Breeding.Multiplier should be at least 0!");
}
/* Conversion */
if (getExpModifier() <= 0) {
reason.add("Conversion.Exp_Modifier should be greater than 0!");
@@ -88,6 +93,11 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
}
}
/* Archery */
if (getArcheryDistanceMultiplier() < 0) {
reason.add("Experience.Archery.Distance_Multiplier should be at least 0!");
}
/* Combat XP Multipliers */
if (getAnimalsXP() < 0) {
reason.add("Experience.Combat.Multiplier.Animals should be at least 0!");
@@ -172,6 +182,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* Spawned Mob modifier */
public double getSpawnedMobXpMultiplier() { return config.getDouble("Experience_Formula.Mobspawners.Multiplier", 0.0); }
public double getBredMobXpMultiplier() { return config.getDouble("Experience_Formula.Breeding.Multiplier", 1.0); }
/* Skill modifiers */
public double getFormulaSkillModifier(SkillType skill) { return config.getDouble("Experience_Formula.Modifier." + StringUtils.getCapitalized(skill.toString())); }
@@ -198,6 +209,7 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
public double getCombatXP(EntityType entity) { return config.getDouble("Experience.Combat.Multiplier." + StringUtils.getPrettyEntityTypeString(entity).replace(" ", "_")); }
public double getAnimalsXP() { return config.getDouble("Experience.Combat.Multiplier.Animals", 1.0); }
public double getWitherSkeletonXP() { return config.getDouble("Experience.Combat.Multiplier.Wither_Skeleton", 4.0); }
public double getElderGuardianXP() { return config.getDouble("Experience.Combat.Multiplier.Elder_Guardian", 4.0); }
/* Materials */
public int getXp(SkillType skill, Material material) { return config.getInt("Experience." + StringUtils.getCapitalized(skill.toString()) + "." + StringUtils.getPrettyItemString(material).replace(" ", "_")); }
@@ -212,6 +224,9 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
/* Alchemy */
public double getPotionXP(PotionStage stage) { return config.getDouble("Experience.Alchemy.Potion_Stage_" + stage.toNumerical(), 10D); }
/* Archery */
public double getArcheryDistanceMultiplier() { return config.getDouble("Experience.Archery.Distance_Multiplier", 0.025); }
/* Excavation */
public int getDirtAndSandXp(MaterialData data) {
Material type = data.getItemType();
@@ -368,4 +383,5 @@ public class ExperienceConfig extends AutoUpdateConfigLoader {
public int getWoodcuttingTreeXP(TreeSpecies species) { return config.getInt("Experience.Woodcutting." + StringUtils.getPrettyTreeSpeciesString(species).replace(" ", "_")); }
public int getWoodcuttingXPHugeBrownMushroom() { return config.getInt("Experience.Woodcutting.Huge_Mushroom_Brown", 70); }
public int getWoodcuttingXPHugeRedMushroom() { return config.getInt("Experience.Woodcutting.Huge_Mushroom_Red", 70); }
}

View File

@@ -5,6 +5,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
@@ -117,11 +118,14 @@ public class PotionConfig extends ConfigLoader {
short dataValue = Short.parseShort(potion_section.getName());
String name = potion_section.getString("Name");
if (name != null) {
name = ChatColor.translateAlternateColorCodes('&', name);
}
List<String> lore = new ArrayList<String>();
if (potion_section.contains("Lore")) {
for (String line : potion_section.getStringList("Lore")) {
lore.add(line);
lore.add(ChatColor.translateAlternateColorCodes('&', line));
}
}

View File

@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
@@ -56,6 +57,7 @@ public class TreasureConfig extends ConfigLoader {
public List<ShakeTreasure> shakeFromMushroomCow = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromPig = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromPigZombie = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromPlayer = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromSheep = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromSkeleton = new ArrayList<ShakeTreasure>();
public List<ShakeTreasure> shakeFromSlime = new ArrayList<ShakeTreasure>();
@@ -174,12 +176,17 @@ public class TreasureConfig extends ConfigLoader {
else if (materialName.contains("INK_SACK")) {
material = Material.INK_SACK;
}
else if (materialName.contains("INVENTORY")) {
// Use magic material BED_BLOCK to know that we're grabbing something from the inventory and not a normal treasure
shakeFromPlayer.add(new ShakeTreasure(new ItemStack(Material.BED_BLOCK, 1, (byte) 0), 1, getInventoryStealDropChance(), getInventoryStealDropLevel()));
continue;
}
else {
material = Material.matchMaterial(materialName);
}
int amount = config.getInt(type + "." + treasureName + ".Amount");
short data = (treasureInfo.length == 2) ? Byte.valueOf(treasureInfo[1]) : (short) config.getInt(type + "." + treasureName + ".Data");
short data = (treasureInfo.length == 2) ? Short.parseShort(treasureInfo[1]) : (short) config.getInt(type + "." + treasureName + ".Data");
if (material == null) {
reason.add("Invalid material: " + materialName);
@@ -236,6 +243,22 @@ public class TreasureConfig extends ConfigLoader {
try {
item = new Potion(PotionType.valueOf(potionType.toUpperCase().trim())).toItemStack(amount);
if (config.contains(type + "." + treasureName + ".Custom_Name")) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
item.setItemMeta(itemMeta);
}
if (config.contains(type + "." + treasureName + ".Lore")) {
ItemMeta itemMeta = item.getItemMeta();
List<String> lore = new ArrayList<String>();
for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', s));
}
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
}
}
catch (IllegalArgumentException ex) {
reason.add("Invalid Potion_Type: " + potionType);
@@ -249,6 +272,22 @@ public class TreasureConfig extends ConfigLoader {
dye.setColor(DyeColor.valueOf(color.toUpperCase().trim()));
item = dye.toItemStack(amount);
if (config.contains(type + "." + treasureName + ".Custom_Name")) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
item.setItemMeta(itemMeta);
}
if (config.contains(type + "." + treasureName + ".Lore")) {
ItemMeta itemMeta = item.getItemMeta();
List<String> lore = new ArrayList<String>();
for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', s));
}
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
}
}
catch (IllegalArgumentException ex) {
reason.add("Invalid Dye_Color: " + color);
@@ -259,13 +298,17 @@ public class TreasureConfig extends ConfigLoader {
if (config.contains(type + "." + treasureName + ".Custom_Name")) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(config.getString(type + "." + treasureName + ".Custom_Name"));
itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', config.getString(type + "." + treasureName + ".Custom_Name")));
item.setItemMeta(itemMeta);
}
if (config.contains(type + "." + treasureName + ".Lore")) {
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setLore(config.getStringList(type + "." + treasureName + ".Lore"));
List<String> lore = new ArrayList<String>();
for (String s : config.getStringList(type + "." + treasureName + ".Lore")) {
lore.add(ChatColor.translateAlternateColorCodes('&', s));
}
itemMeta.setLore(lore);
item.setItemMeta(itemMeta);
}
}
@@ -316,6 +359,9 @@ public class TreasureConfig extends ConfigLoader {
else if (type.equals("Shake.PIG_ZOMBIE")) {
shakeFromPigZombie.add(shakeTreasure);
}
else if (type.equals("Shake.PLAYER")) {
shakeFromPlayer.add(shakeTreasure);
}
else if (type.equals("Shake.SHEEP")) {
shakeFromSheep.add(shakeTreasure);
}
@@ -435,6 +481,11 @@ public class TreasureConfig extends ConfigLoader {
}
}
public boolean getInventoryStealEnabled() { return config.contains("Shake.PLAYER.INVENTORY"); }
public boolean getInventoryStealStacks() { return config.getBoolean("Shake.PLAYER.INVENTORY.Whole_Stacks"); }
public double getInventoryStealDropChance() { return config.getDouble("Shake.PLAYER.INVENTORY.Drop_Chance"); }
public int getInventoryStealDropLevel() { return config.getInt("Shake.PLAYER.INVENTORY.Drop_Level"); }
public double getItemDropRate(int tier, Rarity rarity) { return config.getDouble("Item_Drop_Rates.Tier_" + tier + "." + rarity.toString()); }
public double getEnchantmentDropRate(int tier, Rarity rarity) { return config.getDouble("Enchantment_Drop_Rates.Tier_" + tier + "." + rarity.toString()); }
}

View File

@@ -11,8 +11,8 @@ import com.gmail.nossr50.datatypes.player.PlayerProfile;
import com.gmail.nossr50.datatypes.skills.SkillType;
public interface DatabaseManager {
// One month in seconds
public final long PURGE_TIME = 2630000L * Config.getInstance().getOldUsersCutoff();
// One month in milliseconds
public final long PURGE_TIME = 2630000000L * Config.getInstance().getOldUsersCutoff();
// During convertUsers, how often to output a status
public final int progressInterval = 200;

View File

@@ -44,7 +44,7 @@ public class DatabaseManagerFactory {
*/
public static void setCustomDatabaseManagerClass(Class<? extends DatabaseManager> clazz) {
try {
clazz.getConstructor((Class<?>) null);
clazz.getConstructor();
customManager = clazz;
}
catch (Throwable e) {
@@ -78,10 +78,10 @@ public class DatabaseManagerFactory {
}
public static DatabaseManager createDefaultCustomDatabaseManager() throws Throwable {
return customManager.getConstructor((Class<?>) null).newInstance((Object[]) null);
return customManager.getConstructor().newInstance();
}
public static DatabaseManager createCustomDatabaseManager(Class<? extends DatabaseManager> clazz) throws Throwable {
return clazz.getConstructor((Class<?>) null).newInstance((Object[]) null);
return clazz.getConstructor().newInstance();
}
}

View File

@@ -7,6 +7,7 @@ import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap;
@@ -138,7 +139,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
String[] character = line.split(":");
String name = character[0];
String name = character[USERNAME];
long lastPlayed = 0;
boolean rewrite = false;
try {
@@ -213,7 +214,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
// Write out the same file but when we get to the player we want to remove, we skip his line.
if (!worked && line.split(":")[0].equalsIgnoreCase(playerName)) {
if (!worked && line.split(":")[USERNAME].equalsIgnoreCase(playerName)) {
mcMMO.p.getLogger().info("User found, removing...");
worked = true;
continue; // Skip the player
@@ -272,7 +273,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
// Read the line in and copy it to the output if it's not the player we want to edit
String[] character = line.split(":");
if (!character[41].equalsIgnoreCase(uuid.toString()) && !character[0].equalsIgnoreCase(playerName)) {
if (!(uuid != null && character[UUID_INDEX].equalsIgnoreCase(uuid.toString())) && !character[USERNAME].equalsIgnoreCase(playerName)) {
writer.append(line).append("\r\n");
}
else {
@@ -319,7 +320,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
writer.append(mobHealthbarType == null ? Config.getInstance().getMobHealthbarDefault().toString() : mobHealthbarType.toString()).append(":");
writer.append(profile.getSkillLevel(SkillType.ALCHEMY)).append(":");
writer.append(profile.getSkillXpLevel(SkillType.ALCHEMY)).append(":");
writer.append(uuid.toString()).append(":");
writer.append(uuid != null ? uuid.toString() : "NULL").append(":");
writer.append(profile.getScoreboardTipsShown()).append(":");
writer.append("\r\n");
}
}
@@ -426,7 +428,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
out.append("0:"); // Alchemy
out.append("0:"); // AlchemyXp
out.append(uuid != null ? uuid.toString() : "NULL").append(":"); // UUID
out.append("0:"); // Scoreboard tips shown
// Add more in the same format as the line above
out.newLine();
@@ -472,20 +474,20 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Compare names because we don't have a valid uuid for that player even
// if input uuid is not null
if (character[41].equalsIgnoreCase("NULL")) {
if (!character[0].equalsIgnoreCase(playerName)) {
if (character[UUID_INDEX].equalsIgnoreCase("NULL")) {
if (!character[USERNAME].equalsIgnoreCase(playerName)) {
continue;
}
}
// If input uuid is not null then we should compare uuids
else if ((uuid != null && !character[41].equalsIgnoreCase(uuid.toString())) || (uuid == null && !character[0].equalsIgnoreCase(playerName))) {
else if ((uuid != null && !character[UUID_INDEX].equalsIgnoreCase(uuid.toString())) || (uuid == null && !character[USERNAME].equalsIgnoreCase(playerName))) {
continue;
}
// Update playerName in database after name change
if (!character[0].equalsIgnoreCase(playerName)) {
mcMMO.p.debug("Name change detected: " + character[0] + " => " + playerName);
character[0] = playerName;
if (!character[USERNAME].equalsIgnoreCase(playerName)) {
mcMMO.p.debug("Name change detected: " + character[USERNAME] + " => " + playerName);
character[USERNAME] = playerName;
}
return loadFromLine(character);
@@ -571,6 +573,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
public boolean saveUserUUID(String userName, UUID uuid) {
boolean worked = false;
int i = 0;
BufferedReader in = null;
FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath();
@@ -583,17 +586,18 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
String[] character = line.split(":");
if (!worked && character[0].equalsIgnoreCase(userName)) {
if (!worked && character[USERNAME].equalsIgnoreCase(userName)) {
if (character.length < 42) {
mcMMO.p.getLogger().severe("Could not update UUID for " + userName + "!");
mcMMO.p.getLogger().severe("Database entry is invalid.");
break;
continue;
}
line = line.replace(character[41], uuid.toString());
line = line.replace(character[UUID_INDEX], uuid.toString());
worked = true;
}
i++;
writer.append(line).append("\r\n");
}
@@ -604,6 +608,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().severe("Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?)" + e.toString());
}
finally {
mcMMO.p.getLogger().info(i + " entries written while saving UUID for " + userName);
if (in != null) {
try {
in.close();
@@ -630,6 +635,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
BufferedReader in = null;
FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath();
int i = 0;
synchronized (fileWritingLock) {
try {
@@ -637,19 +643,20 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
StringBuilder writer = new StringBuilder();
String line;
while (((line = in.readLine()) != null) && !fetchedUUIDs.isEmpty()) {
while (((line = in.readLine()) != null)) {
String[] character = line.split(":");
if (fetchedUUIDs.containsKey(character[0])) {
if (!fetchedUUIDs.isEmpty() && fetchedUUIDs.containsKey(character[USERNAME])) {
if (character.length < 42) {
mcMMO.p.getLogger().severe("Could not update UUID for " + character[0] + "!");
mcMMO.p.getLogger().severe("Could not update UUID for " + character[USERNAME] + "!");
mcMMO.p.getLogger().severe("Database entry is invalid.");
continue;
}
character[41] = fetchedUUIDs.remove(character[0]).toString();
character[UUID_INDEX] = fetchedUUIDs.remove(character[USERNAME]).toString();
line = new StringBuilder(org.apache.commons.lang.StringUtils.join(character, ":")).append(":").toString();
}
i++;
writer.append(line).append("\r\n");
}
@@ -660,6 +667,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().severe("Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?)" + e.toString());
}
finally {
mcMMO.p.getLogger().info(i + " entries written while saving UUID batch");
if (in != null) {
try {
in.close();
@@ -695,7 +703,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
String[] character = line.split(":");
users.add(character[0]);
users.add(character[USERNAME]);
}
}
catch (Exception e) {
@@ -753,7 +761,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
while ((line = in.readLine()) != null) {
String[] data = line.split(":");
playerName = data[0];
playerName = data[USERNAME];
int powerLevel = 0;
Map<SkillType, Integer> skills = getSkillMapFromLine(data);
@@ -849,15 +857,20 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
if (line.charAt(line.length() - 1) != ':') {
line = line.concat(":");
}
boolean updated = false;
String[] character = line.split(":");
// Prevent the same username from being present multiple times
if (!usernames.add(character[0])) {
continue;
if (!usernames.add(character[USERNAME])) {
character[USERNAME] = "_INVALID_OLD_USERNAME_'";
updated = true;
if (character.length < UUID_INDEX + 1 || character[UUID_INDEX].equals("NULL")) {
continue;
}
}
// Prevent the same player from being present multiple times
if (character.length == 42 && (!character[41].isEmpty() && !players.add(character[41]))) {
if (character.length >= 42 && (!character[UUID_INDEX].isEmpty() && !character[UUID_INDEX].equals("NULL") && !players.add(character[UUID_INDEX]))) {
continue;
}
@@ -869,39 +882,54 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
String oldVersion = null;
if (character.length <= 33) {
// Introduction of HUDType
// Version 1.1.06
// commit 78f79213cdd7190cd11ae54526f3b4ea42078e8a
line = line.concat(" :");
character = line.split(":");
oldVersion = "1.1.06";
}
if (!character[33].isEmpty()) {
if (character.length > 33 && !character[33].isEmpty()) {
// Removal of Spout Support
// Version 1.4.07-dev2
// commit 7bac0e2ca5143bce84dc160617fed97f0b1cb968
line = line.replace(character[33], "");
character[33] = "";
if (oldVersion == null) {
oldVersion = "1.4.07";
}
updated = true;
}
if (Config.getInstance().getTruncateSkills()) {
for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
int index = getSkillIndex(skill);
if (index >= character.length) {
continue;
}
int cap = Config.getInstance().getLevelCap(skill);
if (Integer.valueOf(character[index]) > cap) {
mcMMO.p.getLogger().warning("Truncating " + skill.getName() + " to configured max level for player " + character[USERNAME]);
character[index] = cap + "";
updated = true;
}
}
}
// If they're valid, rewrite them to the file.
if (character.length == 42) {
if (!updated && character.length == 43) {
writer.append(line).append("\r\n");
continue;
}
StringBuilder newLine = new StringBuilder(line);
if (character.length <= 33) {
// Introduction of HUDType
// Version 1.1.06
// commit 78f79213cdd7190cd11ae54526f3b4ea42078e8a
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = "";
oldVersion = "1.1.06";
}
if (character.length <= 35) {
// Introduction of Fishing
// Version 1.2.00
// commit a814b57311bc7734661109f0e77fc8bab3a0bd29
newLine.append(0).append(":");
newLine.append(0).append(":");
character = Arrays.copyOf(character, character.length + 2);
character[character.length - 1] = "0";
character[character.length - 2] = "0";
if (oldVersion == null) {
oldVersion = "1.2.00";
}
@@ -910,7 +938,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Introduction of Blast Mining cooldowns
// Version 1.3.00-dev
// commit fadbaf429d6b4764b8f1ad0efaa524a090e82ef5
newLine.append(0).append(":");
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = "0";
if (oldVersion == null) {
oldVersion = "1.3.00";
}
@@ -920,7 +949,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Version 1.4.00-dev
// commmit 3f6c07ba6aaf44e388cc3b882cac3d8f51d0ac28
// XXX Cannot create an OfflinePlayer at startup, use 0 and fix in purge
newLine.append("0").append(":");
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = "0";
if (oldVersion == null) {
oldVersion = "1.4.00";
}
@@ -929,7 +959,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Addition of mob healthbars
// Version 1.4.06
// commit da29185b7dc7e0d992754bba555576d48fa08aa6
newLine.append(Config.getInstance().getMobHealthbarDefault().toString()).append(":");
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = Config.getInstance().getMobHealthbarDefault().toString();
if (oldVersion == null) {
oldVersion = "1.4.06";
}
@@ -937,8 +968,9 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
if (character.length <= 39) {
// Addition of Alchemy
// Version 1.4.08
newLine.append("0").append(":");
newLine.append("0").append(":");
character = Arrays.copyOf(character, character.length + 2);
character[character.length - 1] = "0";
character[character.length - 2] = "0";
if (oldVersion == null) {
oldVersion = "1.4.08";
}
@@ -947,61 +979,75 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
// Addition of UUIDs
// Version 1.5.01
// Add a value because otherwise it gets removed
newLine.append("NULL:");
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = "NULL";
if (oldVersion == null) {
oldVersion = "1.5.01";
}
}
if (character.length <= 42) {
// Addition of scoreboard tips auto disable
// Version 1.5.02
character = Arrays.copyOf(character, character.length + 1);
character[character.length - 1] = "0";
if (oldVersion == null) {
oldVersion = "1.5.02";
}
}
// Remove any blanks that shouldn't be there, and validate the other fields
String[] newCharacter = newLine.toString().split(":");
boolean corrupted = false;
for (int i = 0; i < newCharacter.length; i++) {
if (newCharacter[i].isEmpty() && !(i == 2 || i == 3 || i == 23 || i == 33 || i == 41)) {
for (int i = 0; i < character.length; i++) {
if (character[i].isEmpty() && !(i == 2 || i == 3 || i == 23 || i == 33 || i == 41)) {
corrupted = true;
if (newCharacter.length != 42) {
newCharacter = (String[]) ArrayUtils.remove(newCharacter, i);
if (i == 37) {
character[i] = String.valueOf(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR);
}
else if (i == 38) {
character[i] = Config.getInstance().getMobHealthbarDefault().toString();
}
else {
if (i == 37) {
newCharacter[i] = String.valueOf(System.currentTimeMillis() / Misc.TIME_CONVERSION_FACTOR);
}
else if (i == 38) {
newCharacter[i] = Config.getInstance().getMobHealthbarDefault().toString();
}
else {
newCharacter[i] = "0";
}
character[i] = "0";
}
}
if (StringUtils.isInt(newCharacter[i]) && i == 38) {
if (StringUtils.isInt(character[i]) && i == 38) {
corrupted = true;
newCharacter[i] = Config.getInstance().getMobHealthbarDefault().toString();
character[i] = Config.getInstance().getMobHealthbarDefault().toString();
}
if (!StringUtils.isInt(newCharacter[i]) && !(i == 0 || i == 2 || i == 3 || i == 23 || i == 33 || i == 38 || i == 41)) {
if (!StringUtils.isInt(character[i]) && !(i == 0 || i == 2 || i == 3 || i == 23 || i == 33 || i == 38 || i == 41)) {
corrupted = true;
newCharacter[i] = "0";
character[i] = "0";
}
}
if (corrupted) {
mcMMO.p.debug("Updating corrupted database line for player " + newCharacter[0]);
mcMMO.p.debug("Updating corrupted database line for player " + character[USERNAME]);
}
if (oldVersion != null) {
mcMMO.p.debug("Updating database line from before version " + oldVersion + " for player " + character[0]);
mcMMO.p.debug("Updating database line from before version " + oldVersion + " for player " + character[USERNAME]);
}
if (corrupted || oldVersion != null) {
newLine = new StringBuilder(org.apache.commons.lang.StringUtils.join(newCharacter, ":"));
newLine = newLine.append(":");
updated |= corrupted;
updated |= oldVersion != null;
if (Config.getInstance().getTruncateSkills()) {
Map<SkillType, Integer> skills = getSkillMapFromLine(character);
for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
int cap = Config.getInstance().getLevelCap(skill);
if (skills.get(skill) > cap) {
updated = true;
}
}
}
writer.append(newLine).append("\r\n");
if (updated) {
line = new StringBuilder(org.apache.commons.lang.StringUtils.join(character, ":")).append(":").toString();
}
writer.append(line).append("\r\n");
}
// Write the new file
@@ -1087,38 +1133,39 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
Map<SkillType, Float> skillsXp = new EnumMap<SkillType, Float>(SkillType.class); // Skill & XP
Map<AbilityType, Integer> skillsDATS = new EnumMap<AbilityType, Integer>(AbilityType.class); // Ability & Cooldown
MobHealthbarType mobHealthbarType;
int scoreboardTipsShown;
// TODO on updates, put new values in a try{} ?
skillsXp.put(SkillType.TAMING, (float) Integer.valueOf(character[25]));
skillsXp.put(SkillType.MINING, (float) Integer.valueOf(character[4]));
skillsXp.put(SkillType.REPAIR, (float) Integer.valueOf(character[15]));
skillsXp.put(SkillType.WOODCUTTING, (float) Integer.valueOf(character[6]));
skillsXp.put(SkillType.UNARMED, (float) Integer.valueOf(character[16]));
skillsXp.put(SkillType.HERBALISM, (float) Integer.valueOf(character[17]));
skillsXp.put(SkillType.EXCAVATION, (float) Integer.valueOf(character[18]));
skillsXp.put(SkillType.ARCHERY, (float) Integer.valueOf(character[19]));
skillsXp.put(SkillType.SWORDS, (float) Integer.valueOf(character[20]));
skillsXp.put(SkillType.AXES, (float) Integer.valueOf(character[21]));
skillsXp.put(SkillType.ACROBATICS, (float) Integer.valueOf(character[22]));
skillsXp.put(SkillType.FISHING, (float) Integer.valueOf(character[35]));
skillsXp.put(SkillType.ALCHEMY, (float) Integer.valueOf(character[40]));
skillsXp.put(SkillType.TAMING, (float) Integer.valueOf(character[EXP_TAMING]));
skillsXp.put(SkillType.MINING, (float) Integer.valueOf(character[EXP_MINING]));
skillsXp.put(SkillType.REPAIR, (float) Integer.valueOf(character[EXP_REPAIR]));
skillsXp.put(SkillType.WOODCUTTING, (float) Integer.valueOf(character[EXP_WOODCUTTING]));
skillsXp.put(SkillType.UNARMED, (float) Integer.valueOf(character[EXP_UNARMED]));
skillsXp.put(SkillType.HERBALISM, (float) Integer.valueOf(character[EXP_HERBALISM]));
skillsXp.put(SkillType.EXCAVATION, (float) Integer.valueOf(character[EXP_EXCAVATION]));
skillsXp.put(SkillType.ARCHERY, (float) Integer.valueOf(character[EXP_ARCHERY]));
skillsXp.put(SkillType.SWORDS, (float) Integer.valueOf(character[EXP_SWORDS]));
skillsXp.put(SkillType.AXES, (float) Integer.valueOf(character[EXP_AXES]));
skillsXp.put(SkillType.ACROBATICS, (float) Integer.valueOf(character[EXP_ACROBATICS]));
skillsXp.put(SkillType.FISHING, (float) Integer.valueOf(character[EXP_FISHING]));
skillsXp.put(SkillType.ALCHEMY, (float) Integer.valueOf(character[EXP_ALCHEMY]));
// Taming - Unused
skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(character[32]));
skillsDATS.put(AbilityType.SUPER_BREAKER, Integer.valueOf(character[COOLDOWN_SUPER_BREAKER]));
// Repair - Unused
skillsDATS.put(AbilityType.TREE_FELLER, Integer.valueOf(character[28]));
skillsDATS.put(AbilityType.BERSERK, Integer.valueOf(character[26]));
skillsDATS.put(AbilityType.GREEN_TERRA, Integer.valueOf(character[29]));
skillsDATS.put(AbilityType.GIGA_DRILL_BREAKER, Integer.valueOf(character[27]));
skillsDATS.put(AbilityType.TREE_FELLER, Integer.valueOf(character[COOLDOWN_TREE_FELLER]));
skillsDATS.put(AbilityType.BERSERK, Integer.valueOf(character[COOLDOWN_BERSERK]));
skillsDATS.put(AbilityType.GREEN_TERRA, Integer.valueOf(character[COOLDOWN_GREEN_TERRA]));
skillsDATS.put(AbilityType.GIGA_DRILL_BREAKER, Integer.valueOf(character[COOLDOWN_GIGA_DRILL_BREAKER]));
// Archery - Unused
skillsDATS.put(AbilityType.SERRATED_STRIKES, Integer.valueOf(character[30]));
skillsDATS.put(AbilityType.SKULL_SPLITTER, Integer.valueOf(character[31]));
skillsDATS.put(AbilityType.SERRATED_STRIKES, Integer.valueOf(character[COOLDOWN_SERRATED_STRIKES]));
skillsDATS.put(AbilityType.SKULL_SPLITTER, Integer.valueOf(character[COOLDOWN_SKULL_SPLITTER]));
// Acrobatics - Unused
skillsDATS.put(AbilityType.BLAST_MINING, Integer.valueOf(character[36]));
skillsDATS.put(AbilityType.BLAST_MINING, Integer.valueOf(character[COOLDOWN_BLAST_MINING]));
try {
mobHealthbarType = MobHealthbarType.valueOf(character[38]);
mobHealthbarType = MobHealthbarType.valueOf(character[HEALTHBAR]);
}
catch (Exception e) {
mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
@@ -1126,31 +1173,38 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
UUID uuid;
try {
uuid = UUID.fromString(character[41]);
uuid = UUID.fromString(character[UUID_INDEX]);
}
catch (Exception e) {
uuid = null;
}
return new PlayerProfile(character[0], uuid, skills, skillsXp, skillsDATS, mobHealthbarType);
try {
scoreboardTipsShown = Integer.valueOf(character[SCOREBOARD_TIPS]);
}
catch (Exception e) {
scoreboardTipsShown = 0;
}
return new PlayerProfile(character[USERNAME], uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown);
}
private Map<SkillType, Integer> getSkillMapFromLine(String[] character) {
Map<SkillType, Integer> skills = new EnumMap<SkillType, Integer>(SkillType.class); // Skill & Level
skills.put(SkillType.TAMING, Integer.valueOf(character[24]));
skills.put(SkillType.MINING, Integer.valueOf(character[1]));
skills.put(SkillType.REPAIR, Integer.valueOf(character[7]));
skills.put(SkillType.WOODCUTTING, Integer.valueOf(character[5]));
skills.put(SkillType.UNARMED, Integer.valueOf(character[8]));
skills.put(SkillType.HERBALISM, Integer.valueOf(character[9]));
skills.put(SkillType.EXCAVATION, Integer.valueOf(character[10]));
skills.put(SkillType.ARCHERY, Integer.valueOf(character[11]));
skills.put(SkillType.SWORDS, Integer.valueOf(character[12]));
skills.put(SkillType.AXES, Integer.valueOf(character[13]));
skills.put(SkillType.ACROBATICS, Integer.valueOf(character[14]));
skills.put(SkillType.FISHING, Integer.valueOf(character[34]));
skills.put(SkillType.ALCHEMY, Integer.valueOf(character[39]));
skills.put(SkillType.TAMING, Integer.valueOf(character[SKILLS_TAMING]));
skills.put(SkillType.MINING, Integer.valueOf(character[SKILLS_MINING]));
skills.put(SkillType.REPAIR, Integer.valueOf(character[SKILLS_REPAIR]));
skills.put(SkillType.WOODCUTTING, Integer.valueOf(character[SKILLS_WOODCUTTING]));
skills.put(SkillType.UNARMED, Integer.valueOf(character[SKILLS_UNARMED]));
skills.put(SkillType.HERBALISM, Integer.valueOf(character[SKILLS_HERBALISM]));
skills.put(SkillType.EXCAVATION, Integer.valueOf(character[SKILLS_EXCAVATION]));
skills.put(SkillType.ARCHERY, Integer.valueOf(character[SKILLS_ARCHERY]));
skills.put(SkillType.SWORDS, Integer.valueOf(character[SKILLS_SWORDS]));
skills.put(SkillType.AXES, Integer.valueOf(character[SKILLS_AXES]));
skills.put(SkillType.ACROBATICS, Integer.valueOf(character[SKILLS_ACROBATICS]));
skills.put(SkillType.FISHING, Integer.valueOf(character[SKILLS_FISHING]));
skills.put(SkillType.ALCHEMY, Integer.valueOf(character[SKILLS_ALCHEMY]));
return skills;
}
@@ -1161,4 +1215,78 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
@Override
public void onDisable() { }
private int getSkillIndex(SkillType skill) {
switch (skill) {
case ACROBATICS:
return SKILLS_ACROBATICS;
case ALCHEMY:
return SKILLS_ALCHEMY;
case ARCHERY:
return SKILLS_ARCHERY;
case AXES:
return SKILLS_AXES;
case EXCAVATION:
return SKILLS_EXCAVATION;
case FISHING:
return SKILLS_FISHING;
case HERBALISM:
return SKILLS_HERBALISM;
case MINING:
return SKILLS_MINING;
case REPAIR:
return SKILLS_REPAIR;
case SWORDS:
return SKILLS_SWORDS;
case TAMING:
return SKILLS_TAMING;
case UNARMED:
return SKILLS_UNARMED;
case WOODCUTTING:
return SKILLS_WOODCUTTING;
default:
throw new RuntimeException("Primary Skills only");
}
}
public static int USERNAME = 0;
public static int SKILLS_MINING = 1;
public static int EXP_MINING = 4;
public static int SKILLS_WOODCUTTING = 5;
public static int EXP_WOODCUTTING = 6;
public static int SKILLS_REPAIR = 7;
public static int SKILLS_UNARMED = 8;
public static int SKILLS_HERBALISM = 9;
public static int SKILLS_EXCAVATION = 10;
public static int SKILLS_ARCHERY = 11;
public static int SKILLS_SWORDS = 12;
public static int SKILLS_AXES = 13;
public static int SKILLS_ACROBATICS = 14;
public static int EXP_REPAIR = 15;
public static int EXP_UNARMED = 16;
public static int EXP_HERBALISM = 17;
public static int EXP_EXCAVATION = 18;
public static int EXP_ARCHERY = 19;
public static int EXP_SWORDS = 20;
public static int EXP_AXES = 21;
public static int EXP_ACROBATICS = 22;
public static int SKILLS_TAMING = 24;
public static int EXP_TAMING = 25;
public static int COOLDOWN_BERSERK = 26;
public static int COOLDOWN_GIGA_DRILL_BREAKER = 27;
public static int COOLDOWN_TREE_FELLER = 28;
public static int COOLDOWN_GREEN_TERRA = 29;
public static int COOLDOWN_SERRATED_STRIKES = 30;
public static int COOLDOWN_SKULL_SPLITTER = 31;
public static int COOLDOWN_SUPER_BREAKER = 32;
public static int SKILLS_FISHING = 34;
public static int EXP_FISHING = 35;
public static int COOLDOWN_BLAST_MINING = 36;
public static int LAST_LOGIN = 37;
public static int HEALTHBAR = 38;
public static int SKILLS_ALCHEMY = 39;
public static int EXP_ALCHEMY = 40;
public static int UUID_INDEX = 41;
public static int SCOREBOARD_TIPS = 42;
}

View File

@@ -14,8 +14,6 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.mcMMO;
@@ -30,6 +28,9 @@ import com.gmail.nossr50.datatypes.skills.SkillType;
import com.gmail.nossr50.runnables.database.UUIDUpdateAsyncTask;
import com.gmail.nossr50.util.Misc;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
public final class SQLDatabaseManager implements DatabaseManager {
private static final String ALL_QUERY_VERSION = "taming+mining+woodcutting+repair+unarmed+herbalism+excavation+archery+swords+axes+acrobatics+fishing+alchemy";
private String tablePrefix = Config.getInstance().getMySQLTablePrefix();
@@ -132,22 +133,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
massUpdateLock.unlock();
}
@@ -156,7 +143,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
public void purgeOldUsers() {
massUpdateLock.lock();
mcMMO.p.getLogger().info("Purging inactive users older than " + (PURGE_TIME / 2630000L) + " months...");
mcMMO.p.getLogger().info("Purging inactive users older than " + (PURGE_TIME / 2630000000L) + " months...");
Connection connection = null;
Statement statement = null;
@@ -177,22 +164,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
massUpdateLock.unlock();
}
@@ -222,22 +195,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
}
if (success) {
@@ -260,6 +219,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
if (id == -1) {
id = newUser(connection, profile.getPlayerName(), profile.getUniqueId());
if (id == -1) {
mcMMO.p.getLogger().severe("Failed to create new account for " + profile.getPlayerName());
return false;
}
}
@@ -268,6 +228,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(1, id);
success &= (statement.executeUpdate() != 0);
statement.close();
if (!success) {
mcMMO.p.getLogger().severe("Failed to update last login for " + profile.getPlayerName());
return false;
}
statement = connection.prepareStatement("UPDATE " + tablePrefix + "skills SET "
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
@@ -290,6 +254,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(14, id);
success &= (statement.executeUpdate() != 0);
statement.close();
if (!success) {
mcMMO.p.getLogger().severe("Failed to update skills for " + profile.getPlayerName());
return false;
}
statement = connection.prepareStatement("UPDATE " + tablePrefix + "experience SET "
+ " taming = ?, mining = ?, repair = ?, woodcutting = ?"
@@ -312,6 +280,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(14, id);
success &= (statement.executeUpdate() != 0);
statement.close();
if (!success) {
mcMMO.p.getLogger().severe("Failed to update experience for " + profile.getPlayerName());
return false;
}
statement = connection.prepareStatement("UPDATE " + tablePrefix + "cooldowns SET "
+ " mining = ?, woodcutting = ?, unarmed = ?"
@@ -328,33 +300,28 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.setInt(9, id);
success = (statement.executeUpdate() != 0);
statement.close();
if (!success) {
mcMMO.p.getLogger().severe("Failed to update cooldowns for " + profile.getPlayerName());
return false;
}
statement = connection.prepareStatement("UPDATE " + tablePrefix + "huds SET mobhealthbar = ? WHERE user_id = ?");
statement = connection.prepareStatement("UPDATE " + tablePrefix + "huds SET mobhealthbar = ?, scoreboardtips = ? WHERE user_id = ?");
statement.setString(1, profile.getMobHealthbarType() == null ? Config.getInstance().getMobHealthbarDefault().name() : profile.getMobHealthbarType().name());
statement.setInt(2, id);
statement.setInt(2, profile.getScoreboardTipsShown());
statement.setInt(3, id);
success = (statement.executeUpdate() != 0);
statement.close();
if (!success) {
mcMMO.p.getLogger().severe("Failed to update hud settings for " + profile.getPlayerName());
return false;
}
}
catch (SQLException ex) {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
}
return success;
@@ -370,7 +337,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
connection = getConnection(PoolIdentifier.MISC);
statement = connection.prepareStatement("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 ORDER BY " + query + " DESC, user LIMIT ?, ?");
statement = connection.prepareStatement("SELECT " + query + ", user, NOW() FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON (user_id = id) WHERE " + query + " > 0 AND NOT user = '\\_INVALID\\_OLD\\_USERNAME\\_' ORDER BY " + query + " DESC, user LIMIT ?, ?");
statement.setInt(1, (pageNumber * statsPerPage) - statsPerPage);
statement.setInt(2, statsPerPage);
resultSet = statement.executeQuery();
@@ -389,30 +356,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
return stats;
@@ -429,6 +375,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
connection = getConnection(PoolIdentifier.MISC);
for (SkillType skillType : SkillType.NON_CHILD_SKILLS) {
String skillName = skillType.name().toLowerCase();
// Get count of all users with higher skill level than player
String sql = "SELECT COUNT(*) AS rank FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
"AND " + skillName + " > (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE user = ?)";
@@ -441,6 +388,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
int rank = resultSet.getInt("rank");
// Ties are settled by alphabetical order
sql = "SELECT user, " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id WHERE " + skillName + " > 0 " +
"AND " + skillName + " = (SELECT " + skillName + " FROM " + tablePrefix + "users JOIN " + tablePrefix + "skills ON user_id = id " +
"WHERE user = '" + playerName + "') ORDER BY user";
@@ -504,30 +452,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
return skills;
@@ -544,14 +471,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(connection);
}
}
@@ -560,14 +480,23 @@ public final class SQLDatabaseManager implements DatabaseManager {
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(
"UPDATE `" + tablePrefix + "users` "
+ "SET user = ? "
+ "WHERE user = ?");
statement.setString(1, "_INVALID_OLD_USERNAME_");
statement.setString(2, playerName);
statement.executeUpdate();
statement.close();
statement = connection.prepareStatement("INSERT INTO " + tablePrefix + "users (user, uuid, lastlogin) VALUES (?, ?, UNIX_TIMESTAMP())", Statement.RETURN_GENERATED_KEYS);
statement.setString(1, playerName);
statement.setString(2, uuid.toString());
statement.setString(2, uuid != null ? uuid.toString() : null);
statement.executeUpdate();
resultSet = statement.getGeneratedKeys();
if (!resultSet.next()) {
mcMMO.p.getLogger().severe("Unable to create new user account in DB");
return -1;
}
@@ -578,22 +507,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
}
return -1;
}
@@ -640,7 +555,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
+ "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, "
+ "h.mobhealthbar, u.uuid "
+ "h.mobhealthbar, h.scoreboardtips, u.uuid, u.user "
+ "FROM " + tablePrefix + "users u "
+ "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) "
+ "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) "
@@ -654,10 +569,19 @@ public final class SQLDatabaseManager implements DatabaseManager {
if (resultSet.next()) {
try {
PlayerProfile profile = loadFromResult(playerName, resultSet);
String name = resultSet.getString(42); // TODO: Magic Number, make sure it stays updated
resultSet.close();
statement.close();
if (!playerName.isEmpty() && !profile.getPlayerName().isEmpty()) {
if (!playerName.isEmpty() && !playerName.equals(name)) {
statement = connection.prepareStatement(
"UPDATE `" + tablePrefix + "users` "
+ "SET user = ? "
+ "WHERE user = ?");
statement.setString(1, "_INVALID_OLD_USERNAME_");
statement.setString(2, name);
statement.executeUpdate();
statement.close();
statement = connection.prepareStatement(
"UPDATE `" + tablePrefix + "users` "
+ "SET user = ?, uuid = ? "
@@ -672,6 +596,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
return profile;
}
catch (SQLException e) {
printErrors(e);
}
}
resultSet.close();
@@ -680,30 +605,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
// Problem, nothing was returned
@@ -729,7 +633,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "s.taming, s.mining, s.repair, s.woodcutting, s.unarmed, s.herbalism, s.excavation, s.archery, s.swords, s.axes, s.acrobatics, s.fishing, s.alchemy, "
+ "e.taming, e.mining, e.repair, e.woodcutting, e.unarmed, e.herbalism, e.excavation, e.archery, e.swords, e.axes, e.acrobatics, e.fishing, e.alchemy, "
+ "c.taming, c.mining, c.repair, c.woodcutting, c.unarmed, c.herbalism, c.excavation, c.archery, c.swords, c.axes, c.acrobatics, c.blast_mining, "
+ "h.mobhealthbar, u.uuid "
+ "h.mobhealthbar, h.scoreboardtips, u.uuid "
+ "FROM " + tablePrefix + "users u "
+ "JOIN " + tablePrefix + "skills s ON (u.id = s.user_id) "
+ "JOIN " + tablePrefix + "experience e ON (u.id = e.user_id) "
@@ -748,6 +652,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
resultSet.close();
}
catch (SQLException e) {
printErrors(e);
// Ignore
}
convertedUsers++;
@@ -758,30 +663,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(e);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
}
@@ -805,22 +689,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
return false;
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
}
}
@@ -859,22 +729,8 @@ public final class SQLDatabaseManager implements DatabaseManager {
return false;
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
tryClose(connection);
}
}
@@ -897,30 +753,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(e);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
return users;
@@ -952,11 +787,11 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`uuid` varchar(36) NULL DEFAULT NULL,"
+ "`lastlogin` int(32) unsigned NOT NULL,"
+ "PRIMARY KEY (`id`),"
+ "UNIQUE KEY `user` (`user`),"
+ "INDEX(`user`(20) ASC),"
+ "UNIQUE KEY `uuid` (`uuid`)) DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;");
createStatement.close();
tryClose(createStatement);
}
resultSet.close();
tryClose(resultSet);
statement.setString(1, Config.getInstance().getMySQLDatabaseName());
statement.setString(2, tablePrefix + "huds");
resultSet = statement.executeQuery();
@@ -965,11 +800,12 @@ public final class SQLDatabaseManager implements DatabaseManager {
createStatement.executeUpdate("CREATE TABLE IF NOT EXISTS `" + tablePrefix + "huds` ("
+ "`user_id` int(10) unsigned NOT NULL,"
+ "`mobhealthbar` varchar(50) NOT NULL DEFAULT '" + Config.getInstance().getMobHealthbarDefault() + "',"
+ "`scoreboardtips` int(10) NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
createStatement.close();
tryClose(createStatement);
}
resultSet.close();
tryClose(resultSet);
statement.setString(1, Config.getInstance().getMySQLDatabaseName());
statement.setString(2, tablePrefix + "cooldowns");
resultSet = statement.executeQuery();
@@ -991,9 +827,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`blast_mining` int(32) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
createStatement.close();
tryClose(createStatement);
}
resultSet.close();
tryClose(resultSet);
statement.setString(1, Config.getInstance().getMySQLDatabaseName());
statement.setString(2, tablePrefix + "skills");
resultSet = statement.executeQuery();
@@ -1016,9 +852,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`alchemy` int(10) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
createStatement.close();
tryClose(createStatement);
}
resultSet.close();
tryClose(resultSet);
statement.setString(1, Config.getInstance().getMySQLDatabaseName());
statement.setString(2, tablePrefix + "experience");
resultSet = statement.executeQuery();
@@ -1041,15 +877,26 @@ public final class SQLDatabaseManager implements DatabaseManager {
+ "`alchemy` int(10) unsigned NOT NULL DEFAULT '0',"
+ "PRIMARY KEY (`user_id`)) "
+ "DEFAULT CHARSET=latin1;");
createStatement.close();
tryClose(createStatement);
}
resultSet.close();
statement.close();
tryClose(resultSet);
tryClose(statement);
for (UpgradeType updateType : UpgradeType.values()) {
checkDatabaseStructure(connection, updateType);
}
if (Config.getInstance().getTruncateSkills()) {
for (SkillType skill : SkillType.NON_CHILD_SKILLS) {
int cap = Config.getInstance().getLevelCap(skill);
if (cap != Integer.MAX_VALUE) {
statement = connection.prepareStatement("UPDATE `" + tablePrefix + "skills` SET `" + skill.name().toLowerCase() + "` = " + cap + " WHERE `" + skill.name().toLowerCase() + "` > " + cap);
statement.executeUpdate();
tryClose(statement);
}
}
}
mcMMO.p.getLogger().info("Killing orphans");
createStatement = connection.createStatement();
createStatement.executeUpdate("DELETE FROM `" + tablePrefix + "experience` WHERE NOT EXISTS (SELECT * FROM `" + tablePrefix + "users` `u` WHERE `" + tablePrefix + "experience`.`user_id` = `u`.`id`)");
@@ -1061,38 +908,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (createStatement != null) {
try {
createStatement.close();
}
catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(createStatement);
tryClose(connection);
}
}
@@ -1165,6 +984,14 @@ public final class SQLDatabaseManager implements DatabaseManager {
checkUpgradeAddUUIDs(statement);
return;
case ADD_SCOREBOARD_TIPS:
checkUpgradeAddScoreboardTips(statement);
return;
case DROP_NAME_UNIQUENESS:
checkNameUniqueness(statement);
return;
default:
break;
@@ -1176,14 +1003,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
}
}
@@ -1206,9 +1026,10 @@ public final class SQLDatabaseManager implements DatabaseManager {
statement.execute();
statement.close();
statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "huds (user_id, mobhealthbar) VALUES (?, ?)");
statement = connection.prepareStatement("INSERT IGNORE INTO " + tablePrefix + "huds (user_id, mobhealthbar, scoreboardtips) VALUES (?, ?, ?)");
statement.setInt(1, id);
statement.setString(2, Config.getInstance().getMobHealthbarDefault().name());
statement.setInt(3, 0);
statement.execute();
statement.close();
}
@@ -1216,14 +1037,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(statement);
}
}
@@ -1233,6 +1047,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
Map<AbilityType, Integer> skillsDATS = new EnumMap<AbilityType, Integer>(AbilityType.class); // Ability & Cooldown
MobHealthbarType mobHealthbarType;
UUID uuid;
int scoreboardTipsShown;
final int OFFSET_SKILLS = 0; // TODO update these numbers when the query
// changes (a new skill is added)
@@ -1282,12 +1097,19 @@ public final class SQLDatabaseManager implements DatabaseManager {
skillsDATS.put(AbilityType.BLAST_MINING, result.getInt(OFFSET_DATS + 12));
try {
mobHealthbarType = MobHealthbarType.valueOf(result.getString(OFFSET_OTHER + 2));
mobHealthbarType = MobHealthbarType.valueOf(result.getString(OFFSET_OTHER + 1));
}
catch (Exception e) {
mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
}
try {
scoreboardTipsShown = result.getInt(OFFSET_OTHER + 2);
}
catch (Exception e) {
scoreboardTipsShown = 0;
}
try {
uuid = UUID.fromString(result.getString(OFFSET_OTHER + 3));
}
@@ -1295,7 +1117,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
uuid = null;
}
return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType);
return new PlayerProfile(playerName, uuid, skills, skillsXp, skillsDATS, mobHealthbarType, scoreboardTipsShown);
}
private void printErrors(SQLException ex) {
@@ -1310,6 +1132,27 @@ public final class SQLDatabaseManager implements DatabaseManager {
return DatabaseType.SQL;
}
private void checkNameUniqueness(final Statement statement) throws SQLException {
ResultSet resultSet = null;
try {
resultSet = statement.executeQuery("SHOW INDEXES "
+ "FROM `" + tablePrefix + "users` "
+ "WHERE Column_name='user' "
+ " AND NOT Non_unique");
if (!resultSet.next()) {
return;
}
resultSet.close();
mcMMO.p.getLogger().info("Updating mcMMO MySQL tables to drop name uniqueness...");
statement.execute("ALTER TABLE `" + tablePrefix + "users` "
+ "DROP INDEX `user`,"
+ "ADD INDEX `user` (`user`(20) ASC)");
} catch (SQLException ex) {
} finally {
tryClose(resultSet);
}
}
private void checkUpgradeAddAlchemy(final Statement statement) throws SQLException {
try {
statement.executeQuery("SELECT `alchemy` FROM `" + tablePrefix + "skills` LIMIT 1");
@@ -1352,6 +1195,16 @@ public final class SQLDatabaseManager implements DatabaseManager {
}
}
private void checkUpgradeAddScoreboardTips(final Statement statement) throws SQLException {
try {
statement.executeQuery("SELECT `scoreboardtips` FROM `" + tablePrefix + "huds` LIMIT 1");
}
catch (SQLException ex) {
mcMMO.p.getLogger().info("Updating mcMMO MySQL tables for scoreboard tips...");
statement.executeUpdate("ALTER TABLE `" + tablePrefix + "huds` ADD `scoreboardtips` int(10) NOT NULL DEFAULT '0' ;");
}
}
private void checkUpgradeAddSQLIndexes(final Statement statement) throws SQLException {
ResultSet resultSet = null;
@@ -1378,14 +1231,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
}
}
@@ -1415,14 +1261,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
}
new GetUUIDUpdatesRequired().runTaskLaterAsynchronously(mcMMO.p, 100); // wait until after first purge
@@ -1447,27 +1286,9 @@ public final class SQLDatabaseManager implements DatabaseManager {
} catch (SQLException ex) {
printErrors(ex);
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// Ignore
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
tryClose(connection);
}
if (!names.isEmpty()) {
@@ -1504,14 +1325,7 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
}
}
@@ -1540,19 +1354,12 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
}
}
private int getUserID(final Connection connection, final String playerName, final UUID uuid) {
if (cachedUserIDs.containsKey(uuid)) {
if (uuid != null && cachedUserIDs.containsKey(uuid)) {
return cachedUserIDs.get(uuid);
}
@@ -1561,14 +1368,16 @@ public final class SQLDatabaseManager implements DatabaseManager {
try {
statement = connection.prepareStatement("SELECT id, user FROM " + tablePrefix + "users WHERE uuid = ? OR (uuid IS NULL AND user = ?)");
statement.setString(1, uuid.toString());
statement.setString(1, uuid == null ? null : uuid.toString());
statement.setString(2, playerName);
resultSet = statement.executeQuery();
if (resultSet.next()) {
int id = resultSet.getInt("id");
cachedUserIDs.put(uuid, id);
if (uuid != null) {
cachedUserIDs.put(uuid, id);
}
return id;
}
@@ -1577,26 +1386,23 @@ public final class SQLDatabaseManager implements DatabaseManager {
printErrors(ex);
}
finally {
if (resultSet != null) {
try {
resultSet.close();
}
catch (SQLException e) {
// Ignore
}
}
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
// Ignore
}
}
tryClose(resultSet);
tryClose(statement);
}
return -1;
}
private void tryClose(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
}
catch (Exception e) {
// Ignore
}
}
}
@Override
public void onDisable() {

View File

@@ -9,5 +9,7 @@ public enum UpgradeType {
DROP_SPOUT,
ADD_ALCHEMY,
ADD_UUIDS,
ADD_UUIDS_PARTY;
ADD_UUIDS_PARTY,
ADD_SCOREBOARD_TIPS,
DROP_NAME_UNIQUENESS;
}

View File

@@ -101,12 +101,6 @@ public class McMMOPlayer {
this.player = player;
playerMetadata = new FixedMetadataValue(mcMMO.p, playerName);
this.profile = profile;
party = PartyManager.getPlayerParty(playerName, uuid);
ptpRecord = new PartyTeleportRecord();
if (inParty()) {
loginParty();
}
if (profile.getUniqueId() == null) {
profile.setUniqueId(uuid);
@@ -532,6 +526,15 @@ public class McMMOPlayer {
* Party Stuff
*/
public void setupPartyData() {
party = PartyManager.getPlayerParty(player.getName(), player.getUniqueId());
ptpRecord = new PartyTeleportRecord();
if (inParty()) {
loginParty();
}
}
public void setPartyInvite(Party invite) {
this.invite = invite;
}

View File

@@ -28,6 +28,7 @@ public class PlayerProfile {
/* HUDs */
private MobHealthbarType mobHealthbarType;
private int scoreboardTipsShown;
/* Skill Data */
private final Map<SkillType, Integer> skills = new HashMap<SkillType, Integer>(); // Skill & Level
@@ -48,6 +49,7 @@ public class PlayerProfile {
this.playerName = playerName;
mobHealthbarType = Config.getInstance().getMobHealthbarDefault();
scoreboardTipsShown = 0;
for (AbilityType abilityType : AbilityType.values()) {
abilityDATS.put(abilityType, 0);
@@ -70,10 +72,11 @@ public class PlayerProfile {
this.loaded = isLoaded;
}
public PlayerProfile(String playerName, UUID uuid, Map<SkillType, Integer> levelData, Map<SkillType, Float> xpData, Map<AbilityType, Integer> cooldownData, MobHealthbarType mobHealthbarType) {
public PlayerProfile(String playerName, UUID uuid, Map<SkillType, Integer> levelData, Map<SkillType, Float> xpData, Map<AbilityType, Integer> cooldownData, MobHealthbarType mobHealthbarType, int scoreboardTipsShown) {
this.playerName = playerName;
this.uuid = uuid;
this.mobHealthbarType = mobHealthbarType;
this.scoreboardTipsShown = scoreboardTipsShown;
skills.putAll(levelData);
skillsXp.putAll(xpData);
@@ -92,7 +95,7 @@ public class PlayerProfile {
}
// TODO should this part be synchronized?
PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType);
PlayerProfile profileCopy = new PlayerProfile(playerName, uuid, ImmutableMap.copyOf(skills), ImmutableMap.copyOf(skillsXp), ImmutableMap.copyOf(abilityDATS), mobHealthbarType, scoreboardTipsShown);
changed = !mcMMO.getDatabaseManager().saveUser(profileCopy);
if (changed) {
@@ -127,9 +130,25 @@ public class PlayerProfile {
}
public void setMobHealthbarType(MobHealthbarType mobHealthbarType) {
changed = true;
this.mobHealthbarType = mobHealthbarType;
}
public int getScoreboardTipsShown() {
return scoreboardTipsShown;
}
public void setScoreboardTipsShown(int scoreboardTipsShown) {
changed = true;
this.scoreboardTipsShown = scoreboardTipsShown;
}
public void increaseTipsShown() {
setScoreboardTipsShown(getScoreboardTipsShown() + 1);
}
/*
* Cooldowns
*/
@@ -336,7 +355,7 @@ public class PlayerProfile {
int sum = 0;
for (SkillType parent : parents) {
sum += Math.min(getSkillLevel(parent), 1000);
sum += Math.min(getSkillLevel(parent), parent.getMaxLevel());
}
return sum / parents.size();

View File

@@ -1,6 +1,9 @@
package com.gmail.nossr50.datatypes.skills.alchemy;
import java.util.List;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionEffect;
public enum PotionStage {
FIVE(5),
@@ -44,17 +47,27 @@ public enum PotionStage {
public static PotionStage getPotionStage(AlchemyPotion alchemyPotion) {
Potion potion = alchemyPotion.toPotion(1);
List<PotionEffect> effects = alchemyPotion.getEffects();
int stage = 1;
// Check if potion isn't awkward or mundane
if (potion.getType() != null) {
// Check for custom effects added by mcMMO
if (potion.getType() != null || !effects.isEmpty()) {
stage++;
}
// Check if potion has a glowstone dust amplifier
// Else check if the potion has a custom effect with an amplifier added by mcMMO
if (potion.getLevel() > 1) {
stage++;
}else if(!effects.isEmpty()){
for (PotionEffect effect : effects){
if(effect.getAmplifier() > 0){
stage++;
break;
}
}
}
// Check if potion has a redstone dust amplifier

View File

@@ -11,6 +11,7 @@ import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.BrewingStand;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@@ -20,6 +21,7 @@ import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.inventory.ItemStack;
import com.gmail.nossr50.mcMMO;
@@ -49,6 +51,8 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
public class BlockListener implements Listener {
private final mcMMO plugin;
@@ -64,10 +68,6 @@ public class BlockListener implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPistonExtend(BlockPistonExtendEvent event) {
if (!EventUtils.shouldProcessEvent(event.getBlock(), true)) {
return;
}
BlockFace direction = event.getDirection();
Block futureEmptyBlock = event.getBlock().getRelative(direction); // Block that would be air after piston is finished
@@ -79,12 +79,14 @@ public class BlockListener implements Listener {
for (Block b : blocks) {
if (BlockUtils.shouldBeWatched(b.getState()) && mcMMO.getPlaceStore().isTrue(b)) {
b.getRelative(direction).setMetadata(mcMMO.blockMetadataKey, mcMMO.metadataValue);
Block nextBlock = b.getRelative(direction);
mcMMO.getPlaceStore().setTrue(nextBlock);
//b.getRelative(direction).setMetadata(mcMMO.blockMetadataKey, mcMMO.metadataValue);
}
}
// Needed because blocks sometimes don't move when two pistons push towards each other
new PistonTrackerTask(blocks, direction, futureEmptyBlock).runTaskLater(plugin, 2);
//new PistonTrackerTask(blocks, direction, futureEmptyBlock).runTaskLater(plugin, 2);
}
/**
@@ -94,18 +96,64 @@ public class BlockListener implements Listener {
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPistonRetract(BlockPistonRetractEvent event) {
if (!EventUtils.shouldProcessEvent(event.getBlock(), false)) {
// event.isSticky() always returns false
// if (!event.isSticky()){
// return;
// }
// Sticky piston return PISTON_MOVING_PIECE and normal piston PISTON_BASE
if (event.getBlock().getType() != Material.PISTON_MOVING_PIECE) {
return;
}
if (!event.isSticky()) {
// Get opposite direction so we get correct block
BlockFace direction = event.getDirection().getOppositeFace();
Block movedBlock = event.getBlock().getRelative(direction);
mcMMO.getPlaceStore().setTrue(movedBlock);
// If we're pulling a slime block, it might have something attached to it!
if (movedBlock.getRelative(direction).getState().getType() == Material.SLIME_BLOCK) {
for (Block block : event.getBlocks()) {
movedBlock = block.getRelative(direction);
mcMMO.getPlaceStore().setTrue(movedBlock);
// // Treat the slime blocks as if it is the sticky piston itself, because pulling
// // a slime block with a sticky piston is effectively the same as moving a sticky piston.
// new StickyPistonTrackerTask(direction, event.getBlock(), block).runTaskLater(plugin, 2);
}
return;
}
Block movedBlock = event.getRetractLocation().getBlock();
// Needed only because under some circumstances Minecraft doesn't move the block
new StickyPistonTrackerTask(event.getDirection(), event.getBlock(), movedBlock).runTaskLater(plugin, 2);
//new StickyPistonTrackerTask(direction, event.getBlock(), movedBlock).runTaskLater(plugin, 2);
}
/**
* Monitor falling blocks.
*
* @param event The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onFallingBlock(EntityChangeBlockEvent event) {
if (BlockUtils.shouldBeWatched(event.getBlock().getState()) && event.getEntityType().equals(EntityType.FALLING_BLOCK)) {
if (event.getTo().equals(Material.AIR) && mcMMO.getPlaceStore().isTrue(event.getBlock())) {
event.getEntity().setMetadata("mcMMOBlockFall", new FixedMetadataValue( plugin, event.getBlock().getLocation()));
} else {
List<MetadataValue> values = event.getEntity().getMetadata( "mcMMOBlockFall" );
if (!values.isEmpty()) {
if (values.get(0).value() == null) return;
Block spawn = ((org.bukkit.Location) values.get(0).value()).getBlock();
mcMMO.getPlaceStore().setTrue( event.getBlock() );
mcMMO.getPlaceStore().setFalse( spawn );
}
}
}
}
/**
@@ -260,7 +308,7 @@ public class BlockListener implements Listener {
}
}
}
else if (ItemUtils.isPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH)) {
else if (ItemUtils.isFluxPickaxe(heldItem) && !heldItem.containsEnchantment(Enchantment.SILK_TOUCH)) {
SmeltingManager smeltingManager = UserManager.getPlayer(player).getSmeltingManager();
if (smeltingManager.canUseFluxMining(blockState)) {

View File

@@ -23,6 +23,7 @@ import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDamageEvent.DamageModifier;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityShootBowEvent;
@@ -104,13 +105,15 @@ public class EntityListener implements Listener {
/**
* Monitor EntityChangeBlock events.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
Block block = event.getBlock();
// When the event is fired for the falling block that changes back to a normal block
// When the event is fired for the falling block that changes back to a
// normal block
// event.getBlock().getType() returns AIR
if (!BlockUtils.shouldBeWatched(block.getState()) && block.getType() != Material.AIR) {
return;
@@ -142,7 +145,8 @@ public class EntityListener implements Listener {
/**
* Handle EntityDamageByEntity events that involve modifying the event.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamageByEntity(EntityDamageByEntityEvent event) {
@@ -151,12 +155,24 @@ public class EntityListener implements Listener {
}
double damage = event.getFinalDamage();
Entity defender = event.getEntity();
Entity attacker = event.getDamager();
if (damage <= 0) {
if (defender instanceof Player && attacker instanceof Player) {
Player defendingPlayer = (Player) defender;
Player attackingPlayer = (Player) attacker;
if (event.getDamage(DamageModifier.ABSORPTION) > 0) {
if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
event.setCancelled(true);
return;
}
}
}
return;
}
Entity defender = event.getEntity();
if (defender.hasMetadata(mcMMO.customDamageKey)) {
defender.removeMetadata(mcMMO.customDamageKey, plugin);
@@ -173,7 +189,7 @@ public class EntityListener implements Listener {
return;
}
Entity attacker = event.getDamager();
if (Misc.isNPCEntity(attacker)) {
return;
@@ -207,7 +223,8 @@ public class EntityListener implements Listener {
return;
}
// We want to make sure we're not gaining XP or applying abilities when we hit ourselves
// We want to make sure we're not gaining XP or applying abilities
// when we hit ourselves
if (defendingPlayer.equals(attackingPlayer)) {
return;
}
@@ -225,7 +242,8 @@ public class EntityListener implements Listener {
/**
* Handle EntityDamage events that involve modifying the event.
*
* @param event The event to modify
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamage(EntityDamageEvent event) {
@@ -371,7 +389,8 @@ public class EntityListener implements Listener {
/**
* Monitor EntityDeath events.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.LOWEST)
public void onEntityDeathLowest(EntityDeathEvent event) {
@@ -395,7 +414,8 @@ public class EntityListener implements Listener {
/**
* Monitor EntityDeath events.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR)
public void onEntityDeath(EntityDeathEvent event) {
@@ -412,23 +432,30 @@ public class EntityListener implements Listener {
/**
* Monitor CreatureSpawn events.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onCreatureSpawn(CreatureSpawnEvent event) {
LivingEntity entity = event.getEntity();
switch (event.getSpawnReason()) {
case NETHER_PORTAL:
case SPAWNER:
case SPAWNER_EGG:
LivingEntity entity = event.getEntity();
Entity passenger = entity.getPassenger();
entity.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
Entity passenger = entity.getPassenger();
if (passenger != null) {
passenger.setMetadata(mcMMO.entityMetadataKey, mcMMO.metadataValue);
}
return;
case BREEDING:
entity.setMetadata(mcMMO.bredMetadataKey, mcMMO.metadataValue);
return;
default:
return;
}
@@ -437,7 +464,8 @@ public class EntityListener implements Listener {
/**
* Handle ExplosionPrime events that involve modifying the event.
*
* @param event The event to modify
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onExplosionPrime(ExplosionPrimeEvent event) {
@@ -447,7 +475,8 @@ public class EntityListener implements Listener {
return;
}
// We can make this assumption because we (should) be the only ones using this exact metadata
// We can make this assumption because we (should) be the only ones
// using this exact metadata
Player player = plugin.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
if (!UserManager.hasPlayerDataKey(player)) {
@@ -464,7 +493,8 @@ public class EntityListener implements Listener {
/**
* Handle EntityExplode events that involve modifying the event.
*
* @param event The event to modify
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEnitityExplode(EntityExplodeEvent event) {
@@ -474,7 +504,8 @@ public class EntityListener implements Listener {
return;
}
// We can make this assumption because we (should) be the only ones using this exact metadata
// We can make this assumption because we (should) be the only ones
// using this exact metadata
Player player = plugin.getServer().getPlayerExact(entity.getMetadata(mcMMO.tntMetadataKey).get(0).asString());
if (!UserManager.hasPlayerDataKey(player)) {
@@ -492,7 +523,8 @@ public class EntityListener implements Listener {
/**
* Handle EntityExplode events that involve modifying the event.
*
* @param event The event to modify
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onEntityExplodeMonitor(EntityExplodeEvent event) {
@@ -508,7 +540,8 @@ public class EntityListener implements Listener {
/**
* Handle FoodLevelChange events that involve modifying the event.
*
* @param event The event to modify
* @param event
* The event to modify
*/
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onFoodLevelChange(FoodLevelChangeEvent event) {
@@ -533,39 +566,59 @@ public class EntityListener implements Listener {
}
/*
* Some foods have 3 ranks
* Some foods have 5 ranks
* The number of ranks is based on how 'common' the item is
* We can adjust this quite easily if we find something is giving too much of a bonus
* Some foods have 3 ranks Some foods have 5 ranks The number of ranks
* is based on how 'common' the item is We can adjust this quite easily
* if we find something is giving too much of a bonus
*/
switch (player.getItemInHand().getType()) {
case BAKED_POTATO: /* RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @ 1000 */
case BREAD: /* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */
case CARROT_ITEM: /* RESTORES 2 HUNGER - RESTORES 4 1/2 HUNGER @ 1000 */
case GOLDEN_CARROT: /* RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @ 1000 */
case MUSHROOM_SOUP: /* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */
case PUMPKIN_PIE: /* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */
case BAKED_POTATO: /*
* RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @
* 1000
*/
case BREAD: /* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */
case CARROT_ITEM: /*
* RESTORES 2 HUNGER - RESTORES 4 1/2 HUNGER @
* 1000
*/
case GOLDEN_CARROT: /*
* RESTORES 3 HUNGER - RESTORES 5 1/2 HUNGER @
* 1000
*/
case MUSHROOM_SOUP: /*
* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @
* 1000
*/
case PUMPKIN_PIE: /*
* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @
* 1000
*/
if (Permissions.secondaryAbilityEnabled(player, SecondaryAbility.FARMERS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getHerbalismManager().farmersDiet(Herbalism.farmersDietRankLevel1, newFoodLevel));
}
return;
case COOKIE: /* RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
case MELON: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
case POISONOUS_POTATO: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
case POTATO_ITEM: /* RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
case COOKIE: /* RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
case MELON: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
case POISONOUS_POTATO: /*
* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER
* @ 1000
*/
case POTATO_ITEM: /* RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */
if (Permissions.secondaryAbilityEnabled(player, SecondaryAbility.FARMERS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getHerbalismManager().farmersDiet(Herbalism.farmersDietRankLevel2, newFoodLevel));
}
return;
case COOKED_FISH: /* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */
case COOKED_FISH: /*
* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @
* 1000
*/
if (Permissions.secondaryAbilityEnabled(player, SecondaryAbility.FISHERMANS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel1, newFoodLevel));
}
return;
case RAW_FISH: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
case RAW_FISH: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */
if (Permissions.secondaryAbilityEnabled(player, SecondaryAbility.FISHERMANS_DIET)) {
event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel2, newFoodLevel));
}
@@ -579,7 +632,8 @@ public class EntityListener implements Listener {
/**
* Monitor EntityTame events.
*
* @param event The event to watch
* @param event
* The event to watch
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityTame(EntityTameEvent event) {
@@ -601,7 +655,8 @@ public class EntityListener implements Listener {
/**
* Handle EntityTarget events.
*
* @param event The event to process
* @param event
* The event to process
*/
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityTarget(EntityTargetEvent event) {
@@ -619,7 +674,8 @@ public class EntityListener implements Listener {
return;
}
// isFriendlyPet ensures that the Tameable is: Tamed, owned by a player, and the owner is in the same party
// isFriendlyPet ensures that the Tameable is: Tamed, owned by a player,
// and the owner is in the same party
// So we can make some assumptions here, about our casting and our check
if (!(Permissions.friendlyFire(player) && Permissions.friendlyFire((Player) tameable.getOwner()))) {
event.setCancelled(true);
@@ -627,9 +683,11 @@ public class EntityListener implements Listener {
}
/**
* Handle PotionSplash events in order to fix broken Splash Potion of Saturation.
* Handle PotionSplash events in order to fix broken Splash Potion of
* Saturation.
*
* @param event The event to process
* @param event
* The event to process
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPotionSplash(PotionSplashEvent event) {

View File

@@ -17,6 +17,7 @@ import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.event.inventory.FurnaceExtractEvent;
import org.bukkit.event.inventory.FurnaceSmeltEvent;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
@@ -313,6 +314,14 @@ public class InventoryListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryClickEvent(InventoryClickEvent event) {
SkillUtils.removeAbilityBuff(event.getCurrentItem());
if (event.getAction() == InventoryAction.HOTBAR_SWAP) {
SkillUtils.removeAbilityBuff(event.getWhoClicked().getInventory().getItem(event.getHotbarButton()));
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryOpenEvent(InventoryOpenEvent event) {
SkillUtils.removeAbilityBuff(event.getPlayer().getItemInHand());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@@ -1,5 +1,7 @@
package com.gmail.nossr50.listeners;
import java.util.HashSet;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.Sound;
@@ -236,7 +238,7 @@ public class PlayerListener implements Listener {
return;
case IN_GROUND:
Block block = player.getTargetBlock(null, 100);
Block block = player.getTargetBlock((HashSet<Byte>) null, 100);
if (fishingManager.canIceFish(block)) {
event.setCancelled(true);

View File

@@ -57,7 +57,7 @@ public final class LocaleLoader {
public static String formatString(String string, Object... messageArguments) {
if (messageArguments != null) {
MessageFormat formatter = new MessageFormat("");
formatter.applyPattern(string);
formatter.applyPattern(string.replace("'", "''"));
string = formatter.format(messageArguments);
}

View File

@@ -5,6 +5,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
import org.bukkit.metadata.FixedMetadataValue;
@@ -51,6 +52,7 @@ import com.gmail.nossr50.skills.repair.repairables.SimpleRepairableManager;
import com.gmail.nossr50.skills.salvage.salvageables.Salvageable;
import com.gmail.nossr50.skills.salvage.salvageables.SalvageableManager;
import com.gmail.nossr50.skills.salvage.salvageables.SimpleSalvageableManager;
import com.gmail.nossr50.skills.smelting.SmeltingManager;
import com.gmail.nossr50.util.ChimaeraWing;
import com.gmail.nossr50.util.HolidayManager;
import com.gmail.nossr50.util.LogFilter;
@@ -117,8 +119,8 @@ public class mcMMO extends JavaPlugin {
public final static String disarmedItemKey = "mcMMO: Disarmed Item";
public final static String playerDataKey = "mcMMO: Player Data";
public final static String greenThumbDataKey = "mcMMO: Green Thumb";
public final static String pistonDataKey = "mcMMO: Piston State";
public final static String databaseCommandKey = "mcMMO: Processing Database Command";
public final static String bredMetadataKey = "mcMMO: Bred Animal";
public static FixedMetadataValue metadataValue;
@@ -455,6 +457,14 @@ public class mcMMO extends JavaPlugin {
if (Config.getInstance().getChimaeraEnabled()) {
getServer().addRecipe(ChimaeraWing.getChimaeraWingRecipe());
}
if (Config.getInstance().getFluxPickaxeEnabled()) {
getServer().addRecipe(SmeltingManager.getFluxPickaxeRecipe(Material.DIAMOND_PICKAXE));
getServer().addRecipe(SmeltingManager.getFluxPickaxeRecipe(Material.GOLD_PICKAXE));
getServer().addRecipe(SmeltingManager.getFluxPickaxeRecipe(Material.IRON_PICKAXE));
getServer().addRecipe(SmeltingManager.getFluxPickaxeRecipe(Material.STONE_PICKAXE));
getServer().addRecipe(SmeltingManager.getFluxPickaxeRecipe(Material.WOOD_PICKAXE));
}
}
private void scheduleTasks() {

View File

@@ -20,7 +20,7 @@ public class StickyPistonTrackerTask extends BukkitRunnable {
@Override
public void run() {
if (!mcMMO.getPlaceStore().isTrue(movedBlock)) {
if (!mcMMO.getPlaceStore().isTrue(movedBlock.getRelative(direction))) {
return;
}
@@ -30,7 +30,7 @@ public class StickyPistonTrackerTask extends BukkitRunnable {
}
// The sticky piston actually pulled the block so move the PlaceStore data
mcMMO.getPlaceStore().setFalse(movedBlock);
mcMMO.getPlaceStore().setTrue(block.getRelative(direction));
mcMMO.getPlaceStore().setFalse(movedBlock.getRelative(direction));
mcMMO.getPlaceStore().setTrue(movedBlock);
}
}

View File

@@ -70,6 +70,7 @@ public class UUIDUpdateAsyncTask extends BukkitRunnable {
catch (Exception e) {
// Handle 429
if (e.getMessage().contains("429")) {
size += userNamesSection.size();
try {
Thread.sleep(LIMIT_PERIOD);
} catch (InterruptedException ex) {

View File

@@ -1,16 +1,15 @@
package com.gmail.nossr50.runnables.party;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.party.Party;
import com.gmail.nossr50.locale.LocaleLoader;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.party.Party;
import com.gmail.nossr50.locale.LocaleLoader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PartyChatTask extends BukkitRunnable {
private Plugin plugin;
@@ -46,6 +45,6 @@ public class PartyChatTask extends BukkitRunnable {
}
}
plugin.getServer().getConsoleSender().sendMessage("[mcMMO] [P]<" + party.getName() + ">" + message);
plugin.getServer().getConsoleSender().sendMessage(ChatColor.stripColor("[mcMMO] [P]<" + party.getName() + ">" + message));
}
}

View File

@@ -44,7 +44,7 @@ public class PlayerProfileLoadingTask extends BukkitRunnable {
PlayerProfile profile = mcMMO.getDatabaseManager().loadPlayerProfile(player.getName(), player.getUniqueId(), true);
// If successful, schedule the apply
if (profile.isLoaded()) {
new ApplySuccessfulProfile(profile).runTask(mcMMO.p);
new ApplySuccessfulProfile(new McMMOPlayer(player, profile)).runTask(mcMMO.p);
return;
}
@@ -59,10 +59,10 @@ public class PlayerProfileLoadingTask extends BukkitRunnable {
}
private class ApplySuccessfulProfile extends BukkitRunnable {
private final PlayerProfile profile;
private final McMMOPlayer mcMMOPlayer;
private ApplySuccessfulProfile(PlayerProfile profile) {
this.profile = profile;
private ApplySuccessfulProfile(McMMOPlayer mcMMOPlayer) {
this.mcMMOPlayer = mcMMOPlayer;
}
// Synchronized task
@@ -74,7 +74,7 @@ public class PlayerProfileLoadingTask extends BukkitRunnable {
return;
}
McMMOPlayer mcMMOPlayer = new McMMOPlayer(player, profile);
mcMMOPlayer.setupPartyData();
UserManager.track(mcMMOPlayer);
mcMMOPlayer.actualizeRespawnATS();
ScoreboardManager.setupPlayer(player);

View File

@@ -3,7 +3,7 @@ package com.gmail.nossr50.runnables.skills;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.Creature;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@@ -11,20 +11,20 @@ import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.util.Misc;
public class KrakenAttackTask extends BukkitRunnable {
private Creature kraken;
private LivingEntity kraken;
private Player player;
private Location location;
private final boolean GLOBAL_EFFECTS = AdvancedConfig.getInstance().getKrakenGlobalEffectsEnabled();
private final String DEFEAT_MESSAGE = AdvancedConfig.getInstance().getPlayerDefeatMessage();
private final String ESCAPE_MESSAGE = AdvancedConfig.getInstance().getPlayerEscapeMessage();
public KrakenAttackTask(Creature kraken, Player player) {
this.kraken = kraken;
public KrakenAttackTask(LivingEntity kraken2, Player player) {
this.kraken = kraken2;
this.player = player;
}
public KrakenAttackTask(Creature kraken, Player player, Location location) {
this.kraken = kraken;
public KrakenAttackTask(LivingEntity kraken2, Player player, Location location) {
this.kraken = kraken2;
this.player = player;
this.location = location;
}

View File

@@ -56,23 +56,29 @@ public final class AlchemyPotionBrewer {
return item == null || item.getType() == Material.AIR || item.getAmount() == 0;
}
private static boolean removeIngredient(BrewerInventory inventory, Player player) {
private static void removeIngredient(BrewerInventory inventory, Player player) {
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
if (isEmpty(ingredient) || !isValidIngredient(player, ingredient)) {
return false;
return;
}
else if (ingredient.getAmount() <= 1) {
inventory.setIngredient(null);
return true;
return;
}
else {
ingredient.setAmount(ingredient.getAmount() - 1);
inventory.setIngredient(ingredient);
return true;
return;
}
}
private static boolean hasIngredient(BrewerInventory inventory, Player player) {
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
return !isEmpty(ingredient) && isValidIngredient(player, ingredient);
}
public static boolean isValidIngredient(Player player, ItemStack item) {
if (isEmpty(item)) {
return false;
@@ -99,7 +105,7 @@ public final class AlchemyPotionBrewer {
BrewerInventory inventory = ((BrewingStand) brewingStand).getInventory();
ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone();
if (!removeIngredient(inventory, player)) {
if (!hasIngredient(inventory, player)) {
return;
}
@@ -129,6 +135,8 @@ public final class AlchemyPotionBrewer {
return;
}
removeIngredient(inventory, player);
for (AlchemyPotion input : inputList) {
AlchemyPotion output = PotionConfig.getInstance().getPotion(input.getChildDataValue(ingredient));

View File

@@ -9,6 +9,7 @@ import org.bukkit.entity.LivingEntity;
import org.bukkit.inventory.ItemStack;
import com.gmail.nossr50.config.AdvancedConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.util.Misc;
public class Archery {
@@ -21,7 +22,7 @@ public class Archery {
public static double dazeBonusDamage = AdvancedConfig.getInstance().getDazeBonusDamage();
public static final double DISTANCE_XP_MULTIPLIER = 0.025;
public static final double DISTANCE_XP_MULTIPLIER = ExperienceConfig.getInstance().getArcheryDistanceMultiplier();
protected static void incrementTrackerValue(LivingEntity livingEntity) {
for (TrackedEntity trackedEntity : trackedEntities) {

View File

@@ -49,7 +49,7 @@ public class ArcheryManager extends SkillManager {
return;
}
applyXpGain((int) (firedLocation.distanceSquared(targetLocation) * Archery.DISTANCE_XP_MULTIPLIER), getXPGainReason(target, damager));
applyXpGain((int) (Math.min(firedLocation.distanceSquared(targetLocation), 2500) * Archery.DISTANCE_XP_MULTIPLIER), getXPGainReason(target, damager));
}
/**

View File

@@ -74,10 +74,16 @@ public class AxesManager extends SkillManager {
Player player = getPlayer();
player.sendMessage(LocaleLoader.getString("Axes.Combat.CriticalHit"));
if (mcMMOPlayer.useChatNotifications()) {
player.sendMessage(LocaleLoader.getString("Axes.Combat.CriticalHit"));
}
if (target instanceof Player) {
((Player) target).sendMessage(LocaleLoader.getString("Axes.Combat.CritStruck"));
Player defender = (Player) target;
if (UserManager.getPlayer(defender).useChatNotifications()) {
defender.sendMessage(LocaleLoader.getString("Axes.Combat.CritStruck"));
}
damage = (damage * Axes.criticalHitPVPModifier) - damage;
}

View File

@@ -110,6 +110,9 @@ public final class Fishing {
case PIG_ZOMBIE:
return TreasureConfig.getInstance().shakeFromPigZombie;
case PLAYER:
return TreasureConfig.getInstance().shakeFromPlayer;
case SHEEP:
return TreasureConfig.getInstance().shakeFromSheep;

View File

@@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.fishing;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -15,7 +16,6 @@ import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fish;
@@ -29,6 +29,8 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.SkullMeta;
import org.bukkit.material.Wool;
import org.bukkit.potion.Potion;
import org.bukkit.potion.PotionType;
@@ -104,7 +106,7 @@ public class FishingManager extends SkillManager {
vehicle.remove();
}
player.teleport(player.getTargetBlock(null, 100).getLocation(), TeleportCause.PLUGIN);
player.teleport(player.getTargetBlock((HashSet<Byte>) null, 100).getLocation(), TeleportCause.PLUGIN);
String unleashMessage = AdvancedConfig.getInstance().getPlayerUnleashMessage();
@@ -135,7 +137,7 @@ public class FishingManager extends SkillManager {
player.setItemInHand(null);
}
Creature kraken = (Creature) world.spawnEntity(player.getEyeLocation(), (Misc.getRandom().nextInt(100) == 0 ? EntityType.CHICKEN : EntityType.SQUID));
LivingEntity kraken = (LivingEntity) world.spawnEntity(player.getEyeLocation(), (Misc.getRandom().nextInt(100) == 0 ? EntityType.CHICKEN : EntityType.SQUID));
kraken.setCustomName(AdvancedConfig.getInstance().getKrakenName());
if (!kraken.isValid()) {
@@ -167,7 +169,7 @@ public class FishingManager extends SkillManager {
return false;
}
Block targetBlock = getPlayer().getTargetBlock(BlockUtils.getTransparentBlocks(), 100);
Block targetBlock = getPlayer().getTargetBlock((HashSet<Byte>) BlockUtils.getTransparentBlocks(), 100);
if (!targetBlock.isLiquid()) {
return false;
@@ -394,6 +396,45 @@ public class FishingManager extends SkillManager {
// Extra processing depending on the mob and drop type
switch (target.getType()) {
case PLAYER:
Player targetPlayer = (Player) target;
switch (drop.getType()) {
case SKULL_ITEM:
drop.setDurability((short) 3);
SkullMeta skullMeta = (SkullMeta) drop.getItemMeta();
skullMeta.setOwner(targetPlayer.getName());
drop.setItemMeta(skullMeta);
break;
case BED_BLOCK:
if (TreasureConfig.getInstance().getInventoryStealEnabled()) {
PlayerInventory inventory = targetPlayer.getInventory();
int length = inventory.getContents().length;
int slot = Misc.getRandom().nextInt(length);
drop = inventory.getItem(slot);
if (drop == null) {
break;
}
if (TreasureConfig.getInstance().getInventoryStealStacks()) {
inventory.setItem(slot, null);
}
else {
inventory.setItem(slot, (drop.getAmount() > 1) ? new ItemStack(drop.getType(), drop.getAmount() - 1) : null);
drop.setAmount(1);
}
targetPlayer.updateInventory();
}
break;
default:
break;
}
break;
case SHEEP:
Sheep sheep = (Sheep) target;
@@ -437,7 +478,7 @@ public class FishingManager extends SkillManager {
}
Misc.dropItem(target.getLocation(), drop);
CombatUtils.dealDamage(target, Math.max(target.getMaxHealth() / 4, 1)); // Make it so you can shake a mob no more than 4 times.
CombatUtils.dealDamage(target, Math.max(target.getMaxHealth() / 4, 1), getPlayer()); // Make it so you can shake a mob no more than 4 times.
applyXpGain(ExperienceConfig.getInstance().getFishingShakeXP(), XPGainReason.PVE);
}
}

View File

@@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.List;
import org.bukkit.CropState;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NetherWartsState;
import org.bukkit.block.BlockState;
@@ -235,15 +236,24 @@ public class HerbalismManager extends SkillManager {
Player player = getPlayer();
if (treasures.isEmpty() || !EventUtils.simulateBlockBreak(blockState.getBlock(), player, false)) {
if (treasures.isEmpty()) {
return false;
}
int skillLevel = getSkillLevel();
Location location = blockState.getLocation();
blockState.setType(Material.AIR);
Misc.dropItem(blockState.getLocation(), treasures.get(Misc.getRandom().nextInt(treasures.size())).getDrop());
player.sendMessage(LocaleLoader.getString("Herbalism.HylianLuck"));
return true;
for (HylianTreasure treasure : treasures) {
if (skillLevel >= treasure.getDropLevel() && SkillUtils.treasureDropSuccessful(getPlayer(), treasure.getDropChance(), activationChance)) {
if (!EventUtils.simulateBlockBreak(blockState.getBlock(), player, false)) {
return false;
}
blockState.setType(Material.AIR);
Misc.dropItem(location, treasure.getDrop());
player.sendMessage(LocaleLoader.getString("Herbalism.HylianLuck"));
return true;
}
}
return false;
}
/**

View File

@@ -17,7 +17,7 @@ public class Mining {
*
* @param blockState The {@link BlockState} to check ability activation for
*/
protected static int getBlockXp(BlockState blockState) {
public static int getBlockXp(BlockState blockState) {
Material blockType = blockState.getType();
int xp = ExperienceConfig.getInstance().getXp(SkillType.MINING, blockType != Material.GLOWING_REDSTONE_ORE ? blockType : Material.REDSTONE_ORE);
@@ -64,7 +64,8 @@ public class Mining {
case QUARTZ_ORE:
case REDSTONE_ORE:
case STONE:
Misc.dropItem(blockState.getLocation(), new ItemStack(blockType));
case PRISMARINE:
Misc.dropItem(blockState.getLocation(), blockState.getData().toItemStack(1));
return;
default:

View File

@@ -1,6 +1,7 @@
package com.gmail.nossr50.skills.mining;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.bukkit.Material;
@@ -93,7 +94,7 @@ public class MiningManager extends SkillManager {
*/
public void remoteDetonation() {
Player player = getPlayer();
Block targetBlock = player.getTargetBlock(BlockUtils.getTransparentBlocks(), BlastMining.MAXIMUM_REMOTE_DETONATION_DISTANCE);
Block targetBlock = player.getTargetBlock((HashSet<Byte>) BlockUtils.getTransparentBlocks(), BlastMining.MAXIMUM_REMOTE_DETONATION_DISTANCE);
if (targetBlock.getType() != Material.TNT || !EventUtils.simulateBlockBreak(targetBlock, player, true) || !blastMiningCooldownOver()) {
return;

View File

@@ -67,7 +67,7 @@ public class RepairManager extends SkillManager {
return;
}
if (!Permissions.repairMaterialType(player, repairable.getRepairMaterialType())) {
if (!Permissions.repairItemType(player, repairable.getRepairItemType())) {
player.sendMessage(LocaleLoader.getString("mcMMO.NoPermission"));
return;
}

View File

@@ -1,12 +1,20 @@
package com.gmail.nossr50.skills.smelting;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.block.BlockState;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.FurnaceBurnEvent;
import org.bukkit.inventory.FurnaceRecipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.datatypes.skills.SecondaryAbility;
import com.gmail.nossr50.datatypes.skills.SkillType;
@@ -14,10 +22,13 @@ import com.gmail.nossr50.datatypes.skills.XPGainReason;
import com.gmail.nossr50.events.skills.secondaryabilities.SecondaryAbilityWeightedActivationCheckEvent;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.skills.mining.Mining;
import com.gmail.nossr50.skills.smelting.Smelting.Tier;
import com.gmail.nossr50.util.BlockUtils;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
public class SmeltingManager extends SkillManager {
@@ -63,17 +74,51 @@ public class SmeltingManager extends SkillManager {
if (item == null) {
return false;
}
if (!EventUtils.simulateBlockBreak(blockState.getBlock(), player, true)) {
return false;
}
// We need to distribute Mining XP here, because the block break event gets cancelled
applyXpGain(Mining.getBlockXp(blockState), XPGainReason.PVE);
SkillUtils.handleDurabilityChange(getPlayer().getItemInHand(), Config.getInstance().getAbilityToolDamage());
Misc.dropItems(blockState.getLocation(), item, isSecondSmeltSuccessful() ? 2 : 1);
blockState.setType(Material.AIR);
player.sendMessage(LocaleLoader.getString("Smelting.FluxMining.Success"));
if (Config.getInstance().getFluxPickaxeSoundEnabled()) {
player.playSound(blockState.getLocation(), Sound.FIZZ, Misc.FIZZ_VOLUME, Misc.getFizzPitch());
}
ParticleEffectUtils.playFluxEffect(blockState.getLocation());
return true;
}
return false;
}
public static ItemStack getFluxPickaxe(Material material, int amount) {
ItemStack itemStack = new ItemStack(material, amount);
ItemMeta itemMeta = itemStack.getItemMeta();
itemMeta.setDisplayName(ChatColor.GOLD + LocaleLoader.getString("Item.FluxPickaxe.Name"));
List<String> itemLore = itemMeta.hasLore() ? itemMeta.getLore() : new ArrayList<String>();
itemLore.add("mcMMO Item");
itemLore.add(LocaleLoader.getString("Item.FluxPickaxe.Lore.1"));
itemLore.add(LocaleLoader.getString("Item.FluxPickaxe.Lore.2", Smelting.fluxMiningUnlockLevel));
itemMeta.setLore(itemLore);
itemStack.setItemMeta(itemMeta);
return itemStack;
}
public static FurnaceRecipe getFluxPickaxeRecipe(Material material) {
return new FurnaceRecipe(getFluxPickaxe(material, 1), material);
}
/**
* Increases burn time for furnace fuel.
*

View File

@@ -83,7 +83,7 @@ public class SwordsManager extends SkillManager {
}
if (SkillUtils.activationSuccessful(SecondaryAbility.COUNTER, getPlayer(), getSkillLevel(), activationChance)) {
CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier);
CombatUtils.dealDamage(attacker, damage / Swords.counterAttackModifier, getPlayer());
getPlayer().sendMessage(LocaleLoader.getString("Swords.Combat.Countered"));

View File

@@ -277,6 +277,7 @@ public class TamingManager extends SkillManager {
return;
}
location = Misc.getLocationOffset(location, 1);
LivingEntity entity = (LivingEntity) player.getWorld().spawnEntity(location, type);
FakeEntityTameEvent event = new FakeEntityTameEvent(entity, player);

View File

@@ -4,18 +4,13 @@ import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.entity.AnimalTamer;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.scheduler.BukkitRunnable;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.player.UserManager;
import com.gmail.nossr50.util.skills.CombatUtils;
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
@@ -23,18 +18,11 @@ public class TrackedTamingEntity extends BukkitRunnable {
private LivingEntity livingEntity;
private UUID id;
private int length;
private Player owner;
protected TrackedTamingEntity(LivingEntity livingEntity) {
this.livingEntity = livingEntity;
this.id = livingEntity.getUniqueId();
AnimalTamer tamer = ((Tameable)livingEntity).getOwner();
if (tamer != null && tamer instanceof Player) {
this.owner = (Player) tamer;
}
int tamingCOTWLength = Config.getInstance().getTamingCOTWLength(livingEntity.getType());
if (tamingCOTWLength > 0) {
@@ -52,14 +40,7 @@ public class TrackedTamingEntity extends BukkitRunnable {
CombatUtils.dealDamage(livingEntity, livingEntity.getMaxHealth(), DamageCause.SUICIDE, livingEntity);
}
if (!UserManager.hasPlayerDataKey(owner)) {
return;
}
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(owner);
TamingManager tamingManager = mcMMOPlayer.getTamingManager();
tamingManager.removeFromTracker(this);
TamingManager.removeFromTracker(this);
this.cancel();
}

View File

@@ -71,7 +71,14 @@ public class Unarmed {
}
// Inventory is full - cancel the item pickup
return false;
if (dropStack.getAmount() == dropAmount) {
return false;
} else {
drop.remove();
dropStack.setAmount(dropAmount);
((Item) drop.getWorld().dropItem(drop.getLocation(), dropStack)).setPickupDelay(0);
return true;
}
}
else if (firstEmpty != -1) {
drop.remove();

View File

@@ -19,6 +19,7 @@ import com.gmail.nossr50.datatypes.skills.ToolType;
import com.gmail.nossr50.locale.LocaleLoader;
import com.gmail.nossr50.skills.SkillManager;
import com.gmail.nossr50.util.EventUtils;
import com.gmail.nossr50.util.ItemUtils;
import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
@@ -48,7 +49,7 @@ public class UnarmedManager extends SkillManager {
public boolean canDeflect() {
Player player = getPlayer();
return player.getItemInHand().getType() == Material.AIR && Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.DEFLECT);
return ItemUtils.isUnarmed(player.getItemInHand()) && Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.DEFLECT);
}
public boolean canUseBlockCracker() {

View File

@@ -62,13 +62,7 @@ public final class Woodcutting {
species = ((Tree) blockState.getData()).getSpecies();
}
int xp = ExperienceConfig.getInstance().getWoodcuttingTreeXP(species);
if (species == TreeSpecies.JUNGLE && experienceGainMethod == ExperienceGainMethod.TREE_FELLER) {
xp *= 0.5;
}
return xp;
return ExperienceConfig.getInstance().getWoodcuttingTreeXP(species);
}
/**
@@ -86,6 +80,15 @@ public final class Woodcutting {
if (blockState.getData() instanceof Tree) {
species = ((Tree) blockState.getData()).getSpecies();
}
if (blockState.getType() == Material.LOG_2) {
byte data = blockState.getRawData();
if ((data & 1) != 0) {
species = TreeSpecies.ACACIA;
}
if ((data & 2) != 0) {
species = TreeSpecies.DARK_OAK;
}
}
if (Config.getInstance().getWoodcuttingDoubleDropsEnabled(species)) {
Misc.dropItems(blockState.getLocation(), blockState.getBlock().getDrops());

View File

@@ -63,6 +63,18 @@ public final class BlockUtils {
case DROPPER:
case HOPPER:
case TRAPPED_CHEST:
case IRON_DOOR:
case IRON_TRAPDOOR:
case ACACIA_DOOR:
case SPRUCE_DOOR:
case BIRCH_DOOR:
case JUNGLE_DOOR:
case DARK_OAK_DOOR:
case ACACIA_FENCE:
case DARK_OAK_FENCE:
case BIRCH_FENCE:
case JUNGLE_FENCE:
case ARMOR_STAND:
return false;
default:
@@ -161,6 +173,8 @@ public final class BlockUtils {
case SANDSTONE:
case STAINED_CLAY:
case STONE:
case PRISMARINE:
case RED_SANDSTONE:
return true;
default:

View File

@@ -117,7 +117,7 @@ public final class ChimaeraWing {
public static void chimaeraExecuteTeleport() {
Player player = mcMMOPlayer.getPlayer();
if (player.getBedSpawnLocation() != null) {
if (Config.getInstance().getChimaeraUseBedSpawn() && player.getBedSpawnLocation() != null) {
player.teleport(player.getBedSpawnLocation());
}
else {

View File

@@ -9,7 +9,6 @@ import org.bukkit.entity.Fish;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.plugin.PluginManager;
import com.gmail.nossr50.mcMMO;
@@ -280,26 +279,4 @@ public class EventUtils {
return event;
}
/**
* There is a bug in CraftBukkit that causes piston events to
* fire multiple times. Check this method to see if the piston event
* should be processed.
*
* @param block Block object of the piston block
* @param isExtendEvent should be true when called from BlockPistonExtendEvent
*
* @return true if the PistonEvent should be processed, false otherwise
*/
public static boolean shouldProcessEvent(Block block, boolean isExtendEvent) {
String pistonAction = isExtendEvent ? "EXTEND" : "RETRACT";
String lastAction = block.hasMetadata(mcMMO.pistonDataKey) ? block.getMetadata(mcMMO.pistonDataKey).get(0).asString() : "";
if (!lastAction.equals(pistonAction)) {
block.setMetadata(mcMMO.pistonDataKey, new FixedMetadataValue(mcMMO.p, pistonAction));
return true;
}
return false;
}
}

View File

@@ -13,6 +13,7 @@ import org.bukkit.material.Dye;
import com.gmail.nossr50.mcMMO;
import com.gmail.nossr50.config.party.ItemWeightConfig;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.locale.LocaleLoader;
public final class ItemUtils {
@@ -146,6 +147,20 @@ public final class ItemUtils {
}
}
/**
* Checks if the item counts as unarmed.
*
* @param item Item to check
* @return true if the item counts as unarmed, false otherwise
*/
public static boolean isUnarmed(ItemStack item) {
if (Config.getInstance().getUnarmedItemsAsUnarmed()) {
return !isMinecraftTool(item);
}
return item.getType() == Material.AIR;
}
/**
* Checks if the item is a helmet.
*
@@ -694,4 +709,13 @@ public final class ItemUtils {
ItemMeta itemMeta = item.getItemMeta();
return itemMeta.hasDisplayName() && itemMeta.getDisplayName().equals(ChatColor.GOLD + LocaleLoader.getString("Item.ChimaeraWing.Name"));
}
public static boolean isFluxPickaxe(ItemStack item) {
if (!isMcMMOItem(item)) {
return false;
}
ItemMeta itemMeta = item.getItemMeta();
return itemMeta.hasDisplayName() && itemMeta.getDisplayName().equals(ChatColor.GOLD + LocaleLoader.getString("Item.FluxPickaxe.Name"));
}
}

View File

@@ -19,7 +19,6 @@ public final class MaterialUtils {
case REDSTONE_ORE:
case EMERALD_ORE:
return true;
default:
return mcMMO.getModManager().isCustomOre(data);
}

View File

@@ -144,6 +144,23 @@ public final class Misc {
return "UnknownMods";
}
/**
* Gets a random location near the specified location
*/
public static Location getLocationOffset(Location location, double strength) {
double blockX = location.getBlockX();
double blockZ = location.getBlockZ();
double distance;
distance = strength * random.nextDouble();
blockX = (random.nextBoolean()) ? blockX + (distance) : blockX - (distance);
distance = strength * random.nextDouble();
blockZ = (random.nextBoolean()) ? blockZ + (distance) : blockZ - (distance);
return new Location(location.getWorld(), blockX, location.getY(), blockZ);
}
public static Random getRandom() {
return random;
}

View File

@@ -293,8 +293,8 @@ public class HashChunkManager implements ChunkManager {
return false;
}
int cx = x / 16;
int cz = z / 16;
int cx = x >> 4;
int cz = z >> 4;
String key = world.getName() + "," + cx + "," + cz;
if (!store.containsKey(key)) {
@@ -336,8 +336,8 @@ public class HashChunkManager implements ChunkManager {
return;
}
int cx = x / 16;
int cz = z / 16;
int cx = x >> 4;
int cz = z >> 4;
int ix = Math.abs(x) % 16;
int iz = Math.abs(z) % 16;
@@ -382,8 +382,8 @@ public class HashChunkManager implements ChunkManager {
return;
}
int cx = x / 16;
int cz = z / 16;
int cx = x >> 4;
int cz = z >> 4;
int ix = Math.abs(x) % 16;
int iz = Math.abs(z) % 16;

View File

@@ -340,7 +340,7 @@ public class ScoreboardManager {
}
for (String playerName : dirtyPowerLevels) {
McMMOPlayer mcMMOPlayer = UserManager.getOfflinePlayer(playerName);
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(playerName);
if (mcMMOPlayer == null) {
continue;

View File

@@ -199,6 +199,13 @@ public class ScoreboardWrapper {
// TODO is there any way to do the time that looks acceptable?
// player.sendMessage(LocaleLoader.getString("Commands.Scoreboard.Timer", StringUtils.capitalize(sidebarType.toString().toLowerCase()), ticks / 20F));
PlayerProfile profile = UserManager.getPlayer(player).getProfile();
if (profile.getScoreboardTipsShown() >= Config.getInstance().getTipsAmount()) {
return;
}
if (!tippedKeep) {
tippedKeep = true;
player.sendMessage(LocaleLoader.getString("Commands.Scoreboard.Tip.Keep"));
@@ -206,6 +213,7 @@ public class ScoreboardWrapper {
else if (!tippedClear) {
tippedClear = true;
player.sendMessage(LocaleLoader.getString("Commands.Scoreboard.Tip.Clear"));
profile.increaseTipsShown();
}
}

View File

@@ -10,6 +10,7 @@ import org.bukkit.entity.Animals;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Guardian;
import org.bukkit.entity.IronGolem;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@@ -47,7 +48,6 @@ import com.gmail.nossr50.util.Misc;
import com.gmail.nossr50.util.MobHealthbarUtils;
import com.gmail.nossr50.util.Permissions;
import com.gmail.nossr50.util.player.UserManager;
import com.google.common.collect.ImmutableMap;
public final class CombatUtils {
@@ -250,7 +250,7 @@ public final class CombatUtils {
processAxeCombat(target, player, event);
}
}
else if (heldItem.getType() == Material.AIR) {
else if (ItemUtils.isUnarmed(heldItem)) {
if (!SkillType.UNARMED.shouldProcess(target)) {
return;
}
@@ -466,6 +466,7 @@ public final class CombatUtils {
switch (type) {
case BAT:
case SQUID:
case RABBIT:
baseXP = ExperienceConfig.getInstance().getAnimalsXP();
break;
@@ -484,6 +485,7 @@ public final class CombatUtils {
case WITCH:
case WITHER:
case ZOMBIE:
case ENDERMITE:
baseXP = ExperienceConfig.getInstance().getCombatXP(type);
break;
@@ -504,6 +506,14 @@ public final class CombatUtils {
}
break;
case GUARDIAN:
if (((Guardian) target).isElder()) {
baseXP = ExperienceConfig.getInstance().getElderGuardianXP();
} else {
baseXP = ExperienceConfig.getInstance().getCombatXP(type);
}
break;
default:
baseXP = 1.0;
mcMMO.getModManager().addCustomEntity(target);
@@ -515,6 +525,10 @@ public final class CombatUtils {
baseXP *= ExperienceConfig.getInstance().getSpawnedMobXpMultiplier();
}
if (target.hasMetadata(mcMMO.bredMetadataKey)) {
baseXP *= ExperienceConfig.getInstance().getBredMobXpMultiplier();
}
xpGainReason = XPGainReason.PVE;
baseXP *= 10;

View File

@@ -37,6 +37,14 @@ public final class ParticleEffectUtils {
playSmokeEffect(player);
}
public static void playFluxEffect(Location location) {
if (!Config.getInstance().getFluxEffectEnabled()) {
return;
}
location.getWorld().playEffect(location, Effect.MOBSPAWNER_FLAMES, 1);
}
public static void playSmokeEffect(LivingEntity livingEntity) {
Location location = livingEntity.getEyeLocation();
World world = livingEntity.getWorld();

View File

@@ -90,7 +90,7 @@ Skills:
# Modifier: Extra damage for arrows that cause a daze (2 damage = 1 heart)
ChanceMax: 50.0
MaxBonusLevel: 1000
Modifier: 4.0
BonusDamage: 4.0
Retrieve:
# ChanceMax: Maximum chance of retrieving arrows when on <MaxBonusLevel> or higher

View File

@@ -20,6 +20,8 @@ General:
Update_Check: true
Prefer_Beta: false
Power_Level_Cap: 0
# Should mcMMO truncate levels if you lower your max level cap for a skillname
TruncateSkills: false
# Should mcMMO print out debug messages?
Verbose_Logging: false
# Should mcMMO over-write configs to update, or make new ones ending in .new?
@@ -45,6 +47,10 @@ Scoreboard:
# Show the /mcstats scoreboard automatically after logging in
Show_Stats_After_Login: false
# Show scoreboard tips 5 times. Tips are only displayed once for every login session.
# Set to 0 to never show these tips.
Tips_Amount: 5
# Add some more color on the board :-)
Rainbows: false
@@ -207,10 +213,15 @@ Items:
Warmup: 5
RecentlyHurt_Cooldown: 60
Prevent_Use_Underground: true
# Attempt to use the bed spawn, if one is available
Use_Bed_Spawn: true
Use_Cost: 1
Recipe_Cost: 5
Item_Name: FEATHER
Sound_Enabled: true
Flux_Pickaxe:
Enabled: true
Sound_Enabled: true
#
# Settings for Parties
@@ -386,6 +397,8 @@ Skills:
# When using Unarmed, picked up items will automatically get moved to a free slot instead of going in the slot
# of your hand. Should item pickup be disabled when your entire inventory - except for your hand - is full?
Item_Pickup_Disabled_Full_Inventory: true
# Any attacks made without a tool, i.e. with one's open hand, a block, etc., will count as unarmed.
Items_As_Unarmed: false
Woodcutting:
Tree_Feller_Sounds: true
Level_Cap: 0
@@ -479,8 +492,9 @@ Particles:
LargeFireworks: true
# Use particle effect when these abilities trigger
Dodge: true
Bleed: true
Dodge: true
Flux: true
Greater_Impact: true
Call_of_the_Wild: true

View File

@@ -37,6 +37,8 @@ Experience_Formula:
# Experience gained from mobs not naturally spawned will get multiplied by this value. 0 by default.
Mobspawners:
Multiplier: 0
Breeding:
Multiplier: 1.0
# Experience gained will get divided by these values. 1.0 by default, 2.0 means two times less XP gained.
Modifier:
@@ -116,6 +118,8 @@ Experience:
Potion_Stage_3: 60
Potion_Stage_4: 120
Potion_Stage_5: 0
Archery:
Distance_Multiplier: 0.025
Fishing:
Raw_Fish: 800
Raw_Salmon: 800
@@ -196,6 +200,8 @@ Experience:
Sandstone: 30
Stained_Clay: 50
Stone: 30
Red_Sandstone: 100
Prismarine: 70
Repair:
Base: 1000.0
Wood: 0.6
@@ -241,3 +247,6 @@ Experience:
Witch: 0.0
Iron_Golem: 2.0
Wither_Skeleton: 4.0
Endermite: 2.0
Guardian: 3.0
Elder_Guardian: 4.0

File diff suppressed because it is too large Load Diff

View File

@@ -835,6 +835,9 @@ Item.ChimaeraWing.Name=Chimaera Wing
Item.ChimaeraWing.Lore=[[GRAY]]Teleports you to your bed.
Item.Generic.Wait=[[RED]]You need to wait before you can use this again! [[YELLOW]]({0}s)
Item.Injured.Wait=You were injured recently and must wait to use this. [[YELLOW]]({0}s)
Item.FluxPickaxe.Name=Flux Pickaxe
Item.FluxPickaxe.Lore.1=[[GRAY]]Has a chance of instantly smelting ores.
Item.FluxPickaxe.Lore.2=[[GRAY]]Requires Smelting level {0}+
#TELEPORTATION
Teleport.Commencing=[[GRAY]]Commencing teleport in [[GOLD]]({0}) [[GRAY]]seconds, please stand still...
@@ -908,7 +911,6 @@ Smelting.Effect.4=Vanilla XP Boost
Smelting.Effect.5=Increase vanilla XP gained while smelting
Smelting.Effect.6=Flux Mining
Smelting.Effect.7=Chance for ores to be instantly smelted while mining
Smelting.FluxMining.Success=[[GREEN]]That ore smelted itself!
Smelting.Listener=Smelting:
Smelting.SkillName=SMELTING

View File

@@ -22,9 +22,9 @@ Archery.Effect.2=Stordire (Giocatori)
Archery.Effect.3=Disorienta i nemici e infligge {0} Danni
Archery.Effect.4=Recupero Frecce
Archery.Effect.5=Probabilit\u00e0 di recuperare frecce dai cadaveri
Archery.Listener=Tiro con l\'Arco:
Archery.SkillName=TIRO CON L\'ARCO
Archery.Skillup=[[YELLOW]]L\'abilit\u00e0 Tiro con l\'Arco \u00e8 aumentata di {0}. Total ({1})
Archery.Listener=Arco:
Archery.SkillName=ARCO
Archery.Skillup=[[YELLOW]]L\'abilit\u00e0 Arco \u00e8 aumentata di {0}. Total ({1})
Axes.Ability.Bonus.0=Maestria con l\'Ascia
Axes.Ability.Bonus.1={0} Danni Bonus
Axes.Ability.Bonus.2=Sfonda Armature

File diff suppressed because it is too large Load Diff

View File

@@ -12,8 +12,7 @@ description: >
author: nossr50
authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking]
website: http://dev.bukkit.org/server-mods/mcmmo/
website: www.spigotmc.org/resources/mcmmo.2445/
main: com.gmail.nossr50.mcMMO
softdepend: [CombatTag, HealthBar]
load: STARTUP

View File

@@ -793,6 +793,16 @@ Shake:
XP: 0
Drop_Chance: 50.0
Drop_Level: 0
PLAYER:
SKULL_ITEM:
Amount: 1
XP: 0
Drop_Chance: 0.0
Drop_Level: 0
INVENTORY:
Whole_Stacks: false
Drop_Chance: 0.0
Drop_Level: 0
SHEEP:
WOOL:
Amount: 3