From b09a0bc9db45c15bfb428f06d8397c4cd3af4f53 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 25 Jul 2018 21:51:42 +0200 Subject: [PATCH 001/115] v1.13.0 - slowly work our way to Spigot 1.13 - ANYONE USING THIS BUILD IS CRAZY --- doc/changelog.md | 349 +----------------- doc/history/0.1.md | 16 + doc/history/0.10.md | 97 +++++ doc/history/0.2.md | 4 + doc/history/0.3.md | 17 + doc/history/0.4.md | 7 + doc/history/0.5.md | 13 + doc/history/0.6.md | 83 +++++ doc/history/0.7.md | 90 +++++ doc/history/0.8.md | 92 +++++ doc/history/0.9.md | 203 ++++++++++ doc/history/1.0.md | 284 ++++++++++++++ doc/history/1.1.md | 131 +++++++ doc/history/1.2.md | 78 ++++ doc/history/1.3.0.md | 66 ++++ doc/history/1.3.1.md | 47 +++ doc/history/1.3.2.md | 79 ++++ doc/history/1.3.3.md | 112 ++++++ doc/history/1.3.4.md | 52 +++ pom.xml | 4 +- readme.md | 4 +- .../slipcor/pvparena/arena/ArenaClass.java | 30 +- .../slipcor/pvparena/arena/ArenaPlayer.java | 7 +- .../slipcor/pvparena/commands/PAA_Setup.java | 7 +- .../slipcor/pvparena/core/StringParser.java | 133 ++++--- .../pvparena/goals/GoalBlockDestroy.java | 8 +- .../pvparena/goals/GoalDomination.java | 11 +- src/net/slipcor/pvparena/goals/GoalFlags.java | 4 +- src/net/slipcor/pvparena/goals/GoalFood.java | 12 +- .../pvparena/goals/GoalPhysicalFlags.java | 21 +- .../pvparena/goals/GoalTeamDeathConfirm.java | 7 - .../pvparena/listeners/PlayerListener.java | 2 +- .../managers/ConfigurationManager.java | 219 ----------- .../pvparena/regions/CuboidRegion.java | 2 +- .../pvparena/regions/CylindricRegion.java | 2 +- .../pvparena/regions/SphericRegion.java | 2 +- .../runnables/InventoryRefillRunnable.java | 8 +- src/plugin.yml | 2 +- 38 files changed, 1608 insertions(+), 697 deletions(-) create mode 100644 doc/history/0.1.md create mode 100644 doc/history/0.10.md create mode 100644 doc/history/0.2.md create mode 100644 doc/history/0.3.md create mode 100644 doc/history/0.4.md create mode 100644 doc/history/0.5.md create mode 100644 doc/history/0.6.md create mode 100644 doc/history/0.7.md create mode 100644 doc/history/0.8.md create mode 100644 doc/history/0.9.md create mode 100644 doc/history/1.0.md create mode 100644 doc/history/1.1.md create mode 100644 doc/history/1.2.md create mode 100644 doc/history/1.3.0.md create mode 100644 doc/history/1.3.1.md create mode 100644 doc/history/1.3.2.md create mode 100644 doc/history/1.3.3.md create mode 100644 doc/history/1.3.4.md diff --git a/doc/changelog.md b/doc/changelog.md index 1fb81cb99..5d6e1d1ed 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,347 +1,4 @@ -- v1.3.4.298 - attempt to properly back up NBT data of player's items in case of an unnatural leaving of the arena +== PVP-Arena v1.13 Changelog + +- v1.13.0 - slowly work our way to Spigot 1.13 -- v1.3.4.297 - address github issue #351 - add yet another delay to fix Spigot -- v1.3.4.296 - address github issue #329 - actually change the scoreboard title :O -- v1.3.4.295 - fix the fact that the scoreboard did not update on losing the last life. Thanks to @Oruss7 -- v1.3.4.294 - add team size and total team count when joining -- v1.3.4.293 - address github issue #332 - display first checkpoint message, and display numbers starting from 1 -- v1.3.4.292 - address github issue #329 - use arena prefix instead of name, if still too long, shorten manually -- v1.3.4.291 - added debug to PotionSplashEvent for someone to have evidence to report a bug -- v1.3.4.290 - when setting up a region, check that it has actual resulting volume before saving -- v1.3.4.289 - address github issue #324 - call home asynchronously -- v1.3.4.288 - stop igniting your own TNT - and tell people that it is not okay -- v1.3.4.287 - update EventActions docs to properly reflect the node names -- v1.3.4.286 - update EventActions docs and fix github issue #314 by not stopping arenas twice on reload! -- v1.3.4.285 - allow to update spawn and blocks on the fly -- v1.3.4.284 - fix docs [remove colorteams and scoreboard] and add language and docs for BetterClass "respawnCommand" -- v1.3.4.283 - add EventActions addition (classchange hook) -- v1.3.4.282 - address github issue #305 - check max health before setting health -- v1.3.4.281 - address github issue #302 - prevent NPE for spectators when joining the arena -- v1.3.4.280 - remove debug output of time message nodes -- v1.3.4.279 - add github issue #249 - playSound (???) to add particle effect, DONE -- v1.3.4.278 - add github issue #124 - add timer configs to add/remove/change timer interval messages -- v1.3.4.277 - add github issue #117 - BossBar for Domination -- v1.3.4.276 - do not setup a scoreboard if spectating is cancelled/not possible -- v1.3.4.275 - allow right clicking blocks when LOST attempt 2 -- v1.3.4.274 - allow right clicking blocks when LOST and add Region Protection Tutorial -- v1.3.4.273 - update player equip function to support offhand slots -- v1.3.4.272 - properly protect and not overprotect, affected: MOBS [block lightning], TNT [prevent entity damage], GROW [actually block block growth] -- v1.3.4.271 - remove metrics and update the readme with new region shape tutorial -- v1.3.4.270 - do not add spectator names to the scoreboard -- v1.3.4.269 - update the spectator scoreboard -- v1.3.4.268 - create a scoreboard for spectators -- v1.3.4.267 - address github issue #291 by adding "perms.spectatorinteract" to allow spectators to interact -- v1.3.4.266 - remove debug and address github issue #292 by checking if a player already joined an arena before doing anything -- v1.3.4.265 - how I miss those debug times. IS THE PLAYER FLYING OR NOT!??!! -- v1.3.4.264 - why not try without delay? -- v1.3.4.263 - change fly mode saving and restoring -- v1.3.4.262 - do not restore flying state if specating on death -- v1.3.4.261 - delay flying mode setting by 5 ticks when restoring a player -- v1.3.4.260 - address github issue #290 - catch NPE about Spawn Eggs -- v1.3.4.259 - finish off github issue #280 by adding a proper message about reloading the languages -- v1.3.4.258 - finish the fix for issue #198 by supporting beacon block definitions -- v1.3.4.257 - address github issue #198 - make particle circle function goal independant -- v1.3.4.256 - address github issue #285 - catch NPE by checking for missing round argument -- v1.3.4.255 - address github issue #263 - properly cancel interact event - I assumed that they come uncancelled - wrong -- v1.3.4.254 - who ordered .lck files? Not me! Byebye! [debugging file handler not closed] -- v1.3.4.253 - hotfix about cancelling PlayerItemConsumeEvent - sorry @mibby, fasting is over now! -- v1.3.4.252 - fix issue #263 by cancelling PlayerItemConsumeEvent - since when is this a necessity? The interact event was cancelled :P -- v1.3.4.251 - fix spawn alignment glitches, some of which were fixed by restarting the server, fix double messages around right clicking -- v1.3.4.250 - update some things to the latest API - fix CheckPoints spawn set logic, fix PlayerDeathMatch required kill display -- v1.3.4.249 - update to Spigot 1.11 - address github issue #218 -- v1.3.3.248 - /pa reload ymls | reload main config, language and help ymls -- v1.3.3.247 - do not duplicate offhand items and don't try to set objectives that are not needed (because of disabled scoreboard) -- v1.3.3.246 - address github issue #280, reload global language and help nodes on /pa reload -- v1.3.3.245 - revert player names appearing on scoreboards, maybe properly display 0 team lives left? -- v1.3.3.244 - catch an NPE about scoreboards and dead/offline players and fix a scoreboard crash vulnerability -- v1.3.3.243 - eventually delay scoreboard display to arena start, delay inventory reset to when a player gets put back to their exit spawn, delay fire tick reset -- v1.3.3.242 - properly reset scoreboard when simply leaving by command -- v1.3.3.241 - address github issue #278 - support "hand" placeholder for multiple-item-definitions too -- v1.3.3.240 - address github issue #276 by catching the NPE even deeper -- v1.3.3.239 - fix inventory double drop bug when losing the last life -- v1.3.3.238 - allow for default death messaeges by setting both deathmessage config nodes to false -- v1.3.3.237 - address github issue #271 - do not remove/use player list scoreboard if scoreboard is disabled -- v1.3.3.236 - address github issue #273 - add Elytra to chestplate definition list -- v1.3.3.235 - address github issue #274 - fix player leaving handling in general -- v1.3.3.234 - properly require permission for /pa command -- v1.3.3.233 - address github issue #273 - single item definitions (maybe more) gets lost until restart -- v1.3.3.232 - add github issue #258 - liberation scoreboard separation of jailed players -- v1.3.3.231 - add github issue #198 - particle display of domination claim radius -- v1.3.3.230 - add github issue #237 - items on kill, settable via command and "inventory" handle! -- v1.3.3.229 - address github issue #254 - update Arrow Hack for Spigot > 1.9 -- v1.3.3.228 - address github issue #151 and try to add a custom scoreboard entry to show round progress -- v1.3.3.227 - fix scoreboard removal and fix a bug that caused doubled starting method call -- v1.3.3.226 - allow longer scoreboard entries (48 characters for now) -- v1.3.3.225 - reintroduce custom scoreboard entries -- v1.3.3.224 - address github issue #264 - ArenaClass equipping debug triggers NPE -- v1.3.3.223 - address github issue #267 - critical fix about gamemodes -- v1.3.3.222 - fix grabbing the flag giving you no wool head -- v1.3.3.221 - refresh debug instance for global debug when stopping / changing debug output -- v1.3.3.220 - further ID fixes, and fix a but about GameMode setting and one about players being able to join an arena when it is restoring -- v1.3.3.219 - finish the item ID burial -- v1.3.3.218 - stop supporting item IDs in configs - configs shall be updated! -- v1.3.3.217 - do not nag people to update if updater type DOWNLOAD is selected - addresses github issue #244 -- v1.3.3.216 - address a bug about invisibility being nullified by internal scoreboard -- v1.3.3.215 - address issue #238 by adding refillCustomInventory - defaulting to true -- v1.3.3.214 - address issue #255 - Remove arrows stuck to everyone -- v1.3.3.213 - address issue #256 - Exception about ScoreBoards when shutting down -- v1.3.3.212 - fix issue #252 by catching a NPE -- v1.3.3.211 - revert c67e4a6 - never mess with flying speed or walking speed again plz :P -- v1.3.3.210 - revert 4f75803 - never mess with flying speed or walking speed again plz :P -- v1.3.3.209 - final attempt to get rid of the speed issue - deactivate with -10 -- v1.3.3.208 - address issues with commit 4f75803 -- v1.3.3.207 - address github issues #245 and #248 -- v1.3.3.206 - finish the spawn region fix -- v1.3.3.205 - continue attemmpt to fix region spawning -- v1.3.3.204 - revert the last commit and try to fix region spawning -- v1.3.3.203 - try to fix an issue about respawning players not getting reset properly -- v1.3.3.202 - try to finish off github issue #212 by delaying scoreboard slot selection and player removal -- v1.3.3.201 - allow to disable all gamemode changes; make "takeOutOfGame" actually work -- v1.3.3.200 - prevent the plugin from messing up player restoring in certain reset cases -- v1.3.3.199 - address github issue #238 - allow to keep ALL items on respawn -- v1.3.3.198 - add "teleportonkill" to allow force respawn of killers -- v1.3.3.197 - address github issue #238 - allow to keep ALL items on respawn -- v1.3.3.196 - address github issue #240 - message consistency -- v1.3.3.195 - address github issue #241 - don't use Location, use Vectors for offset -- v1.3.3.194 - fix github issue #232 - Potions disappearing when readying up -- v1.3.3.193 - fix StatisticsManager to actually be persistent. SORRY! -- v1.3.3.192 - add config for github issue #220 -- v1.3.3.191 - fix github issue #188 - I found the right way to deactivate collision -- v1.3.3.190 - address github issue #120 - limiting class changes -- v1.3.3.189 - address github issue #99 - can we finally bury this? ^^ -- v1.3.3.188 - [FFA] allow to punish being killed by other things than a player: punishsuicide -- v1.3.3.187 - allow to set keepOnRespawn to "all" to, yes, keep all items -- v1.3.3.186 - implement ColorTeams and ScoreBoards modules into core - addresses github issue #212 -- v1.3.3.185 - add an announcement verification hack to WarmupJoin -- v1.3.3.184 - revert build #177 (saturation lock), does not work anyways -- v1.3.3.183 - very important module fix - player resetting was broken! -- v1.3.3.182 - reduce command whitelist case sensitivity -- v1.3.3.181 - reduce command case sensitivity -- v1.3.3.180 - allow modules to know whether to soft reset a player -- v1.3.3.179 - fix config node typo -- v1.3.3.178 - allow to quick leave with caps lock -- v1.3.3.177 - add saturation lock, to prevent regains going crazy -- v1.3.3.176 - apply global and specific teleport offset when resetting player -- v1.3.3.175 - fix github issue #230 -- v1.3.3.174 - little thing about #230 and add more debug to see why it might not work yet -- v1.3.3.173 - address github issue #222, again -- v1.3.3.172 - finish github issue #225 -- v1.3.3.171 - add github issue #230 - apply the teleport protection to the lounge, too, to prevent teleport warnings -- v1.3.3.170 - try to fix disabling breaking arena shortcut rotation -- v1.3.3.169 - maybe fix an issue that shortcut rotation doesn't work when the arenas are disabled at start -- v1.3.3.168 - partially revert breaking #222 even more -- v1.3.3.167 - address github issue #227 - reset killer's items to KILLER's class -- v1.3.3.166 - maybe finally tackle github issue #222 -- v1.3.3.165 - properly implement github issue #225 -- v1.3.3.164 - finish up github issue #203 -- v1.3.3.163 - address github issue #224 -- v1.3.3.162 - address all remnants of issue #203 -- v1.3.3.161 - address github issue #224 - double output in the lounge -- v1.3.3.160 - I got an idea, how about we actually implement issue #188 ?! oh and add issue #225 -- v1.3.3.159 - address github issue #222 -- v1.3.3.158 - continue fixing the issue mentioned in build #153 -- v1.3.3.157 - address github issue #222, again -- v1.3.3.156 - change the updating process and block installing/updating when there is no install.yml due to "update.files" (you can allow this setting and disable automatic updates with updatemode "none" or "announce") -- v1.3.3.155 - remove spectral arrows from the potion meta list, those don't seem to have potion effects -- v1.3.3.153 - try to fix the issue of lounge players not being able to interact where they should -- v1.3.3.152 - try to implement github issue #188 -- v1.3.3.151 - add config setting for github issue #188 -- v1.3.3.150 - address github issue #131 - if it's not fixed, I at least added debug -- v1.3.3.149 - address github issue #215 by removing a never launched minigame API and make sure to get the proper shortcut name, if possible -- v1.3.3.148 - finally fix github issue #205 -- v1.3.3.147 - prevent inventory dropping even if custom class is active -- v1.3.3.146 - found the little bug that caused github issue #205 ! -- v1.3.3.145 - partially revert d8d9bf174027aadc6ccd641b6cef7b660f435f25 to address github issue #205 -- v1.3.3.144 - potions are operational. Please update your class definitions (if you did not use class chests) -- v1.3.3.143 - please use the same logic for saving and loading -- v1.3.3.142 - potions should work now. Please redo all your potionish classes (potions, splash potions, lingering, arrows, etc) -- v1.3.3.141 - try to fix armor supply -- v1.3.3.140 - properly fix Potion creation/saving broken by Spigot 1.9 API changes -- v1.3.3.139 - properly fix Inventory handling broken by Spigot 1.9 API changes -- v1.3.3.138 - move to Spigot 1.9.4 -- v1.3.2.137 - address github issue #205 -- v1.3.2.136 - add language response for ChestFiller -- v1.3.2.135 - add documentation about ChestFiller changes, add some more config nodes that are now properly loaded with defaults automatically -- v1.3.2.134 - address github issue #201 - properly call PAJoinEvent, this never was implemented correctly. Sorry! -- v1.3.2.133 - prepare ChestFiller addition by adding language and documentation -- v1.3.2.132 - prepare ChestFiller addition by adding config node -- v1.3.2.131 - remove FallingAnvils hooks and documentation - it did not work out :/ -- v1.3.2.130 - stop spamming, please. Aims at fixing github issue #154 -- v1.3.2.129 - address github issue #209 - oups -- v1.3.2.128 - add a module method "parseStartCountDown" to possibly override the remaining seconds to go -- v1.3.2.127 - fix github issue #204 by removing all traces of the nonexisting command "import" -- v1.3.2.126 - address github issue #202 - remove "error" and only write it to debug -- v1.3.2.125 - address github issue #155, prevent double dropping of inventory. Hope this does not break anything :P -- v1.3.2.124 - address github issue #154 - just remove tick 4, it's not that important anyways. And remove the blocklist spam :) -- v1.3.2.122 - furthermore fix the uninstall routine -- v1.3.2.121 - address github issue #131 - I think I found the bug! -- v1.3.2.120 - address github issue #203 by firstly fixing the NPE and adding more info to the uninstalling error (Main server log!) -- v1.3.2.119 - prevent double instantiation of arenas - use with caution! :P -- v1.3.2.118 - [CheckPoints] - address github issue #197 -- v1.3.2.117 - [BetterFight] add config setting to restrict explosions only to one-hit deaths -- v1.3.2.116 - add CheckPoint goal (github issue #184) - have fun testing! -- v1.3.2.115 - add "refillforkill" - restocks the inventory with the class items -- v1.3.2.114 - address github issue #191 - prevent NPE due to NULL item in class items -- v1.3.2.113 - add more debug to investigate fire charge ignition issues -- v1.3.2.112 - continue fix for Scoreboards being double reset in modules -- v1.3.2.111 - prepare fix for Scoreboards being double reset in modules -- v1.3.2.110 - address github issue #185 by fixing WorldEdit documentation and messages -- v1.3.2.109 - address github issue #186 -- v1.3.2.107 - address github issue #178 - prevent enderpearl teleport when not alive and fighting -- v1.3.2.106 - [TeamDeathMatch] fix a double broadcast of the winning team -- v1.3.2.105 - fix the documentation for EventAction config -- v1.3.2.103 - furthermore attempt to fix #175 by adding a teleport lock variable -- v1.3.2.102 - support multiple WATCH and LOUNGE regions - addresses github issue #175 -- v1.3.2.101 - finish github issue #174 -- v1.3.2.100 - address github issue #174 -- v1.3.2.99 - add Beacons settings and documentation -- v1.3.2.97 - add Titles API hooks, documentation will follow -- v1.3.2.96 - add a configuration node to change the schematics folder for WorldEdit - adds github issue #129 -- v1.3.2.95 - add region command documentation - thanks @Oruss7 -- v1.3.2.94 - add Language for special Duel/Vault hooking -- v1.3.2.93 - add config settings and documentation for the FallingAnvils module -- v1.3.2.92 - [forcewin] how about we load the command so it can be used? -- v1.3.2.91 - add /pa [arena] forcewin, shorthand !fw - forces a player / team to win -- v1.3.2.90 - fix some more errors about the new command. Works now :) -- v1.3.2.89 - fix the shorthand and the doc linking -- v1.3.2.88 - add /pa [arena] classchest [class] - shorthand !cc - fixed class chests containing the items -- v1.3.2.87 - address github issue #168, NPE on StructureGrowEvent -- v1.3.2.85 - revert deprecation of ArenaModule.getArena() - failsafe(r) loading of modules and goals - arenas will not appear lost any more! -- v1.3.2.84 - address github issue #161, properly read ambiguous ready block definition -- v1.3.2.83 - address github issue #159 - do not instanciate the tracker if disabled -- v1.3.2.82 - address github issue #158 by adding 'shortcut_shuffle' -- v1.3.2.81 - address github issue #154, maybe even issue #86 - only check necessarily flagged regions and BATTLE regions, with include-check -- v1.3.2.80 - properly fix build #68 -- v1.3.2.79 - add TELEPORT protection to allow teleport prevention (it was silently allowed if only happening IN the region, without command) -- v1.3.2.78 - change WALLS config setting command to "wallseconds", it interfered with the most probable arena name -- v1.3.2.77 - revert the CommandPreProcessEvent and rather fix the underlying problem, the command whitelist being too greedy. Added a config setting to use comand list as wildcards -- v1.3.2.76 - enforce player and teamplayer max values, move CommandPreProcessEvent to priority low to fix MobArena join related exploits -- v1.3.2.75 - properly save an ArenaGoal name to the round map (instead of its instance) -- v1.3.2.74 - fix a NPE in the EndRunnable when using rounds -- v1.3.2.73 - add a new command "regionclear" to manage region clearing exceptions -- v1.3.2.72 - add language and documentation for the WorldEdit addition -- v1.3.2.71 - add WorldEdit config to specify regions to autoload/autosave -- v1.3.2.70 - allow data values in MATERIAL definitions (only works with /pa set [node] hand) -- v1.3.2.69 - properly apply rewards when teamrewards is used -- v1.3.2.68 - remove repo pushing to maybe fix building for now -- v1.3.2.64 - fix issue #143 - thanks to Oruss7! -- v1.3.2.63 - add some message output when class changing fails -- v1.3.2.62 - prepare module class change hooking -- v1.3.2.61 - address github issue #114 - add LibsDisguises support -- v1.3.2.60 - fix CTF being messed up by people continuing to play -- v1.3.2.59 - fix update check -- v1.3.2.58 - /pa help - it still shows the colored standard reply even with sub-arguments -- v1.3.2.57 - address github issue #135 - language addition -- v1.3.2.56 - address github issue #141 - add config calcoffset to tweak block dissolve greediness -- v1.3.2.55 - fix Spectate Spectators being told they cannot teleport when switching view -- v1.3.2.54 - new Module: Spectate - uses the 1.8 SPECTATOR GameMode -- v1.3.2.51 - update to Java 7 -- v1.3.1.49 - fix an NPE on server shutdown -- v1.3.1.48 - update all the things in the doc -- v1.3.1.46 - pull #106 - thanks a TON to @Oruss7 for putting together this load of information! -- v1.3.1.45 - the final update for 1.7.9 - unless critical errors arrive. I need to get ready for 1.9 -- v1.3.1.44 - prevent an NPE in the WarmupJoin module -- v1.3.1.43 - revert the last commit and furthermore clarify and verify correctly. Modules build incoming -- v1.3.1.42 - fix a logic messups in an internal join check -- v1.3.1.41 - duel module finished -- v1.3.1.40 - allow to disable the Duel force ready & start -- v1.3.1.39 - duel module language finish -- v1.3.1.38 - finish off github issue #118 -- v1.3.1.37 - more shurtcut arena list fixes -- v1.3.1.36 - try to fix the round arena status check -- v1.3.1.35 - apply former fix for arena listing -- v1.3.1.34 - override only_shortcuts with allow_ungrouped to allow joining arenas not grouped under shortcuts -- v1.3.1.33 - properly format and save spawn offsets -- v1.3.1.32 - properly format and save spawn offsets -- v1.3.1.31 - properly allow for 5 arguments of /pa spawn -- v1.3.1.30 - fix github issues #115, #118 -- v1.3.1.29 - address github issue #112 -- v1.3.1.28 - how about we don't delete the spawn after offsetting it? -.- -- v1.3.1.26 - github issue #104 - EXPERIMENTAL! -- v1.3.1.25 - this time for real - we need to tell people they CAN decline :) -- v1.3.1.24 - add final language for github issue #97 -- v1.3.1.23 - add config for github issue #86 -- v1.3.1.22 - release build -- v1.3.1.21 - and more language nodes -- v1.3.1.20 - prepare Dual fixes and commit some language/message fixes -- v1.3.1.19 - fix another Exception in the time goal -- v1.3.1.18 - properly output unclaiming vs contesting flags in domination goal - language file consistency fixed -- v1.3.1.17 - fix some language derps and move the delayed class change to where it makes more sense -- v1.3.1.16 - fix github issue #108 - contesting (unclaiming) too late -- v1.3.1.15 - add github issue #100 - player.healforkill - true/false :) -- v1.3.1.14 - use the SNAPSHOT distinction and address github issue #85 -- v1.3.1.13 - hide the not-really stat type NULL (player name) -- v1.3.1.12 - fix github issue #95 by adding a null check -- v1.3.1.11 - clarify language for RespawnRelay and fix a little Exception in the Time goal -- v1.3.1.10 - address github issue #88 - properly keep players as DEAD when being relayed -- v1.3.1.9 - address github issue #87 - add THORNS damage handling -- v1.3.1.8 - properly deal with inventory protection -- v1.3.1.7 - how about we don't spam EVERYthing but spam after collecting everything, and inform people that we have prevented something? -- v1.3.1.6 - fix some mathematical and logical derps -- v1.3.1.5 - really add INVENTORY check - properly define new Infect commands [setprotect|getprotect] -- v1.3.1.4 - allow goals to deny BREAK, PLACE, TNT, TNTBREAK, DROP, INVENTORY, PICKUP, CRAFT - proof of concept! -- v1.3.1.1 - link to new jenkins. Thanks to @graywolf336 -- v1.3.0.558 - fix github issue #83 -- v1.3.0.557 - fix github issue #61 -- v1.3.0.556 - fix github issue #64 -- v1.3.0.555 - add x-offset and z-offset, so one can change the default behaviour of putting ppl on the middle of a block -- v1.3.0.554 - fix an NPE in some places due to a return value of null should be expected! -- v1.3.0.553 - add chat.toGlobal to allow private talking players to talk to the public with a prefix -- v1.3.0.552 - add CRAFT RegionProtection to prevent item crafting -- v1.3.0.551 - add damage.fromOutsiders (false) to allow players (and other entities) to hurt fighters -- v1.3.0.550 - properly check for some things before adding players to a class via command -- v1.3.0.549 - try to fix long usernames staying on signs -- v1.3.0.548 - prevent a NPE -- v1.3.0.547 - call the leave event - I am shocked noone noticed that until yesterday -- v1.3.0.546 - reverse all the things and do what I promised the last 2 commits -- v1.3.0.545 - fix books! (for real) -- v1.3.0.544 - fix books! -- v1.3.0.543 - trying again -- v1.3.0.542 - attempt to fix some data reading issues (for ink sacks and wool blocks) -- v1.3.0.541 - fix some display issues about max team players -- v1.3.0.540 - attempt to fix special character issues -- v1.3.0.539 - allow to take suicides into account for TDM -- v1.3.0.538 - still on github issue #78 - never remove perms! -- v1.3.0.537 - fix missing perms message, addressing github issue #78 -- v1.3.0.536 - finish github issue #78 - typo messup -- v1.3.0.535 - address github issue #78 - add language nodes for missing perms -- v1.3.0.534 - prevent tamed animals belonging to an arena player from teleporting -- v1.3.0.533 - finally fix github issue #76 - inventory reset messup -- v1.3.0.532 - address github issue #76 -- v1.3.0.531 - address github issue #64 -- v1.3.0.530 - add "classSwitchAfterRespawn", defaulting to false -- v1.3.0.529 - revert #523 - I don't care anymore - this HAS to fix it, otherwise I give up on development :P -- v1.3.0.528 - revert #519 - second attempt at fixing an issue on several implementations -- v1.3.0.527 - revert #518 - this fixed dbo issue #912 (duplications on Cauldron) but caused items disappearing on other implementations -- v1.3.0.526 - add more config settings for PlayerKillReward -- v1.3.0.525 - address DBO issue #923 -- v1.3.0.524 - address DBO issue #921 -- v1.3.0.522 - fix integer/integer divisions -.- -- v1.3.0.521 - clarify custom class determination debug -- v1.3.0.520 - clarify damage debug values -- v1.3.0.519 - forcefully place players where they joined if the player is disconnecting -- v1.3.0.518 - forcefully remove items when a player leaves the arena -- v1.3.0.517 - address DBO issue #907 - don't try to teleport null/dead players -- v1.3.0.516 - try fixing NOCAMP damage -- v1.3.0.515 - [IDEA] various fixes -- v1.3.0.511 - address DBO issue #888 - reset chat color if desired -- v1.3.0.510 - add mobs fighting by your side. Give classes a spawn egg with displayname "SPAWN" -- v1.3.0.509 - properly build #507 prefix -- v1.3.0.507 - add materialprefixes to the global config, for special Material names (bukkit:SAND) -- v1.3.0.506 - add '*' command for the whitelist to allow all commands -- v1.3.0.505 - add per command permissions - defaulting to old behaviour -- v1.3.0.504 - don't drop inventory if not desired -- v1.3.0.503 - fix the UUID interpretation; use player names for creation, not the UUID -.- -- v1.3.0.502 - how about we actually RUN the runnable? -- v1.3.0.501 - force /pa leave on final player death if no specate module present -- v1.3.0.500 - address ticket #869, #884, #792 - - add time.resetDelay (default: -1 --> off) - delay for resetting players (TP & inventory) - - support single SPAWN regions for team matches - - support lore and displayname for keepItems -- v1.3.0.499 - address ticket 792, 879, 881 - - attempt to fix the Food Goal to properly handle player deaths - - require explicit perms for /pa arenaclass (if desired) -- v1.3.0.498 - properly initiate late joining PlayerDeathMatch players -- v1.3.0.497 - check for explicit class perms, even though we have no Sign! -- v1.3.0.496 - minor fixes -- v1.3.0.495 - add Command Tab support; Big Command rewrite!! \ No newline at end of file diff --git a/doc/history/0.1.md b/doc/history/0.1.md new file mode 100644 index 000000000..b69259dab --- /dev/null +++ b/doc/history/0.1.md @@ -0,0 +1,16 @@ +== PVP-Arena v0.1 Changelog + +* v0.1.13 - place bets on a match +* v0.1.12 - display stats with /pa users | /pa teams +* v0.1.11 - config: woolhead: put colored wool on heads! +* v0.1.10 - config: only start with even teams +* v0.1.9 - teleport location configuration +* v0.1.8 - lives! +* v0.1.7 - commands to show who is playing and on what team +* v0.1.6 - custom class: fight with own items +* v0.1.5 - class choosing not toggling +* v0.1.4 - arena disable via command * disable / * enable +* v0.1.3 - ingame config reload +* v0.1.2 - class permission requirement +* v0.1.1 - ready block configurable +* v0.1.0 - release version \ No newline at end of file diff --git a/doc/history/0.10.md b/doc/history/0.10.md new file mode 100644 index 000000000..b8dbb9dc4 --- /dev/null +++ b/doc/history/0.10.md @@ -0,0 +1,97 @@ +== PVP-Arena v0.10 Changelog + +* v0.10.3.15 - LOGICALLY set the player location before saving the state (for laggy servers) +* v0.10.3.14 - Stop ppl from setting the flags as a SPAWN ... +* v0.10.3.13 - aim to fix CosmoVibe :p +* v0.10.3.12 - allow teleportation into arena regions that are NOT type BATTLE +* v0.10.3.11 - fix Flags. Period. +* v0.10.3.10 - fix BlockDestroy with explosions +* v0.10.3.9 - fix /pa ready +* v0.10.3.8 - add Ticket #227 - player time and auto igniting TNT +* v0.10.3.7 - fix DOM - points lead to winning, not to losing! +* v0.10.3.6 - re-add MODULES_COLORTEAMS_HIDENAME - who removed that?! +* v0.10.3.5 - fix Ticket #197 - readying up mechanism messed up +* v0.10.3.4 - aims to fix Ticket #193 - arena not ending +* v0.10.3.3 - Support TNT in BlockDestroy +* v0.10.3.2 - Several fixes +* v0.10.3.1 - StartRunnable now is on the main... thank you, TagAPI :p +* v0.10.3.0 - violations! +* v0.10.2.36 - ouch ... quick command fix! +* v0.10.2.35 - formatting ? +* v0.10.2.34 - correctly reset Domination and BlockDestroy on start +* v0.10.2.33 - stop people from destroying their own block in BlockDestroy ^^ +* v0.10.2.32 - add a special class being assigned when being the tank: %tank% +* v0.10.2.31 - No more restarts! Modules shall NOT rely on server restarts! - No more restarts! Modules shall NOT rely on server restarts! +* v0.10.2.30 - WorldEdit module announcements +* v0.10.2.29 - fix the arena end timer +* v0.10.2.28 - stop kicking everyone on start !!! +* v0.10.2.27 - add a debug line that might change everything +* v0.10.2.25 - properly fix players dying. Take that, logic!! +* v0.10.2.24 - try to hackfix the hackfix +* v0.10.2.23 - critical fix. WHO REMOVED THAT!!?? +* v0.10.2.22 - fix player death handling +* v0.10.2.21 - add goal: BlockDestroy +* v0.10.2.20 - add goal: PhysicalFlags +* v0.10.2.19 - Pull #4 - Don't return false! +* v0.10.2.18 - some small fixes +* v0.10.2.17 - ignore ready blocks unless not ready +* v0.10.2.16 - BetterFight: explosions on death ^^ +* v0.10.2.15 - add region flag NODAMAGE - yay! +* v0.10.2.14 - add "winner" config in case of timeout! +* v0.10.2.13 - add configurable GAMEMODE :) +* v0.10.2.12 - stop ignoring players being removed! +* v0.10.2.11 - fix AutoVote infinity :D +* v0.10.2.10 - /pa class display error, more debug +* v0.10.2.9 - RelayRunnable implementation +* v0.10.2.8 - rewrite respawn handling +* v0.10.2.7 - add TOUCHDOWN gamemode to Flags +* v0.10.2.6 - add configurable PlayerKillRewards +* v0.10.2.5 - add Goal "PlayerKillRewards" and fix NPE +* v0.10.2.4 - fix book saving and loading +* v0.10.2.3 - add lore saving and loading +* v0.10.2.2 - cancel region selection by redoing /pa [arena] region +* v0.10.2.1 - add configurable POTION EFFECT to flag carriers +* v0.10.2.0 - Debugger rewrite +* v0.10.1.21 - add LOUNGE region type functionality (kick ;) ) +* v0.10.1.20 - allow FFA players to win and lose via region :p +* v0.10.1.19 - I) fix arenas with flags being derpy II) secret. DONT use! +* v0.10.1.18 - attempt to save more than casual items. don't try this at home! - yet +* v0.10.1.17 - save armor when saving a class +* v0.10.1.16 - added default confirmation for /pa [arena] remove +* v0.10.1.15 - add "not enough EXP to choose class" (BetterClasses) +* v0.10.1.14 - addresses Ticket #119 +* v0.10.1.13 - add a configurable timer to start without PVP +* v0.10.1.12 - re-add timer scheduling (WIN,LOSE,DEATH regions) +* v0.10.1.11 - fix Sabotage +* v0.10.1.10 - fix Sabotage Spawn parsing +* v0.10.1.9 - fix Player death parsing +* v0.10.1.8 - fix ArenaRunnable setup +* v0.10.1.7 - fix first smart spawn -.- +* v0.10.1.6 - fix death announcements, clean up death handling +* v0.10.1.5 - finally fix the WarmupJoin module +* v0.10.1.4 - fix NPE about sign joining +* v0.10.1.3 - add /pa [arena] team! +* v0.10.1.2 - remove unused config nodes +* v0.10.1.1 - fix FFA respawning (locations) +* v0.10.1.0 - CraftBukkit 1.4.6 +* v0.10.0.21 - once and for all, fix deathmatches! +* v0.10.0.20 - this should work. fixed DeathMatch respawns! +* v0.10.0.19 - hopefully fix DeathMatch respawns :) +* v0.10.0.18 - fix NPE in DeathMatch :) +* v0.10.0.17 - allow re-joining for Lives and all DeathMatch modules +* v0.10.0.16 - properly check for BATTLE regions instead for "battlefield" +* v0.10.0.15 - fix smart spawning not being implemented in a smart way +* v0.10.0.14 - add debug for a strange bug when teleporting people +* v0.10.0.13 - stop telling people they are already part of arenas! +* v0.10.0.12 - reset fall distance to not kill people twice ;) +* v0.10.0.11 - fix BetterGears +* v0.10.0.10 - fix updating via /pa update mods | /pa update goals +* v0.10.0.9 - version bump for DBO +* v0.10.0.8 - wow, what a fail. sorry guys, updater fixed :D +* v0.10.0.7 - re-add automatic plugin update !! +* v0.10.0.6 - EndRunnable now is Sync - thanks, TagAPI :p +* v0.10.0.5 - activate lounge, spectator and internals by default +* v0.10.0.4 - fix the blacklist/whitelist removal message +* v0.10.0.3 - allow re-joining, if ppl know what they're doing +* v0.10.0.2 - avoid NPE in Time Goal +* v0.10.0.1 - module system rewrite \ No newline at end of file diff --git a/doc/history/0.2.md b/doc/history/0.2.md new file mode 100644 index 000000000..c71c35517 --- /dev/null +++ b/doc/history/0.2.md @@ -0,0 +1,4 @@ +== PVP-Arena v0.2 Changelog + +* v0.2.1 - cleanup, comments, iConomy 6 support +* v0.2.0 - language support \ No newline at end of file diff --git a/doc/history/0.3.md b/doc/history/0.3.md new file mode 100644 index 000000000..f1b40514f --- /dev/null +++ b/doc/history/0.3.md @@ -0,0 +1,17 @@ +== PVP-Arena v0.3 Changelog + +* v0.3.14 - timed arena modes +* v0.3.13 - Telepass via Permission +* v0.3.12 - set flag positions +* v0.3.11 - set regions for lounges, spectator, exit +* v0.3.10 - CraftBukkit #1337 config version, rewrite +* v0.3.9 - Permissions, rewrite +* v0.3.8 - BOSEconomy, rewrite +* v0.3.7 - Bugfixes, Cleanup +* v0.3.6 - CTF Arena +* v0.3.5 - Powerups!! +* v0.3.4 - Rewrite +* v0.3.3 - Random spawns possible for every arena +* v0.3.2 - Classes now can store up to 6 players +* v0.3.1 - New Arena! FreeFight +* v0.3.0 - Multiple Arenas \ No newline at end of file diff --git a/doc/history/0.4.md b/doc/history/0.4.md new file mode 100644 index 000000000..3d177b4fe --- /dev/null +++ b/doc/history/0.4.md @@ -0,0 +1,7 @@ +== PVP-Arena v0.4 Changelog + +* v0.4.4 - Random spawns per team, not shared +* v0.4.3 - max / min bet +* v0.4.2 - command blacklist +* v0.4.1 - command manager, arena information and arena config check +* v0.4.0 - mayor rewrite, improved help \ No newline at end of file diff --git a/doc/history/0.5.md b/doc/history/0.5.md new file mode 100644 index 000000000..67a6b8bf2 --- /dev/null +++ b/doc/history/0.5.md @@ -0,0 +1,13 @@ +== PVP-Arena v0.5 Changelog + +* v0.5.11 - CTF flag bug, command error msg improvement +* v0.5.10 - fight temp perms, custom class drops, spectate fix +* v0.5.9 - max players, max team pleayers +* v0.5.8 - private arenas, item reward fix +* v0.5.7 - bugfixes, spawn remove command, enable/disable save +* v0.5.6 - ready handling fix, min team size +* v0.5.5 - blacklist, update check +* v0.5.4 - Capture the Pumpkin arena! +* v0.5.3 - Backend rewrite, +* v0.5.2 - Bugfixes, configurable player start values +* v0.5.1 - rewrite, temporary sign bug fix \ No newline at end of file diff --git a/doc/history/0.6.md b/doc/history/0.6.md new file mode 100644 index 000000000..fbfdc935c --- /dev/null +++ b/doc/history/0.6.md @@ -0,0 +1,83 @@ +== PVP-Arena v0.6 Changelog + +* v0.6.41.1 - fix the Potion Type NPE +* v0.6.41.0 - possibility to customize the Arena prefix +* v0.6.40.26 - fix NPE when not selecting a region before trying to save the selection +* v0.6.40.25 - fix inventory protection +* v0.6.40.24 - fix region protection issues +* v0.6.40.20 - fix dead players still wearing their armor +* v0.6.40.19 - set debug ingame /pa debug [value] +* v0.6.40.18 - recognize players running outside of the arena +* v0.6.40.17 - fix woolhead removal for flag arenas +* v0.6.40.16 - fix ready block hit while countdown teleporting ppl inside the arena. Bad, bad players! +* v0.6.40.15 - hackfix Potion Effects not vanishing. Bad, bad API! +* v0.6.40.14 - fix resetting of player stats -.- +* v0.6.40.13 - fix abusing the spectator state +* v0.6.40.11 - fix a random NPE; fix WoolHead enforcement +* v0.6.40.10 - fix powerup type REPAIR and a NPE in flag arenas +* v0.6.40.9 - fix another issue with the startup countdown +* v0.6.40.8 - Backend organising by NodinChan, has NO effect on the plugin atm +* v0.6.40.7 - Fix NPE and fix LeaderBoards +* v0.6.40.6 - Tries to fix mcMMO damage messing up the arena ;) +* v0.6.40 - Multiple flags for CTF +* v0.6.39 - Enchantments +* v0.6.38 - Arena chat +* v0.6.37 - Item reward random +* v0.6.36.11 - fix a bug where players were able to start alone / with just one team +* v0.6.36.8 - fix various bugs +* v0.6.36.4 - add a proper arena start message ; add a PAKillEvent +* v0.6.36.3 - fix bet placing NPE +* v0.6.36.2 - add Vault support +* v0.6.36 - fix for every arena start bug caused by leaving / quitting players +* v0.6.35.3 - taught talking to DOM arena +* v0.6.35.2 - fix the CTF issues +* v0.6.35 - fix the death issues, finally +* v0.6.29.9 - fix the fire bug, finally +* v0.6.29.8 - create custom events properly +* v0.6.29.7 - reset team flags on arena startup to be colored +* v0.6.29.6 - fixed CTF NPE +* v0.6.29.5 - added config setting protection.restore to stop block restoring +* v0.6.29.4 - added teleport ignoring INSIDE the battlefield +* v0.6.29.3 - fixed countdown join bug, for real :D +* v0.6.29.2 - fixed sign restoring bug +* v0.6.29.1 - fixed inventory hack bug +* v0.6.29 - join teams with sign. Line 2: teamname +* v0.6.28.6 - cancel 5s countdown if player joins +* v0.6.28.5 - spawn camping just for battlefield & fighting players +* v0.6.28.4 - add config: protection.punish (default false) +* v0.6.28.3 - fix 2 NPEs happening when spawn camping or using /pa leave +* v0.6.28.2 - fix a very bad bug occurring after fixing an NPE +* v0.6.28.1 - fix various NPEs +* v0.6.28 - potion effects for PowerUps +* v0.6.27 - join range possible without set region +* v0.6.26.2 - fixed NPE +* v0.6.26.1 - added proper join event calling +* v0.6.26 - add custom events for other plugins to listen to +* v0.6.25 - get stats with /pa {name} stats [stattype] +* v0.6.24 - sort arena board by click +* v0.6.23 - config "hideName": remove names over head +* v0.6.22 - punish spawn camping +* v0.6.21 - [PUMPKIN|CTF|DOM] join arenas ingame +* v0.6.20 - arena start runnable (5s, if readycount > x%), interrupted by player join +* v0.6.19 - fixed players joining from vehicles +* v0.6.18 - added entry fee "pay" message +* v0.6.17 - force joining from a special region, if one arena has set "join" region +* v0.6.16 - "explicitPermission" to enable need of "pvparena.join.[arenaname]" +* v0.6.15 - new debug system +* v0.6.14 - main config: onlyPVPinArena -> cancel all damage except arena! +* v0.6.13.2 - quitting ingame does not break anything +* v0.6.13.1 - fixed block destruction being possible +* v0.6.13 - EDIT mode /pa {name} edit +* v0.6.12 - "[player] killed" + " by [player/cause]" +* v0.6.11 - config: betWinFactor [2], betTeamWinFactor [1], betPlayerWinFactor [2] +* v0.6.10 - config: allowDrops [true] +* v0.6.9 - config: flagColors: set flag (head) colors +* v0.6.8 - config: woolFlagHead: change/set woolhead on flag grabbing +* v0.6.7 - config: autoclass: [classname] +* v0.6.6 - team chat: add player name +* v0.6.5 - [Spout] wool lock (inv change cancel) +* v0.6.4 - [Spout] color name over head +* v0.6.3 - game mode: death match, spheric regions, block repair, powerup spawn +* v0.6.2 - leaderboards RELOADED, spawn protection, flag coloring/whitening, inv drops +* v0.6.1 - sign update/check, announcements, death!, arena end timer +* v0.6.0 - huge rewrite \ No newline at end of file diff --git a/doc/history/0.7.md b/doc/history/0.7.md new file mode 100644 index 000000000..3a1e1ae41 --- /dev/null +++ b/doc/history/0.7.md @@ -0,0 +1,90 @@ +== PVP-Arena v0.7 Changelog + +* v0.7.25.2 - cancel woolhead removal when needed +* v0.7.25.1 - properly handle piston event protection +* v0.7.25.0 - rewrite of /pa {arenaname} info +* v0.7.24.0 - attempt to improve the statistics usage +* v0.7.23.4 - fixed the woolhead removal - again +* v0.7.23.3 - fix an issue with death events +* v0.7.23.2 - fix late joining +* v0.7.23.1 - fix freefight type issues, fix classitems messing causing NPEs +* v0.7.23.0 - /pa [name] alive - list alive players +* v0.7.22.2 - fix PotionEffects not being removed properly +* v0.7.22.1 - more intelligent and extroverted help system +* v0.7.22.0 - add readying of all teams with checkEachTeam: false +* v0.7.21.0 - fix many issues inside modules +* v0.7.20.13 - fix an NPE on non pvp death +* v0.7.20.12 - add cylindric arena region shape +* v0.7.20.11 - fix custom class not working +* v0.7.20.10 - fix the end timer not deactivating PVP for losers +* v0.7.20.8 - fix issues.... +* v0.7.20.7 - fix stuff and update for tank arena mode +* v0.7.20.6 - fix alot of permissions issues oO +* v0.7.20.5 - fix the wool head not being correctly secured +* v0.7.20.4 - fix the ready up bug +* v0.7.20.3 - fix various bugs +* v0.7.20.2 - fix various bugs +* v0.7.20.1 - fix teams/ctf/pumpkin lounge setting not working +* v0.7.20.0 - feature freeze, future updates will just add/update modules or fix bugs +* v0.7.19.5 - fix messy code about random spawns +* v0.7.19.4 - fix teams/ctf/pumpkin spawn setting not working +* v0.7.19.3 - fix region NPE +* v0.7.19.2 - fix missing messages +* v0.7.19.1 - fix multiple enchantments +* v0.7.19.0 - command handling rewrite +* v0.7.18.0 - region modules +* v0.7.17.4 - fix chest restoring +* v0.7.17.3 - make the countdown timer configurable +* v0.7.17.2 - fix arenaboards displaying the global stats for players during a match +* v0.7.17.1 - fix fluids and block burning not being cancellable/replaced properly +* v0.7.17.0 - (more) correctly calculate armor in order to detect death +* v0.7.16.1 - fix when teleporting players +* v0.7.16.0 - more colors! +* v0.7.15.0 - /pa readylist - to see people not being flagged as ready +* v0.7.14.1 - add a delay to teleporting, making the player teleporting thread safe +* v0.7.14.0 - teleport to spawns with /pa tp [spawnname] +* v0.7.13.1 - FIRST restore blocks, then restore inventories! +* v0.7.13.0 - add config setting to force warming up on /pa join | /pa spectate +* v0.7.12.1 - fix /pa [name] remove [spawnname] +* v0.7.12.0 - multiple Enchantments +* v0.7.11.3 - add a different tracker +* v0.7.11.2 - fix the player handling / inventory issue +* v0.7.10.6 - fix the Loader +* v0.7.10.5 - fix watching players not belonging to the arena +* v0.7.10.4 - fix restoring of the team nameplate +* v0.7.10.3 - fix timed (team) arenas giving no rewards +* v0.7.10.2 - fix timed arenas totally f up +* v0.7.10.1 - fix CraftBukkitUpToDate compatibility +* v0.7.10.0 - add restoring of dispensers and furnaces +* v0.7.9.22 - change game.allowDrops priority. Custom class not needed! +* v0.7.9.21 - fix module loading +* v0.7.9.20 - fix modules not containing version +* v0.7.9.19 - fix player recognition -.- +* v0.7.9.18 - fix spheric regions not being saved properly +* v0.7.9.17 - fix all arena type ready methods +* v0.7.9.16 - fix CTF/Pumpkin interact cancelling +* v0.7.9.15 - hook inv shift click to protection.inventory +* v0.7.9.14 - fix ColorTeams +* v0.7.9.13 - fix CTF/Pumpkin arena returning "Flag set:" on many occasions ^^ +* v0.7.9.12 - fix mobs messing up the game. bad, bad mobs! +* v0.7.9.11 - fix an NPE with activated quit check +* v0.7.9.10 - fix ArenaBoards not working if spectators are present +* v0.7.9.9 - fix many issues with invisible armor, players etc by disabling the team coloring function +* v0.7.9.8 - fix team chat doubling +* v0.7.9.7 - add customisable end timer, add damage cancelling +* v0.7.9.6 - fix an NPE with /pa bet [player] +* v0.7.9.5 - fix an NPE possible on arena end +* v0.7.9.4 - fix more beta bugs +* v0.7.9.2 - fix various bugs +* v0.7.9 - rewrite concerning ArenaPlayer / Players +* v0.7.8 - ArenaModule: Announcements +* v0.7.7 - ArenaModule: TempPerms +* v0.7.6 - ArenaModule: PowerUps +* v0.7.5 - ArenaModule: VaultSupport +* v0.7.4 - ArenaModule: Economy +* v0.7.3 - ArenaModule: BlockRestore +* v0.7.2 - ArenaModule: ColorTeams +* v0.7.1 - ArenaModule: ArenaBoards +* v0.7.0.3 - Kick leads to arena leave +* v0.7.0.2 - Chest restoring +* v0.7 - another huge rewrite, modules that provide Arena Types \ No newline at end of file diff --git a/doc/history/0.8.md b/doc/history/0.8.md new file mode 100644 index 000000000..0e8d54b26 --- /dev/null +++ b/doc/history/0.8.md @@ -0,0 +1,92 @@ +== PVP-Arena v0.8 Changelog + +* v0.8.12.3 - trimmed some unneeded methods +* v0.8.12.2 - offline updating +* v0.8.12.1 - fix several NPEs +* v0.8.12.0 - fix disconnect exploit +* v0.8.11.28 - maybe fix the chatting the correct way ^^ +* v0.8.11.27 - fix 1.3.1 spamming about PlayerChatEvent. real fix incoming +* v0.8.11.26 - fix class saving +* v0.8.11.25 - fix regions being one block too short on each side +* v0.8.11.24 - fix non-fighters inside an arena being damaged. +* v0.8.11.23 - fix the loser's inventory disappearing issue +* v0.8.11.22 - fix general protection issues (greedy protection) +* v0.8.11.21 - fix joining teams with signs +* v0.8.11.20 - fix /pa [] class +* v0.8.11.19 - fix some spawn settings not working +* v0.8.11.18 - fix battlefield/arena end/win/lose issues +* v0.8.11.17 - add ingame class preview / edit / saving / removing +* v0.8.11.16 - also restrict blockplace on block whitelist/blacklist +* v0.8.11.15 - attempt to fix losers being counted as winners, adding PALoseEvent on the way +* v0.8.11.14 - fix several issues about players logically hurting themselves (ender pearls etc) +* v0.8.11.13 - prevent teleporting INTO an arena +* v0.8.11.12 - fix arena join messages +* v0.8.11.11 - unknown +* v0.8.11.10 - fix multiple join regions need you to be in all join regions oO +* v0.8.11.9 - fix losing making you leave the match +* v0.8.11.8 - fix deaths and kills not being registered +* v0.8.11.7 - fix players being kicked from arena +* v0.8.11.6 - add proper CUSTOM announcement implementation +* v0.8.11.5 - zip NPE bug? +* v0.8.11.4 - fix spectator check +* v0.8.11.3 - fix other issues +* v0.8.11.2 - fix a player death NPE +* v0.8.11.1 - fix StartRunnable issues +* v0.8.11.0 - add PAWinEvent +* v0.8.10.14 - revert inventory handling +* v0.8.10.13 - change and fix update check +* v0.8.10.12 - allow module update deactivation +* v0.8.10.11 - properly reset inventories! +* v0.8.10.10 - reset Potion Effects on respawn +* v0.8.10.9 - add MultiInv compatibility +* v0.8.10.8 - fix NPE about resetPlayer +* v0.8.10.7 - add config setting to change default command +* v0.8.10.6 - fix custom classes inventory handling +* v0.8.10.5 - re-activate the escape check +* v0.8.10.4 - fix inventory being removed for custom classes at the end... +* v0.8.10.3 - properly ignore alpha and beta builds from update nag +* v0.8.10.2 - fix WIN and LOSE region not triggering timers +* v0.8.10.1 - fix spawn setting not working for some modules +* v0.8.10.0 - add WIN and LOSE regions +* v0.8.9.0 - finish region protection +* v0.8.8.9 - fix Projectile Exception (Ticket 338) +* v0.8.8.8 - fix the region selection spam +* v0.8.8.7 - add message coloring +* v0.8.8.6 - fix synchronisation issues +* v0.8.8.5 - fix "youescaped" bug +* v0.8.8.4 - fix NPE in statistics handling +* v0.8.8.3 - fix /pa update [type] +* v0.8.8.2 - fix /pa uninstall * +* v0.8.8.1 - block break NPE +* v0.8.8.0 - timer rewrite to fix many issues +* v0.8.7.2 - fix minor display bug +* v0.8.7.1 - fix NPE when players disconnect while being told something +* v0.8.7.0 - add /pa update, /pa install and /pa uninstall +* v0.8.6.20 - fix TimerInfo visibility +* v0.8.6.19 - support arena name guessing +* v0.8.6.18 - enhance /pa version flexibility +* v0.8.6.17 - give proper error when using unsupported region types +* v0.8.6.16 - fixed other regions not being initialized properly +* v0.8.6.15 - fixed cubic regions not being initialized properly +* v0.8.6.14 - fixed /pa reload messing up when an arena was running +* v0.8.6.13 - better information about missing game modes +* v0.8.6.12 - add proper error for old pa create command +* v0.8.6.11 - distinguish tnt block damage from player block damage +* v0.8.6.10 - remove mobs and animals on region reset +* v0.8.6.9 - fix spawn access (players taking the enemy flag at other positions) +* v0.8.4.8 - add hook parseRespawn to Modules +* v0.8.4.7 - fix woolHead support +* v0.8.4.6 - teach the countdowns to talk! (continued) +* v0.8.4.5 - fix the player not being reset properly after a fight +* v0.8.4.4 - teach the countdowns to talk! +* v0.8.4.3 - add hook to add required spawns via modules +* v0.8.4.2 - revert hook for sabotage arena, fix Player velocity on respawn +* v0.8.4.1 - add hook for sabotage arena, ArenaType.onEntityExplode +* v0.8.4.0 - read default classes from config.yml, if set +* v0.8.3.0 - add blacklist/whitelist for block breaking +* v0.8.2.3 - fix droppings inside the spectator area +* v0.8.2.2 - only track plugin if used (if arenas defined) +* v0.8.2.1 - add arena wide command whitelist +* v0.8.2.0 - rewrite in order to fix the player teleporting / ghosting issue +* v0.8.1.0 - major fix - more to come, but this is a severe bug fix +* v0.8.0.0 - major rewrite of player death handling, fixes many things \ No newline at end of file diff --git a/doc/history/0.9.md b/doc/history/0.9.md new file mode 100644 index 000000000..57b7068e1 --- /dev/null +++ b/doc/history/0.9.md @@ -0,0 +1,203 @@ +== PVP-Arena v0.9 Changelog + +* v0.9.9.18 - /pa [arena] region [regionname] border - YAY! +* v0.9.9.17 - don't spawn players on flags. derp :p +* v0.9.9.16 - activate region force join - hooray! +* v0.9.9.15 - enhance the battlefield quit process: add "death" instead of kick +* v0.9.9.14 - add SPAWN regions that >enforce< random spawning +* v0.9.9.13 - broadcast when a player / team is ready +* v0.9.9.12 - allow data values for blacklist and whitelist +* v0.9.9.11 - SET - stop being so damn PICKY about cases! +* v0.9.9.10 - regions are now safe when the arena is off/disabled :p +* v0.9.9.9 - add /pa togglemodule/!tm [module] !!! +* v0.9.9.8 - add running commands in ALL arenas /pa ALL [...] +* v0.9.9.7 - fix node collision: battlefieldguard=> BFGACTIVE +* v0.9.9.6 - fix spectating cause an NPE +* v0.9.9.5 - fix internal modules vanishing on reload +* v0.9.9.4 - fix CLASS help +* v0.9.9.3 - add module hooks to BattlefieldJoin start +* v0.9.9.2 - add BetterGears - COLORED DYES +* v0.9.9.1 - fix the place/break whitelist / blacklist ! +* v0.9.9.0 - fix /pa install | uninstall | update +* v0.9.8.25 - support TEAM based PlayerLives goal !! +* v0.9.8.24 - support TANK gamemode - welcome back !! +* v0.9.8.23 - activate MOBS protection, and teach Listeners some RESPECT +* v0.9.8.22 - rewrite spawning (FREE) - new config settings! +* v0.9.8.21 - split the announcing of "join the arena!" (ADVERT) and "let the fight begin" (START) +* v0.9.8.20 - make sure PA loads after SKINS dependencies +* v0.9.8.19 - re-introduce arena.getWorld() +* v0.9.8.18 - update Skins language +* v0.9.8.17 - allow setting classes to have empty inventory +* v0.9.8.16 - update importer (weapondamage), remove unnecessary WORLD node from config! +* v0.9.8.15 - fix an ConcurrentModificationException about region restoring +* v0.9.8.14 - fix #97 - Other -- Additional grammar issues - ITERVAL !!!!! +* v0.9.8.13 - add /pa [arena] start +* v0.9.8.12 - add proper functionality to /pa [arena] spectate +* v0.9.8.11 - finally implement the SOFT version of a player leave - FIX ppl spectating after death +* v0.9.8.10 - fix the ArenaRunnable implementation ("XXX has not been scheduled yet") +* v0.9.8.9 - restructure the player removal to allow proper removement by modules +* v0.9.8.8 - add #96 - Feature Request - Ability to disable armor durability +* v0.9.8.7 - properly update the config if nodes are missing +* v0.9.8.6 - add #92 - Feature Request - List number of players per team +* v0.9.8.5 - fix #85 - Other - Grammar fix for capturing a flag? +* v0.9.8.4 - support WorldEdit auto loading and saving of BATTLE regions +* v0.9.8.3 - add module hooking into class selection +* v0.9.8.2 - add config node and langage for BetterClasses +* v0.9.8.1 - re-add module arena start handling +* v0.9.8.0 - rewrite the arena start. use with caution! +* v0.9.7.14 - fix part of #101 - free team can be colored other than WHITE +* v0.9.7.13 - fix #103 - Bug - FFA games not ending! +* v0.9.7.12 - fix #98 - Bug - Fire continuation after leaving/death +* v0.9.7.11 - remove debug +* v0.9.7.10 - quick fix for players not being properly set to fighting state +* v0.9.7.9 - more output and less team resetting +* v0.9.7.8 - properly update the gamemode when it is being set +* v0.9.7.7 - never code when your brain is infected! +* v0.9.7.6 - fix fixes causing broken commands +* v0.9.7.5 - fix #84 - Bug - Disconnecting with flag does not reset flag +* v0.9.7.4 - add missing classes +* v0.9.7.3 - fix #90 - Bug - Class signs with player names not working properly. +* v0.9.7.2 - fix #89 - Bug - Unable to join arena on a specific team +* v0.9.7.1 - fix Sabotage spawning a second destructive TNT +* v0.9.7.0 - welcome back, Sabotage! +* v0.9.6.30 - remove calling of the unused ArenaGoal.commitJoin method +* v0.9.6.29 - add soft depends to fix loading issues +* v0.9.6.28 - place every flag block on the player's head for now +* v0.9.6.27 - prevent removing your head gear when carrying a flag +* v0.9.6.26 - attempt to fix disconnecting players not resetting carried flags +* v0.9.6.25 - reset WoolHeads even if inventories should not be reset +* v0.9.6.24 - fix regions activating all protections on server start +* v0.9.6.23 - fix players being able to re-join a match +* v0.9.6.20 - fix regions being messed on restarting +* v0.9.6.19 - more debug +* v0.9.6.18 - Items +* v0.9.6.17 - aiming to fix the player drops being dropped at the respawn position instead of the death position +* v0.9.6.16 - fix non-pvp deaths messing up the Flags goal +* v0.9.6.15 - fix .10 +* v0.9.6.14 - fix the FFA game mode team count logic +* v0.9.6.13 - globally activate head gear removal prevention +* v0.9.6.12 - fix saved players not being physically reset +* v0.9.6.11 - quick debug NPE fix +* v0.9.6.10 - re-enable Debug override +* v0.9.6.9 - fix inventory loss because of disconnect and server crash, finally +* v0.9.6.8 - there are more signs! +* v0.9.6.7 - allow readying up and using signs in the lounge +* v0.9.6.6 - add a bit more of debug +* v0.9.6.5 - fix an NPE in the InventoryRefillRunnable +* v0.9.6.4 - fix issue #81 +* v0.9.6.3 - fix the last commit which in fact broke more than it should fix +* v0.9.6.2 - fix refillInventory +* v0.9.6.1 - fix the Location->Block calculation +* v0.9.6.0 - add /pa import [arenaname] - v0.8 import! +* v0.9.5.21 - fix TeamDeathMatch kill announcement #2 +* v0.9.5.20 - fix TeamDeathMatch kill announcement +* v0.9.5.19 - add default spawn "exit" to possible spawns +* v0.9.5.18 - reactivate /pa reload +* v0.9.5.17 - enhance and finish the help system +* v0.9.5.16 - fix issue #72.1 | block offset in negative X/Z ranges - fix issue #72.1 | block offset in negative X/Z ranges +* v0.9.5.15 - fix issue #71 +* v0.9.5.14 - hotfix +* v0.9.5.13 - finish .11 +* v0.9.5.12 - fix players being said to be in an arena when they aren't +* v0.9.5.11 - fix players being able to mess up the lounge / spectator / battlefield before starting +* v0.9.5.10 - attempt to fix the player status error with BattlefieldJoin (no lounges) +* v0.9.5.9 - last player(s) teleport bug +* v0.9.5.8 - fix wrong player death handling at the end of the arena +* v0.9.5.7 - enhancing help messages to reflect shorthand commands +* v0.9.5.6 - update all modules. This is information and order :p +* v0.9.5.5 - integrate NodinChan's loader, the update is just. f. +* v0.9.5.4 - fix StandardLounge + FreeForAll +* v0.9.5.3 - fix Runnables being cancelled when not being running +* v0.9.5.2 - fix tracker / stats deactivation derpyness +* v0.9.5.1 - fix player reset (first restore, then teleport) +* v0.9.5.0 - add /pa round +* v0.9.4.1 - add /pa stats +* v0.9.4.0 - add /pa help +* v0.9.3.52 - add language and config for the duel module +* v0.9.3.51 - properly tell a player that an arena is disabled +* v0.9.3.50 - don't ask... +* v0.9.3.48 - fix a blockrestore bug about regions +* v0.9.3.47 - fix joining not cancelling the start countdown, finally +* v0.9.3.46 - reanimate StandardSpectator +* v0.9.3.45 - fix two language issues +* v0.9.3.44 - add some little debug to StartRunnable +* v0.9.3.43 - revert InventoryRefillRunnable to be a simple Runnable +* v0.9.3.42 - correctly display /pa list - depending on game mode, fix player damage on teleport +* v0.9.3.41 - use BukkitRunnables instead of Runnables +* v0.9.3.40 - fix respawning players not being restored under certain circumstances +* v0.9.3.39 - fix the Timers +* v0.9.3.38 - fix #29 - Inventory not being restored on respawn. Hilarious collateral damage! +* v0.9.3.37 - fix the Flag goal not activating spawn setting +* v0.9.3.36 - fix a bug about timers ^^ +* v0.9.3.35 - add a tiny bit more debug +* v0.9.3.34 - aim to fix #57 and #46 +* v0.9.3.33 - fix players DCing / being kicked getting double refund (and other things) +* v0.9.3.32 - fix the next NPE ^^ +* v0.9.3.31 - quick fix for a sleeping NPE +* v0.9.3.30 - possibly resolve #46 - Bug -- Stuck in the floor? +* v0.9.3.29 - try to fix ticket #55 - Bug -- Min/Max player limit not working +* v0.9.3.28 - hopefully fix ticket #58 - NPE while joining when the arena is full +* v0.9.3.27 - fix ticket #59 - Bug -- Champion team is announced numerous times +* v0.9.3.26 - startup error fix +* v0.9.3.25 - fix bug #56 +* v0.9.3.24 - yet another attempt to fix the spawn bug +* v0.9.3.23 - fix tickets #48, #52 +* v0.9.3.22 - a new attempt to fix the spawn bug +* v0.9.3.21 - fix several small things +* v0.9.3.20 - aims to fix the spawn issues +* v0.9.3.19 - fix some more color issues +* v0.9.3.18 - fix bug #41 +* v0.9.3.17 - fix players not always getting told they are ready +* v0.9.3.16 - fix players being able to drop stuff in the lounge ^^ +* v0.9.3.15 - separate edit mode and arena lock state +* v0.9.3.14 - fix the start countdown +* v0.9.3.13 - fix a NPE about player chatting, language tweaks +* v0.9.3.12 - fix playerLeave +* v0.9.3.11 - remove debug StackTrace for ticket #32 +* v0.9.3.10 - fix the SpawnManager choking on block locations +* v0.9.3.9 - fix IllegalStateException for configParse +* v0.9.3.8 - aim to fix ticket #31 +* v0.9.3.7 - fix tickets #25, #32 +* v0.9.3.6 - fix tickets #33, #34, add debug StackTrace for Ticket #32 +* v0.9.3.5 - language fixes +* v0.9.3.4 - and another one. aiming to fix arenas not announcing players leaving the arena +* v0.9.3.3 - for mibby +* v0.9.3.2 - fix /pa reload resetting configs - finally :/ +* v0.9.3.1 - fix an NPE (BlockChange), remove EDIT calling STOP, fix the command whitelist +* v0.9.3.0 - PACheckResult -> rewrite -> PACheck | new check, commit, parse system +* v0.9.2.12 - fix the even check, ticket #28 +* v0.9.2.11 - fix people not being able to ready themselves up in special cases +* v0.9.2.10 - remove debug, fix #19 and #20 +* v0.9.2.9 - fix the startup, affecting VAULT (entryfee), announcements (join message) and more +* v0.9.2.8 - fix several little issues +* v0.9.2.7 - resolve #3, #4, #5, #7, #8, #9, #18 +* v0.9.2.6 - final fix of #2,#11,#15,#16,#17 +* v0.9.2.5 - fix spam of "No arenas found!" +* v0.9.2.4 - fix Issues #2,#11,#15,#16,#17 +* v0.9.2.3 - fix Issue #12,#13 +* v0.9.2.2 - fix a NPE +* v0.9.2.1 - fix a display bug about the Protection command help +* v0.9.2.0 - inventory issue fixed! +* v0.9.1.X - beta test release +* v0.9.0.0 - major organisation rewrite +** <<<<< changes since v0.8.12.5 >>>>> +** use NC-BukkitLib instead of NC-LoaderLib +** the region modules are not "Regions", they are "RegionShapes" ;) +** attach the chatting determination to the player, not to an arena +** remove ArenaType, add ArenaGoal (one type => multiple goals) +** remove lives from the main plugin, attach this logic to the arena goals +** remove positions from the arena, attach to player +** enormous rewrite considering renaming, restructuring, improvements during 1.0 development +** intense command rewrite +** <<<<< updated commits of v0.8.12.5 >>>>> +** allow other-world-spawns +** flatfile inventories for restoring +** [PVP Arena] [arenaname] -> format properly +** arena welcome message per arena +** check what to repair on interact / hit (dont reset every freaking block :p ) +** intelligent and case insensitive arena guessing +** ready up with /pa ready +** splash damage/healing affects teams correctly +** teleport -> 2L -> inv save +** inv restore -> 2L -> teleport +** rewards: "rewards-min-players" \ No newline at end of file diff --git a/doc/history/1.0.md b/doc/history/1.0.md new file mode 100644 index 000000000..c5e1be38e --- /dev/null +++ b/doc/history/1.0.md @@ -0,0 +1,284 @@ +== PVP-Arena v1.0 Changelog + +=== Changelog + +* v1.0.9.292 - maybe support CrackShot and other plugins utilizing "only" projectiles +* v1.0.9.291 - add more goal specific events +* v1.0.9.290 - enhance duel module messaging +* v1.0.9.289 - add regiontypes! BL_INV / WL_INV => blacklist / whitelist inventory +* v1.0.9.288 - make /pa teams properly read the color variables +* v1.0.9.287 - compare changes or fix greedy replacements - derp +* v1.0.9.286 - if we have to care about case, we should do it the right way and constistently +* v1.0.9.285 - fix the install.yml error and add the new curse API updater +* v1.0.9.284 - don't remove a player from the has played list if we need to track them +* v1.0.9.283 - add a Vault setting to only allow betting during the first X seconds +* v1.0.9.281 - add language for chestfiller reset +* v1.0.9.279 - fix BattleFieldJoin putting ppl nowhere before the match started +* v1.0.9.278 - allow to enforce late joining only to initial players "onlyifhasplayed" +* v1.0.9.277 - remove import command. goodbye, v0.8 +* v1.0.9.276 - properly iterate through random spawns +* v1.0.9.275 - actually allow multiple block related goals -.- +* v1.0.9.274 - allow Potions to contain more than one effect - derp +* v1.0.9.271 - make PAJoinEvent and PAStartEvent cancellable +* v1.0.9.270 - add a DBO guideline compliant updater +* v1.0.8.269 - yippie, fixed? +* v1.0.8.268 - revert the replacement of the color code char. gg slipcor +* v1.0.8.267 - hackfix commands to work for players being in the LateLounge queue +* v1.0.8.266 - allow "quickloot" per arena, so players just click a chest to loot +* v1.0.8.265 - silently support BattlefieldManager [/spoiler] +* v1.0.8.264 - minor language format fix +* v1.0.8.263 - don't reset skulls because they receive no damage :P +* v1.0.8.262 - do not drop experience if there is none to drop +* v1.0.8.261 - seriously, bukkit - Y U F up? +* v1.0.8.260 - reset EXP on death (if dropping) +* v1.0.8.259 - drop orbs, because bukkit doesn't want to +* v1.0.8.258 - create pseudo teams before trying to teleport members to it +* v1.0.8.257 - properly implement Bukkit 1.6 API +* v1.0.8.256 - update to MC 1.6 - Bukkit 1.6.2-R0.1 +* v1.0.8.255 - never gonna give you up, #254 +* v1.0.8.254 - fix EXP not properly dropping on some occasions +* v1.0.8.253 - #252 - next try +* v1.0.8.252 - allow late join for PlayerKillReward +* v1.0.8.251 - fix late joining spawns and /pa [arena] teams +* v1.0.8.250 - support class spawns and fix issue #249, revealing that spawning was still broken +* v1.0.7.249 - remove dead code and properly add spawns & blocks when defining them +* v1.0.7.248 - attemt to fix issues #618 and #621 +* v1.0.7.247 - fix spawning, please - (begging works, fyi) +* v1.0.7.246 - add more debug, because everyone loves debugging :) +* v1.0.7.245 - properly check the TNT flag, not the FIRE flag +* v1.0.7.244 - [BREAKING?] - only for dev tests! - SpawnManager rewrite +* v1.0.7.243 - fix ValeraSTK's spawning - break others? no clue +* v1.0.7.242 - spawn debug enhancement (maybe fix) +* v1.0.7.241 - finally fix initial spawning (maybe) +* v1.0.7.240 - enhance the debug for Wahrheit +* v1.0.7.239 - Wahrheit will love this fix! +* v1.0.7.238 - fix an NPE in /pa stats +* v1.0.7.237 - apply default chat parameter +* v1.0.7.236 - allow Wahrheit to use multiple team spawns with PlayerLives +* v1.0.7.235 - allow to require a minimum game length to reward +* v1.0.7.234 - allow to find out how long an arena is running +* v1.0.7.233 - maybe fix the issue by supporting spawn maps? +* v1.0.7.232 - clarify debug for #578 +* v1.0.7.231 - stop punishing players that are left alone. Reward them! +* v1.0.7.230 - re-add announcement config language node +* v1.0.7.229 - try to fix tank spawning +* v1.0.7.228 - add infect death debug - investigating #578 +* v1.0.7.227 - add language node debug - for all the debugs I don't understand :P +* v1.0.7.226 - fix a minor language issue +* v1.0.7.225 - add "customReturnsGear" - allows to play with items but not bringing/taking things +* v1.0.7.224 - prevent death as promised +* v1.0.7.223 - support third party health boosts that vanish after joining +* v1.0.7.222 - maybe fix an issue about autoClass not working on some occasions? +* v1.0.7.221 - properly set the claimed determination map +* v1.0.7.220 - add announce offset and points limitation for DOM +* v1.0.7.219 - properly use wool byte instead of dye byte +* v1.0.7.218 - add autovote autostart - so PA manages ALL THE SERVERS +* v1.0.7.217 - stop breaking servers that didnt want stats in the first place +* v1.0.7.216 - reset stats for admins that /pa reload +* v1.0.7.215 - do not set to an empty path - sry... +* v1.0.7.214 - hell yeah. How about we save the player files? Derp! - thx, Uhehesh +* v1.0.7.213 - stop creating debug files if we don't need them. please... +* v1.0.7.212 - fix startup NPE due to Statistics +* v1.0.7.211 - properly support "none" as an item list +* v1.0.7.210 - for ravand and others: CONFIG: autovote only spams to JOIN regions +* v1.0.6.209 - properly apply #208 and always load the yml! +* v1.0.6.208 - properly load statistics from the player.yml - since when is this broken!? +* v1.0.6.207 - try to fix spawn calculation for the infect goal +* v1.0.6.206 - properly escape & before blindly handing it to the colorize method +* v1.0.6.205 - first check if the arena is running, then check for other errors +* v1.0.6.204 - be prepared for weird multi world setups (a bit better) +* v1.0.6.203 - add proper player name when debugging a player +* v1.0.6.202 - try to fix join edit mode determination - and fix 80% of the lag caused by joining +* v1.0.6.201 - allow to enforce the start countdown +* v1.0.6.200 - allow to restrict autovote to one world, or multiple worlds - allow to restrict autovote to one world, or multiple worlds +* v1.0.6.199 - reduce kill count of deathmatch goals for the DEATH region flag +* v1.0.6.198 - allow taking specific things out of the match +* v1.0.6.197 - add some language nodes for proper error/notice display +* v1.0.6.196 - enhance/clarify debug +* v1.0.6.195 - add the possibility to interact in lounge mode +* v1.0.6.194 - awesome feature: join a game before it has begun +* v1.0.6.193 - everyone loves derpy server implementations +* v1.0.6.192 - add config setting for respawnrelay spawn choosing +* v1.0.6.191 - allow to respawn to a specific spawn +* v1.0.6.190 - update Metrics to revision 7 +* v1.0.6.189 - adjust reward handling for FREE arenas to reflect the recent rewrites +* v1.0.6.188 - add language per arena; add items.excludeFromDrops +* v1.0.5.187 - prepare for a language rewrite, fix all warnings! +* v1.0.5.186 - allow to set config materials by "hand" and items by "inventory" +* v1.0.4.185 - enhance arena list command display +* v1.0.4.184 - add PAPlayerClassChangeEvent +* v1.0.4.183 - try fixing BlockDestroy ending +* v1.0.4.182 - fix NPE +* v1.0.4.181 - craftbukkit is a lie! +* v1.0.4.180 - add a warning if a player has a state when joining (no autoClass then?) +* v1.0.4.179 - properly call PAExitEvent and PALeaveEvent on timed end +* v1.0.4.178 - fix little NPE +* v1.0.4.177 - add a max radius to PlayerFinder +* v1.0.4.176 - try to fix PlayerKillReward +* v1.0.4.175 - properly remove spectators +* v1.0.4.174 - fix #473, #474, #478, #493, #498, #505 +* v1.0.4.173 - allow to debug to server.log, oldschool, if files are not working +* v1.0.4.172 - allow to disallow arena gameplay if player has a scoreboard +* v1.0.3.171 - revert an attempt to fix rewards (leading to double rewards and messed up players) +* v1.0.3.170 - finally allow of force joining players to a team +* v1.0.3.169 - properly start timers. this time for real. +* v1.0.3.168 - little region tick rewrite +* v1.0.3.167 - fix #486 +* v1.0.3.166 - allow disallowing of spectator talk +* v1.0.3.165 - verify that rewards were not already given +* v1.0.3.164 - various fixes +* v1.0.3.163 - properly put BlockDestroy loser to the lose location +* v1.0.3.162 - fix Valera's server. btw: v2.0 is a LIE! +* v1.0.3.161 - update player's inventories. just because we can +* v1.0.3.160 - revert #155; fixed properly in #159 +* v1.0.3.159 - spectators and players in lounge do NOT have lives! +* v1.0.3.158 - revert #156; fix readyup countdown messups +* v1.0.3.157 - only care about arena players teleporting OUT, not FROM OUTSIDE +* v1.0.3.156 - properly initiate spectators +* v1.0.3.155 - properly initiate late joining players +* v1.0.3.154 - hackfix lore - we need v2.0 ! +* v1.0.2.153 - check region ticks on everyone, not just fighters +* v1.0.2.152 - fix custom potions and colored description/lore +* v1.0.2.151 - catch a NPE about deaths +* v1.0.2.150 - properly read item descriptions +* v1.0.2.149 - never stop WATCH region timers. period. +* v1.0.2.148 - properly give rewards when time determines the winners +* v1.0.2.147 - remove arrows from players; this is said to cause crashes +* v1.0.2.146 - properly update plugin files that have been renamed +* v1.0.2.145 - add some more debug to 3 (arena) +* v1.0.2.144 - fix an announcement not happening in special cases +* v1.0.2.143 - add all the helmets! And check before replacing the helmet ;) +* v1.0.2.142 - force ready up people joining late on an arena that counts down to start +* v1.0.2.141 - fix NPE +* v1.0.2.140 - genius developer! Check if too far away before joining. +* v1.0.2.139 - check for worlds before comparing locations +* v1.0.2.138 - fix /pa shutup with arguments! +* v1.0.2.137 - don't spam the winning/losing message for every remaining infect player +* v1.0.2.136 - properly allow players to fly if they ... did Oo +* v1.0.2.135 - fix infected player display, attempt tp properly end the infected mode +* v1.0.2.134 - Only force arena configuration loading if configs were messed up +* v1.0.2.133 - Reload root config and all arena configs, even lost ones! +* v1.0.1.132 - Fix displayname loading +* v1.0.1.131 - STOP removing paintings on arena end. You idiot plugin! +* v1.0.1.130 - add legacy types "infect" and "liberation" +* v1.0.1.129 - add a way of not using plugins in "Skins" module +* v1.0.1.128 - properly set un-infected players' lives +* v1.0.1.127 - properly round decimal calculation +* v1.0.1.126 - support decimals in life display (for pillars) +* v1.0.1.125 - support autoClass definitions per team +* v1.0.1.124 - properly calculate losing players +* v1.0.1.123 - stop giving rewards to matches where more than half of the players win +* v1.0.1.122 - attempt to fix an NPE about colored items +* v1.0.1.121 - attempt to fix TNT ignite determination +* v1.0.1.120 - update blockrestore config to allow block restore disabling +* v1.0.1.119 - don't clear the killrewards map after one match. bad plugin! +* v1.0.1.118 - start join tasks when resetting an arena +* v1.0.1.117 - fix leaf decay determination +* v1.0.1.116 - fix block listener logic +* v1.0.1.115 - fix v#113 to support woolheads +* v1.0.1.114 - prevent exception when spawns are on different worlds +* v1.0.1.113 - properly clear inventory when changing via arenaclass command +* v1.0.1.112 - alter v110 fix to only apply for Snowballs. Fixes #375 +* v1.0.1.111 - properly start JOIN tick before arena start. Fixes #370 +* v1.0.1.110 - allow projectiles to knock back +* v1.0.1.109 - attempt to fix v108 and v102 +* v1.0.1.108 - more precise debugging +* v1.0.1.107 - properly start an arena with BattlefieldJoin and no regions +* v1.0.1.106 - more secret fixes +* v1.0.1.105 - fix getLives method of ArenaGoals +* v1.0.1.104 - more hacking for automation +* v1.0.1.103 - properly deny players joining an arena because of explicit perms missing +* v1.0.1.102 - properly save, fix and revert fly mode +* v1.0.1.101 - make y offset configurable and add nodamage timer on leave +* v1.0.1.100 - add /pa [arena] playerjoin [playername] {team} - join enforcing +* v1.0.1.99 - add API access to player's teams and team names +* v1.0.1.98 - properly print error message when arena is full; #343 +* v1.0.1.97 - properly implement the proper implementation of adding players to the life pool +* v1.0.1.96 - add the "CustomSpawn" module to define custom named spawns +* v1.0.1.95 - attempt to fix statistics madness +* v1.0.1.94 - Support CUSTOM POTIONS - fixes ticket #330 +* v1.0.1.93 - EventActions now is able to activate redstone! +* v1.0.1.92 - properly implement players adding to the life pool +* v1.0.1.91 - fix AIOOB error due to /pa install +* v1.0.1.90 - optimization and TagAPI fix for autovote +* v1.0.1.89 - enhance information about config messups +* v1.0.1.88 - allow giving/taking food for pvp killing +* v1.0.1.87 - add /pa [arena] shutup - disables arena announcements +* v1.0.1.86 - repair tools when breaking blocks +* v1.0.1.85 - pro tip: when altering the Config, save it! +* v1.0.1.84 - properly parse /pa round arguments +* v1.0.1.83 - fix /pa round error message +* v1.0.1.82 - allow modules to hook into tnt explosions in unprotected regions +* v1.0.1.81 - automatically ready ppl that join and select a class when an arena is starting +* v1.0.1.80 - fix BattlefieldJoin (direct joining) +* v1.0.1.79 - fix Infect goal. Strange noone witnessed this :p +* v1.0.1.78 - revert v0.10.0.3 (zOMG), fix re-join arenas messing up +* v1.0.1.77 - default to teamkill = true -> fixes 99% of all issues :p +* v1.0.1.76 - stop respawning players that have lost a TDM match! +* v1.0.1.75 - don't reset the (ready) countdown if player count is ok +* v1.0.1.74 - add Citizens support (don't remove NPCs) +* v1.0.1.73 - fix #295 - display proper help when trying to set spawn wrongly +* v1.0.1.72 - add SpecialJoin setting for player count display +* v1.0.1.71 - add [team]foodfurnace to only allow the team to use THAT furnace +* v1.0.1.70 - fix tank winning message +* v1.0.1.69 - fix /pa class load [classname] - remember: /pa class done ! +* v1.0.1.68 - and, yeah fixed /pa stats ! +* v1.0.1.67 - half-assed fix for arenaboards, so that they at least display SOMETHING +* v1.0.1.66 - fix the TNTBREAK flag, this (finally) prevents block damage +* v1.0.1.65 - support "My Worlds" worlds +* v1.0.1.64 - fix splash potions for free for all arenas +* v1.0.1.63 - repair bows if wanted +* v1.0.1.62 - finish JavaDocs for ArenaGoal and ArenaModule +* v1.0.1.61 - finish /pa info output +* v1.0.1.60 - add Walls MATERIAL and RespawnRelay SECONDS config setting +* v1.0.1.59 - enhance /pa info output +* v1.0.1.58 - update LateLounge to display queue position +* v1.0.1.57 - oups, default to NOT "claimall" for Pillars +* v1.0.1.56 - Add [m]PlayerFinder, [m]Walls, enhance Pillars +* v1.0.1.55 - Add GOAL: Food! +* v1.0.1.54 - save regions on region update. This should prevent WorldEdit messups when resizing. +* v1.0.1.53 - fix StringParser, bug about LORE affected player dumps and classes +* v1.0.1.52 - fix #271 - properly handle mis-set wand settings instead of spamming +* v1.0.1.51 - fix and improve arena creation, add proper message if no goal active +* v1.0.1.50 - allow colored prefixes, fix BlockDestroy destruction detection +* v1.0.1.49 - fix what NodinChan promised: You dun goofed! +* v1.0.1.48 - improve handling of admins sticking files into wrong folders +* v1.0.1.47 - fix #2 and #4 of Ticket #262 +* v1.0.1.46 - try fixing Ticket #209, correctly remove player from arena +* v1.0.1.45 - add LIBERATION! [ WIP! ] +* v1.0.1.44 - add INFECT! +* v1.0.1.43 - add class spawns! +* v1.0.1.42 - properly add a draw for team games +* v1.0.1.41 - revert former "fixes" + stop resetting configs! +* v1.0.1.40 - finally fix the timed end bug! +* v1.0.1.39 - attempt #3 to fix the timed end +* v1.0.1.38 - attempt #2 to fix the timed end +* v1.0.1.37 - properly reset ArenaPlayers on timed end +* v1.0.1.36 - properly reset ArenaPlayers that still have a team +* v1.0.1.35 - fix some little derping inside the goal winning management +* v1.0.1.34 - Turret module settings and spawn management! +* v1.0.1.33 - fix #251 - rather than triggering the end, check for remaining teams +* v1.0.1.32 - fix #209 - only replace BlockDestroy Block if more lives than blocks! +* v1.0.1.31 - Pillars config setting fix +* v1.0.0.30 - more pillar configuration! +* v1.0.0.29 - PILLAR goal! +* v1.0.0.28 - fix more issues with CB 1.7 and respawning +* v1.0.0.27 - override .equals() for PALocation and PABlockLocation +* v1.0.0.26 - fix an NPE due to disconnecting when the arena checks if it is ready +* v1.0.0.25 - fix WarmupJoin - anyone remember stupid messups? Now we know why. +* v1.0.0.24 - fix the Map.clone() issues in all goals +* v1.0.0.23 - what you say! +* v1.0.0.22 - rewrite part one: fix lives. affects ALL GOALS! +* v1.0.0.21 - fix a little NPE in BlockDestroy goal. REWRITE incoming! +* v1.0.0.20 - new attempt to fix the .clone() issue +* v1.0.0.19 - revert #18 - first sleep then code. night! +* v1.0.0.18 - .clone() Lesson 1: unlink field references +* v1.0.0.17 - wait. what? if this fixes it, Im gonna... +* v1.0.0.16 - add to /pa debug 102 +* v1.0.0.15 - add to /pa debug 9 +* v1.0.0.14 - support multiple destroyable blocks! +* v1.0.0.13 - fix #243 - trying to add a team +* v1.0.0.12 - don't send messages if empty +* v1.0.0.11 - fix an NPE when calculating the winner +* v1.0.0.10 - attempt to fix Ticket #193,#198,#209 +* v1.0.0.1 - update versions and readme \ No newline at end of file diff --git a/doc/history/1.1.md b/doc/history/1.1.md new file mode 100644 index 000000000..599f3824e --- /dev/null +++ b/doc/history/1.1.md @@ -0,0 +1,131 @@ +== PVP-Arena v1.1 Changelog + +=== Changelog + +* v1.1.2.420 - add config settings for DBO ticket 815 +* v1.1.2.419 - don't trigger a score trigger for destroying your own block +* v1.1.2.418 - remove unneeded event, there is a static hook present! +* v1.1.2.417 - properly implement the event +* v1.1.2.416 - add "proper" (hackfix) API to use Announcements in other modules +* v1.1.2.415 - update classes for 1.7 -> ProjectileSource +* v1.1.2.414 - update to bukkit 1.7 +* v1.1.2.413 - fixed: add goal "PlayerDeathConfirm" - FUN FUN FUN !!! +* v1.1.2.412 - jenkins no likey switch? +* v1.1.2.411 - add goal "PlayerDeathConfirm" - FUN FUN FUN !!! +* v1.1.1.410 - take worlds into account when comparing region overlap +* v1.1.1.409 - expose shortcut definitions and values +* v1.1.1.408 - consoleoffduty: allow the console to use shortcuts by default +* v1.1.1.407 - actually allow usage of /pa duty +* v1.1.1.406 - revert 403 and 405 - sorry, moo :P +* v1.1.1.405 - fix 403 - maybe +* v1.1.1.404 - shortcut determination debug enhancement +* v1.1.1.403 - try to queue teleports at the end, for less invisibility?? +* v1.1.1.402 - adds /pa duty; adding github issue #41 +* v1.1.0.401 - address github issue #44 +* v1.1.0.400 - address github issue #42 - hooray for single arena shortcuts! +* v1.1.0.399 - address github issue #46 +* v1.1.0.398 - change inv clearing: NONE / SURVIVAL / CREATIVE / ALL +* v1.1.0.397 - fix issue #808 - team kills score in TDM +* v1.1.0.396 - properly / sanely initiate shortcut definition defaults +* v1.1.0.395 - make classes.yml copy-able - needs reordering if you already set global classes. sorry! +* v1.1.0.394 - add a "maxhealth" setting to alter starting health, and allow setting health to -1 for FULL health +* v1.1.0.393 - allow admins to create multiple battle regions and only need players to be in one of those +* v1.1.0.392 - allow for case insensitive ALL / FULL debug +* v1.1.0.391 - fix Liberation LOST determination +* v1.1.0.390 - add "items.keepOnRespawn" to ... duh... keep items on respawn +* v1.1.0.389 - add "clearCreative" setting to clear creative players before joining +* v1.1.0.388 - properly unkill PlayerDeathMatch losers +* v1.1.0.387 - properly mark users as such +* v1.1.0.386 - tweak liberation debug output +* v1.1.0.385 - properly return that there are not enough players +* v1.1.0.384 - finalize the finalization +* v1.1.0.383 - finalize the arena shortcut system +* v1.1.0.382 - don't remove liberation and TDM players on the final kill +* v1.1.0.381 - have playerdeathmatch and playerkillrewards reflect default arena ending behaviour +* v1.1.0.380 - double check each goal if the arena is counting down to end +* v1.1.0.379 - attempty to activate loggers per arena ... maybe? +* v1.1.0.378 - properly display warning on module enabling +* v1.1.0.377 - support tank late joining, addresses github issue #40 +* v1.1.0.376 - fix class saving and load messup - sorry ! +* v1.1.0.375 - sort all the things! +* v1.1.0.374 - ... +* v1.1.0.373 - don't ask +* v1.1.0.372 - fix spectators not being completely reset +* v1.1.0.371 - allow specification of armor slot (0!BONE -> bone hat) +* v1.1.0.370 - totally not break anything by fixing githubg issue #37 +* v1.1.0.369 - address github issue #39 - rotation +* v1.1.0.368 - together with Announcements v367, fix github issue #38 +* v1.1.0.367 - plugin for sale. I pay you 100 bucks! +* v1.1.0.366 - never code when not drunk! +* v1.1.0.365 - clarify missing goal/arena file message +* v1.1.0.364 - run the "score" goal when players destroy blockdestroy blocks +* v1.1.0.363 - address github issue #36 - arenas are saved lowercase! +* v1.1.0.362 - add global class definitions, classes.yml +* v1.1.0.361 - allow for case insensitive lazy usage of shortcuts +* v1.1.0.360 - add /pa [arena] template save|load [file] +* v1.1.0.359 - finish /pa reload, reloading the main config and all arenas+subs +* v1.1.0.358 - correctly place shortcuts instead of arena names, when enforcing +* v1.1.0.357 - add pvparena.override - to specifically allow/deny special privileges +* v1.1.0.356 - add new main config settings to allow for arena management +* v1.1.0.355 - fix playerlives goal lives calculation for team arenas +* v1.1.0.354 - support hoppers and droppers and stuff for FOOD goal! +* v1.1.0.353 - if this breaks all the things, blame moo ! +* v1.1.0.352 - attempt to add readme files to the jar +* v1.1.0.351 - really fix the NPE mentioned in #351 +* v1.1.0.350 - fix strange refill runnable NPE +* v1.1.0.349 - don't require a lounge for infected people! +* v1.1.0.348 - force reset an arena if the start event has been cancelled +* v1.1.0.347 - properly allow autovote to access running arenas +* v1.1.0.346 - sanely handle non global non arena notification runnables +* v1.1.0.345 - add an evil invisibility fix attempt +* v1.1.0.344 - finally finish! fix arrows staying stuck on players! +* v1.1.0.343 - still onyl for moo !!! +* v1.1.0.342 - only for moo !!! arrow debugging! +* v1.1.0.341 - suprise, #340 now works +* v1.1.0.340 - fix invisibility - configurably +* v1.1.0.339 - stop removing region runnables if they are needed +* v1.1.0.338 - support max health changing ingame by double checking max health +* v1.1.0.337 - allow to select classes and ready up with right click +* v1.1.0.336 - actually apply proper duration and level for flag carrier potion effefct +* v1.1.0.335 - allow hunger disabling (player.hunger) +* v1.1.0.334 - stop starvation in the lounge +* v1.1.0.333 - attempt to properly remove liberation losers +* v1.1.0.332 - attempt to tackle github issue #16 and github issue #19 +* v1.1.0.331 - implement #330 in a more sane way +* v1.1.0.330 - allow mods to notify admins that forgot to set their regions to BATTLE +* v1.1.0.329 - check if anyone IS liberated before stating and giving points! fixes github issue #32 +* v1.1.0.328 - fix liberation liberation formatting +* v1.1.0.327 - address github issue #22 - properly parse dead player's chat and refill inventory +* v1.1.0.326 - address github issue #22 - read the player's team name rather than trying to teleport to nulljail +* v1.1.0.325 - suppress an issue about non arena players damaging arena players or vice versa - github issue #27 +* v1.1.0.324 - stop using multiple end countdowns at at time, addresses github issue #23 +* v1.1.0.323 - address github issue #19 - refresh arena debuggers +* v1.1.0.322 - allow players to re-ready +* v1.1.0.321 - omnom on force start github issue #16, maybe even github issue #14 +* v1.1.0.320 - stop counting suicides as deathmatch points - addresses github issue #29 +* v1.1.0.319 - attempt to maintain WATCH region maintainance +* v1.1.0.318 - properly check before blocking commands +* v1.1.0.317 - undo #316; try again later +* v1.1.0.316 - little gamemode deprecation fix +* v1.1.0.315 - automatically assign joining to one arena if only one is running +* v1.1.0.314 - in 3+ team games, properly determine if there is a draw +* v1.1.0.313 - bettergears config addition: only replace armor if leather +* v1.1.0.312 - prevent a NPE apparently happening on perm removal +* v1.1.0.311 - offer bettergears armor customisation; revert #310 +* v1.1.0.310 - offer betterclasses armor customisation +* v1.1.0.309 - language fixes, partially fixes github issue #23 +* v1.1.0.308 - addresses github issue #21 - hackfix +* v1.1.0.307 - add specific vault reward settings +* v1.1.0.306 - fix GitHub issue #18 +* v1.1.0.305 - restructure logging creating - now per command - maybe +* v1.1.0.304 - allow re-readying to initiate an arena start +* v1.1.0.303 - fix the Time Goal ending and NPE derp +* v1.1.0.302 - end games where people leave a Time Goal only match +* v1.1.0.301 - FORCE START OVERRIDE! let's pray this does not break all the thingsthat +* v1.1.0.300 - if this does not disable flying, you are hacking, mibby +* v1.1.0.298 - attempt to enforce flymode removal +* v1.1.0.297 - merge code optimisations by Iaccidentally +* v1.1.0.296 - nope, backwards compatibility is too hard - more changes to come. Hands off! +* v1.1.0.295 - try to establish backwards compatibility +* v1.1.0.294 - finish the ArenaRegion rewrite. Use with caution!!! +* v1.1.0.293 - rewrite the ArenaRegion system. Hope noone created their own Shapes yet :O \ No newline at end of file diff --git a/doc/history/1.2.md b/doc/history/1.2.md new file mode 100644 index 000000000..64df2c55f --- /dev/null +++ b/doc/history/1.2.md @@ -0,0 +1,78 @@ +== PVP-Arena v1.2 Changelog + +=== Changelog + +* v1.2.4.494 - remove some debug spam about dye and leather data +* v1.2.4.493 - properly make use of the "keepOnDeath" together with "dropsInventory" +* v1.2.4.492 - remove the remaining Exceptions -.- +* v1.2.4.491 - remove debug leftovers - sorry! +* v1.2.4.490 - address DBO ticket #874 - various fixes/additions +* v1.2.4.489 - finally correctly address the inventory restoring issues (keepItems should be fixed now!) +* v1.2.4.488 - add showRemainingLives - allow hiding of the remaining lives +* v1.2.4.487 - fix little Arcade related NPE +* v1.2.4.486 - add (hacky) support for Arcade; and: jenkins maven repo! +* v1.2.4.485 - possibly fix PlayerLives ending? +* v1.2.4.484 - shift death parsing order; attempt to fix respawnrelay - ticket #792 +* v1.2.4.482 - [DOM] change announceOffset to display logic, not to count logic; addresses github issue #66 +* v1.2.4.481 - fix TDM kill output. address github issue #65; revert fix build #465 +* v1.2.4.480 - address github issue #64 +* v1.2.4.479 - add Domination tickinterval (60) and tickreward (1); adds github issue #60 +* v1.2.4.478 - fix a respawn relay NPE, e.g. when a player leaves while respawning +* v1.2.4.477 - more Inventory dropping/restoring fixes +* v1.2.4.476 - WARNING - MAYBE BREAKING +* v1.2.3.475 - add config settings for global points system +* v1.2.3.474 - address ticket #866 +* v1.2.3.473 - forward allowed items instead of the (mostly cleared) event drops +* v1.2.3.472 - add respawnrelay specific debug +* v1.2.3.471 - rewrite the smart respawning +* v1.2.3.470 - fixed debug +* v1.2.3.469 - even more debug :/ +* v1.2.3.468 - godgodgodgo - I will! [smart respawn debug spam] +* v1.2.3.467 - default to VILLAGER instead of WOOL as Rescue Entity +* v1.2.3.466 - add "Rescue" language and config node +* v1.2.3.465 - mibby sais push, slipcor pushes! +* v1.2.3.464 - another instance of false proclamation of rewards +* v1.2.3.463 - add final liberation kill, don't tell the arena the rewards have been given too early +* v1.2.3.462 - address github issue #46 - buffer team players +* v1.2.3.461 - fix WorldGuard language nodes +* v1.2.3.461 - fix arena player class determination +* v1.2.3.460 - fix "custom" classes not being considered as such, fixes #828 +* v1.2.3.459 - allow inventory access for Flag Holders; fixes #828 +* v1.2.3.458 - add WorldGuard config settings +* v1.2.3.457 - add PlayerClass command implementation +* v1.2.3.456 - add player created classes [pvparena.create.class] +* v1.2.3.455 - add better named ArenaBoard headers +* v1.2.3.454 - support colored ArenaBoard signs +* v1.2.3.453 - add default goal config settings +* v1.2.3.452 - add the teleport lag y-offset to "old" (pre-join) locations +* v1.2.3.451 - add ' ' to the non printed messages. addresses github issue #59 +* v1.2.3.450 - finish github issue #53 [Infect] +* v1.2.3.449 - small fixes +* v1.2.3.448 - [WARNING] only for mibby & github issue #54 - might break player resets!! - force remove players from arenas +* v1.2.3.447 - anyone having an issue with us NOT kicking everyone if the arena fails to start? addresses github issue #44 +* v1.2.3.446 - add PATeamChangeEvent for infect, tank and other things like that +* v1.2.3.445 - fix github issue #57 - modules/goals do not add default config settings +* v1.2.3.444 - [WARNING] only for mibby & github issue #44 - rewrote the start check, might either fix it or break everything +* v1.2.3.443 - add ColorTeams->ScoreBoard to use the scoreboard coloring instead of TagAPI +* v1.2.3.442 - little fixes, thanks to samoatesgames +* v1.2.3.441 - add debug for github issue #44 - countdown ignoring uneven teams +* v1.2.3.440 - add debug for github issue #46 - "teamrewards" +* v1.2.3.439 - [BlockDissolve] add "startSeconds" to wait X seconds before removing +* v1.2.3.438 - properly maintain sorting when handing over sorted collections +* v1.2.3.437 - add debug for github issue #43 +* v1.2.3.436 - properly save the config after setting an inventory to a config node +* v1.2.3.435 - add BlockDissolve config values +* v1.2.3.434 - only add needed config nodes +* v1.2.2.433 - [g:TeamLives] only mark a player as lost when needed +* v1.2.2.432 - verify #431 +* v1.2.2.431 - properly remove player names that are longer than 15 characters +* v1.2.2.430 - nerf #429 +* v1.2.2.429 - add an error stacktrace while unsuccessfully handling a sign removal +* v1.2.2.428 - finish the old/new updater! +* v1.2.2.427 - fix a ClassCastException when using /pa info +* v1.2.2.426 - change the updater to my former way for several reasons. see documentation +* v1.2.2.425 - add alwaysJoinInBattle - allow people to join late, no matter what! +* v1.2.2.424 - fix issue #830 - only care about players not playing or players part of the current arena +* v1.2.2.423 - enforce inventory reset (if wanted) +* v1.2.2.422 - properly reset the "players that have played" counters +* v1.2.2.421 - prepare for 1.8 - STEP 1: use player UUIDs for stats \ No newline at end of file diff --git a/doc/history/1.3.0.md b/doc/history/1.3.0.md new file mode 100644 index 000000000..5278f1ef0 --- /dev/null +++ b/doc/history/1.3.0.md @@ -0,0 +1,66 @@ +== PVP-Arena v1.3.0 Changelog + +- v1.3.0.558 - fix github issue #83 +- v1.3.0.557 - fix github issue #61 +- v1.3.0.556 - fix github issue #64 +- v1.3.0.555 - add x-offset and z-offset, so one can change the default behaviour of putting ppl on the middle of a block +- v1.3.0.554 - fix an NPE in some places due to a return value of null should be expected! +- v1.3.0.553 - add chat.toGlobal to allow private talking players to talk to the public with a prefix +- v1.3.0.552 - add CRAFT RegionProtection to prevent item crafting +- v1.3.0.551 - add damage.fromOutsiders (false) to allow players (and other entities) to hurt fighters +- v1.3.0.550 - properly check for some things before adding players to a class via command +- v1.3.0.549 - try to fix long usernames staying on signs +- v1.3.0.548 - prevent a NPE +- v1.3.0.547 - call the leave event - I am shocked noone noticed that until yesterday +- v1.3.0.546 - reverse all the things and do what I promised the last 2 commits +- v1.3.0.545 - fix books! (for real) +- v1.3.0.544 - fix books! +- v1.3.0.543 - trying again +- v1.3.0.542 - attempt to fix some data reading issues (for ink sacks and wool blocks) +- v1.3.0.541 - fix some display issues about max team players +- v1.3.0.540 - attempt to fix special character issues +- v1.3.0.539 - allow to take suicides into account for TDM +- v1.3.0.538 - still on github issue #78 - never remove perms! +- v1.3.0.537 - fix missing perms message, addressing github issue #78 +- v1.3.0.536 - finish github issue #78 - typo messup +- v1.3.0.535 - address github issue #78 - add language nodes for missing perms +- v1.3.0.534 - prevent tamed animals belonging to an arena player from teleporting +- v1.3.0.533 - finally fix github issue #76 - inventory reset messup +- v1.3.0.532 - address github issue #76 +- v1.3.0.531 - address github issue #64 +- v1.3.0.530 - add "classSwitchAfterRespawn", defaulting to false +- v1.3.0.529 - revert #523 - I don't care anymore - this HAS to fix it, otherwise I give up on development :P +- v1.3.0.528 - revert #519 - second attempt at fixing an issue on several implementations +- v1.3.0.527 - revert #518 - this fixed dbo issue #912 (duplications on Cauldron) but caused items disappearing on other implementations +- v1.3.0.526 - add more config settings for PlayerKillReward +- v1.3.0.525 - address DBO issue #923 +- v1.3.0.524 - address DBO issue #921 +- v1.3.0.522 - fix integer/integer divisions -.- +- v1.3.0.521 - clarify custom class determination debug +- v1.3.0.520 - clarify damage debug values +- v1.3.0.519 - forcefully place players where they joined if the player is disconnecting +- v1.3.0.518 - forcefully remove items when a player leaves the arena +- v1.3.0.517 - address DBO issue #907 - don't try to teleport null/dead players +- v1.3.0.516 - try fixing NOCAMP damage +- v1.3.0.515 - [IDEA] various fixes +- v1.3.0.511 - address DBO issue #888 - reset chat color if desired +- v1.3.0.510 - add mobs fighting by your side. Give classes a spawn egg with displayname "SPAWN" +- v1.3.0.509 - properly build #507 prefix +- v1.3.0.507 - add materialprefixes to the global config, for special Material names (bukkit:SAND) +- v1.3.0.506 - add '*' command for the whitelist to allow all commands +- v1.3.0.505 - add per command permissions - defaulting to old behaviour +- v1.3.0.504 - don't drop inventory if not desired +- v1.3.0.503 - fix the UUID interpretation; use player names for creation, not the UUID -.- +- v1.3.0.502 - how about we actually RUN the runnable? +- v1.3.0.501 - force /pa leave on final player death if no specate module present +- v1.3.0.500 - address ticket #869, #884, #792 + - add time.resetDelay (default: -1 --> off) - delay for resetting players (TP & inventory) + - support single SPAWN regions for team matches + - support lore and displayname for keepItems +- v1.3.0.499 - address ticket 792, 879, 881 + - attempt to fix the Food Goal to properly handle player deaths + - require explicit perms for /pa arenaclass (if desired) +- v1.3.0.498 - properly initiate late joining PlayerDeathMatch players +- v1.3.0.497 - check for explicit class perms, even though we have no Sign! +- v1.3.0.496 - minor fixes +- v1.3.0.495 - add Command Tab support; Big Command rewrite!! \ No newline at end of file diff --git a/doc/history/1.3.1.md b/doc/history/1.3.1.md new file mode 100644 index 000000000..c5c6fdf8a --- /dev/null +++ b/doc/history/1.3.1.md @@ -0,0 +1,47 @@ +== PVP-Arena v1.3.1 Changelog + +- v1.3.1.49 - fix an NPE on server shutdown +- v1.3.1.48 - update all the things in the doc +- v1.3.1.46 - pull #106 - thanks a TON to @Oruss7 for putting together this load of information! +- v1.3.1.45 - the final update for 1.7.9 - unless critical errors arrive. I need to get ready for 1.9 +- v1.3.1.44 - prevent an NPE in the WarmupJoin module +- v1.3.1.43 - revert the last commit and furthermore clarify and verify correctly. Modules build incoming +- v1.3.1.42 - fix a logic messups in an internal join check +- v1.3.1.41 - duel module finished +- v1.3.1.40 - allow to disable the Duel force ready & start +- v1.3.1.39 - duel module language finish +- v1.3.1.38 - finish off github issue #118 +- v1.3.1.37 - more shurtcut arena list fixes +- v1.3.1.36 - try to fix the round arena status check +- v1.3.1.35 - apply former fix for arena listing +- v1.3.1.34 - override only_shortcuts with allow_ungrouped to allow joining arenas not grouped under shortcuts +- v1.3.1.33 - properly format and save spawn offsets +- v1.3.1.32 - properly format and save spawn offsets +- v1.3.1.31 - properly allow for 5 arguments of /pa spawn +- v1.3.1.30 - fix github issues #115, #118 +- v1.3.1.29 - address github issue #112 +- v1.3.1.28 - how about we don't delete the spawn after offsetting it? -.- +- v1.3.1.26 - github issue #104 - EXPERIMENTAL! +- v1.3.1.25 - this time for real - we need to tell people they CAN decline :) +- v1.3.1.24 - add final language for github issue #97 +- v1.3.1.23 - add config for github issue #86 +- v1.3.1.22 - release build +- v1.3.1.21 - and more language nodes +- v1.3.1.20 - prepare Dual fixes and commit some language/message fixes +- v1.3.1.19 - fix another Exception in the time goal +- v1.3.1.18 - properly output unclaiming vs contesting flags in domination goal - language file consistency fixed +- v1.3.1.17 - fix some language derps and move the delayed class change to where it makes more sense +- v1.3.1.16 - fix github issue #108 - contesting (unclaiming) too late +- v1.3.1.15 - add github issue #100 - player.healforkill - true/false :) +- v1.3.1.14 - use the SNAPSHOT distinction and address github issue #85 +- v1.3.1.13 - hide the not-really stat type NULL (player name) +- v1.3.1.12 - fix github issue #95 by adding a null check +- v1.3.1.11 - clarify language for RespawnRelay and fix a little Exception in the Time goal +- v1.3.1.10 - address github issue #88 - properly keep players as DEAD when being relayed +- v1.3.1.9 - address github issue #87 - add THORNS damage handling +- v1.3.1.8 - properly deal with inventory protection +- v1.3.1.7 - how about we don't spam EVERYthing but spam after collecting everything, and inform people that we have prevented something? +- v1.3.1.6 - fix some mathematical and logical derps +- v1.3.1.5 - really add INVENTORY check - properly define new Infect commands [setprotect|getprotect] +- v1.3.1.4 - allow goals to deny BREAK, PLACE, TNT, TNTBREAK, DROP, INVENTORY, PICKUP, CRAFT - proof of concept! +- v1.3.1.1 - link to new jenkins. Thanks to @graywolf336 \ No newline at end of file diff --git a/doc/history/1.3.2.md b/doc/history/1.3.2.md new file mode 100644 index 000000000..6d0af568e --- /dev/null +++ b/doc/history/1.3.2.md @@ -0,0 +1,79 @@ +== PVP-Arena v1.3.2 Changelog + +- v1.3.2.137 - address github issue #205 +- v1.3.2.136 - add language response for ChestFiller +- v1.3.2.135 - add documentation about ChestFiller changes, add some more config nodes that are now properly loaded with defaults automatically +- v1.3.2.134 - address github issue #201 - properly call PAJoinEvent, this never was implemented correctly. Sorry! +- v1.3.2.133 - prepare ChestFiller addition by adding language and documentation +- v1.3.2.132 - prepare ChestFiller addition by adding config node +- v1.3.2.131 - remove FallingAnvils hooks and documentation - it did not work out :/ +- v1.3.2.130 - stop spamming, please. Aims at fixing github issue #154 +- v1.3.2.129 - address github issue #209 - oups +- v1.3.2.128 - add a module method "parseStartCountDown" to possibly override the remaining seconds to go +- v1.3.2.127 - fix github issue #204 by removing all traces of the nonexisting command "import" +- v1.3.2.126 - address github issue #202 - remove "error" and only write it to debug +- v1.3.2.125 - address github issue #155, prevent double dropping of inventory. Hope this does not break anything :P +- v1.3.2.124 - address github issue #154 - just remove tick 4, it's not that important anyways. And remove the blocklist spam :) +- v1.3.2.122 - furthermore fix the uninstall routine +- v1.3.2.121 - address github issue #131 - I think I found the bug! +- v1.3.2.120 - address github issue #203 by firstly fixing the NPE and adding more info to the uninstalling error (Main server log!) +- v1.3.2.119 - prevent double instantiation of arenas - use with caution! :P +- v1.3.2.118 - [CheckPoints] - address github issue #197 +- v1.3.2.117 - [BetterFight] add config setting to restrict explosions only to one-hit deaths +- v1.3.2.116 - add CheckPoint goal (github issue #184) - have fun testing! +- v1.3.2.115 - add "refillforkill" - restocks the inventory with the class items +- v1.3.2.114 - address github issue #191 - prevent NPE due to NULL item in class items +- v1.3.2.113 - add more debug to investigate fire charge ignition issues +- v1.3.2.112 - continue fix for Scoreboards being double reset in modules +- v1.3.2.111 - prepare fix for Scoreboards being double reset in modules +- v1.3.2.110 - address github issue #185 by fixing WorldEdit documentation and messages +- v1.3.2.109 - address github issue #186 +- v1.3.2.107 - address github issue #178 - prevent enderpearl teleport when not alive and fighting +- v1.3.2.106 - [TeamDeathMatch] fix a double broadcast of the winning team +- v1.3.2.105 - fix the documentation for EventAction config +- v1.3.2.103 - furthermore attempt to fix #175 by adding a teleport lock variable +- v1.3.2.102 - support multiple WATCH and LOUNGE regions - addresses github issue #175 +- v1.3.2.101 - finish github issue #174 +- v1.3.2.100 - address github issue #174 +- v1.3.2.99 - add Beacons settings and documentation +- v1.3.2.97 - add Titles API hooks, documentation will follow +- v1.3.2.96 - add a configuration node to change the schematics folder for WorldEdit - adds github issue #129 +- v1.3.2.95 - add region command documentation - thanks @Oruss7 +- v1.3.2.94 - add Language for special Duel/Vault hooking +- v1.3.2.93 - add config settings and documentation for the FallingAnvils module +- v1.3.2.92 - [forcewin] how about we load the command so it can be used? +- v1.3.2.91 - add /pa [arena] forcewin, shorthand !fw - forces a player / team to win +- v1.3.2.90 - fix some more errors about the new command. Works now :) +- v1.3.2.89 - fix the shorthand and the doc linking +- v1.3.2.88 - add /pa [arena] classchest [class] - shorthand !cc - fixed class chests containing the items +- v1.3.2.87 - address github issue #168, NPE on StructureGrowEvent +- v1.3.2.85 - revert deprecation of ArenaModule.getArena() - failsafe(r) loading of modules and goals - arenas will not appear lost any more! +- v1.3.2.84 - address github issue #161, properly read ambiguous ready block definition +- v1.3.2.83 - address github issue #159 - do not instanciate the tracker if disabled +- v1.3.2.82 - address github issue #158 by adding 'shortcut_shuffle' +- v1.3.2.81 - address github issue #154, maybe even issue #86 - only check necessarily flagged regions and BATTLE regions, with include-check +- v1.3.2.80 - properly fix build #68 +- v1.3.2.79 - add TELEPORT protection to allow teleport prevention (it was silently allowed if only happening IN the region, without command) +- v1.3.2.78 - change WALLS config setting command to "wallseconds", it interfered with the most probable arena name +- v1.3.2.77 - revert the CommandPreProcessEvent and rather fix the underlying problem, the command whitelist being too greedy. Added a config setting to use comand list as wildcards +- v1.3.2.76 - enforce player and teamplayer max values, move CommandPreProcessEvent to priority low to fix MobArena join related exploits +- v1.3.2.75 - properly save an ArenaGoal name to the round map (instead of its instance) +- v1.3.2.74 - fix a NPE in the EndRunnable when using rounds +- v1.3.2.73 - add a new command "regionclear" to manage region clearing exceptions +- v1.3.2.72 - add language and documentation for the WorldEdit addition +- v1.3.2.71 - add WorldEdit config to specify regions to autoload/autosave +- v1.3.2.70 - allow data values in MATERIAL definitions (only works with /pa set [node] hand) +- v1.3.2.69 - properly apply rewards when teamrewards is used +- v1.3.2.68 - remove repo pushing to maybe fix building for now +- v1.3.2.64 - fix issue #143 - thanks to Oruss7! +- v1.3.2.63 - add some message output when class changing fails +- v1.3.2.62 - prepare module class change hooking +- v1.3.2.61 - address github issue #114 - add LibsDisguises support +- v1.3.2.60 - fix CTF being messed up by people continuing to play +- v1.3.2.59 - fix update check +- v1.3.2.58 - /pa help - it still shows the colored standard reply even with sub-arguments +- v1.3.2.57 - address github issue #135 - language addition +- v1.3.2.56 - address github issue #141 - add config calcoffset to tweak block dissolve greediness +- v1.3.2.55 - fix Spectate Spectators being told they cannot teleport when switching view +- v1.3.2.54 - new Module: Spectate - uses the 1.8 SPECTATOR GameMode +- v1.3.2.51 - update to Java 7 \ No newline at end of file diff --git a/doc/history/1.3.3.md b/doc/history/1.3.3.md new file mode 100644 index 000000000..17572ca81 --- /dev/null +++ b/doc/history/1.3.3.md @@ -0,0 +1,112 @@ +== PVP-Arena v1.3.3 Changelog + +- v1.3.3.248 - /pa reload ymls | reload main config, language and help ymls +- v1.3.3.247 - do not duplicate offhand items and don't try to set objectives that are not needed (because of disabled scoreboard) +- v1.3.3.246 - address github issue #280, reload global language and help nodes on /pa reload +- v1.3.3.245 - revert player names appearing on scoreboards, maybe properly display 0 team lives left? +- v1.3.3.244 - catch an NPE about scoreboards and dead/offline players and fix a scoreboard crash vulnerability +- v1.3.3.243 - eventually delay scoreboard display to arena start, delay inventory reset to when a player gets put back to their exit spawn, delay fire tick reset +- v1.3.3.242 - properly reset scoreboard when simply leaving by command +- v1.3.3.241 - address github issue #278 - support "hand" placeholder for multiple-item-definitions too +- v1.3.3.240 - address github issue #276 by catching the NPE even deeper +- v1.3.3.239 - fix inventory double drop bug when losing the last life +- v1.3.3.238 - allow for default death messaeges by setting both deathmessage config nodes to false +- v1.3.3.237 - address github issue #271 - do not remove/use player list scoreboard if scoreboard is disabled +- v1.3.3.236 - address github issue #273 - add Elytra to chestplate definition list +- v1.3.3.235 - address github issue #274 - fix player leaving handling in general +- v1.3.3.234 - properly require permission for /pa command +- v1.3.3.233 - address github issue #273 - single item definitions (maybe more) gets lost until restart +- v1.3.3.232 - add github issue #258 - liberation scoreboard separation of jailed players +- v1.3.3.231 - add github issue #198 - particle display of domination claim radius +- v1.3.3.230 - add github issue #237 - items on kill, settable via command and "inventory" handle! +- v1.3.3.229 - address github issue #254 - update Arrow Hack for Spigot > 1.9 +- v1.3.3.228 - address github issue #151 and try to add a custom scoreboard entry to show round progress +- v1.3.3.227 - fix scoreboard removal and fix a bug that caused doubled starting method call +- v1.3.3.226 - allow longer scoreboard entries (48 characters for now) +- v1.3.3.225 - reintroduce custom scoreboard entries +- v1.3.3.224 - address github issue #264 - ArenaClass equipping debug triggers NPE +- v1.3.3.223 - address github issue #267 - critical fix about gamemodes +- v1.3.3.222 - fix grabbing the flag giving you no wool head +- v1.3.3.221 - refresh debug instance for global debug when stopping / changing debug output +- v1.3.3.220 - further ID fixes, and fix a but about GameMode setting and one about players being able to join an arena when it is restoring +- v1.3.3.219 - finish the item ID burial +- v1.3.3.218 - stop supporting item IDs in configs - configs shall be updated! +- v1.3.3.217 - do not nag people to update if updater type DOWNLOAD is selected - addresses github issue #244 +- v1.3.3.216 - address a bug about invisibility being nullified by internal scoreboard +- v1.3.3.215 - address issue #238 by adding refillCustomInventory - defaulting to true +- v1.3.3.214 - address issue #255 - Remove arrows stuck to everyone +- v1.3.3.213 - address issue #256 - Exception about ScoreBoards when shutting down +- v1.3.3.212 - fix issue #252 by catching a NPE +- v1.3.3.211 - revert c67e4a6 - never mess with flying speed or walking speed again plz :P +- v1.3.3.210 - revert 4f75803 - never mess with flying speed or walking speed again plz :P +- v1.3.3.209 - final attempt to get rid of the speed issue - deactivate with -10 +- v1.3.3.208 - address issues with commit 4f75803 +- v1.3.3.207 - address github issues #245 and #248 +- v1.3.3.206 - finish the spawn region fix +- v1.3.3.205 - continue attemmpt to fix region spawning +- v1.3.3.204 - revert the last commit and try to fix region spawning +- v1.3.3.203 - try to fix an issue about respawning players not getting reset properly +- v1.3.3.202 - try to finish off github issue #212 by delaying scoreboard slot selection and player removal +- v1.3.3.201 - allow to disable all gamemode changes; make "takeOutOfGame" actually work +- v1.3.3.200 - prevent the plugin from messing up player restoring in certain reset cases +- v1.3.3.199 - address github issue #238 - allow to keep ALL items on respawn +- v1.3.3.198 - add "teleportonkill" to allow force respawn of killers +- v1.3.3.197 - address github issue #238 - allow to keep ALL items on respawn +- v1.3.3.196 - address github issue #240 - message consistency +- v1.3.3.195 - address github issue #241 - don't use Location, use Vectors for offset +- v1.3.3.194 - fix github issue #232 - Potions disappearing when readying up +- v1.3.3.193 - fix StatisticsManager to actually be persistent. SORRY! +- v1.3.3.192 - add config for github issue #220 +- v1.3.3.191 - fix github issue #188 - I found the right way to deactivate collision +- v1.3.3.190 - address github issue #120 - limiting class changes +- v1.3.3.189 - address github issue #99 - can we finally bury this? ^^ +- v1.3.3.188 - [FFA] allow to punish being killed by other things than a player: punishsuicide +- v1.3.3.187 - allow to set keepOnRespawn to "all" to, yes, keep all items +- v1.3.3.186 - implement ColorTeams and ScoreBoards modules into core - addresses github issue #212 +- v1.3.3.185 - add an announcement verification hack to WarmupJoin +- v1.3.3.184 - revert build #177 (saturation lock), does not work anyways +- v1.3.3.183 - very important module fix - player resetting was broken! +- v1.3.3.182 - reduce command whitelist case sensitivity +- v1.3.3.181 - reduce command case sensitivity +- v1.3.3.180 - allow modules to know whether to soft reset a player +- v1.3.3.179 - fix config node typo +- v1.3.3.178 - allow to quick leave with caps lock +- v1.3.3.177 - add saturation lock, to prevent regains going crazy +- v1.3.3.176 - apply global and specific teleport offset when resetting player +- v1.3.3.175 - fix github issue #230 +- v1.3.3.174 - little thing about #230 and add more debug to see why it might not work yet +- v1.3.3.173 - address github issue #222, again +- v1.3.3.172 - finish github issue #225 +- v1.3.3.171 - add github issue #230 - apply the teleport protection to the lounge, too, to prevent teleport warnings +- v1.3.3.170 - try to fix disabling breaking arena shortcut rotation +- v1.3.3.169 - maybe fix an issue that shortcut rotation doesn't work when the arenas are disabled at start +- v1.3.3.168 - partially revert breaking #222 even more +- v1.3.3.167 - address github issue #227 - reset killer's items to KILLER's class +- v1.3.3.166 - maybe finally tackle github issue #222 +- v1.3.3.165 - properly implement github issue #225 +- v1.3.3.164 - finish up github issue #203 +- v1.3.3.163 - address github issue #224 +- v1.3.3.162 - address all remnants of issue #203 +- v1.3.3.161 - address github issue #224 - double output in the lounge +- v1.3.3.160 - I got an idea, how about we actually implement issue #188 ?! oh and add issue #225 +- v1.3.3.159 - address github issue #222 +- v1.3.3.158 - continue fixing the issue mentioned in build #153 +- v1.3.3.157 - address github issue #222, again +- v1.3.3.156 - change the updating process and block installing/updating when there is no install.yml due to "update.files" (you can allow this setting and disable automatic updates with updatemode "none" or "announce") +- v1.3.3.155 - remove spectral arrows from the potion meta list, those don't seem to have potion effects +- v1.3.3.153 - try to fix the issue of lounge players not being able to interact where they should +- v1.3.3.152 - try to implement github issue #188 +- v1.3.3.151 - add config setting for github issue #188 +- v1.3.3.150 - address github issue #131 - if it's not fixed, I at least added debug +- v1.3.3.149 - address github issue #215 by removing a never launched minigame API and make sure to get the proper shortcut name, if possible +- v1.3.3.148 - finally fix github issue #205 +- v1.3.3.147 - prevent inventory dropping even if custom class is active +- v1.3.3.146 - found the little bug that caused github issue #205 ! +- v1.3.3.145 - partially revert d8d9bf174027aadc6ccd641b6cef7b660f435f25 to address github issue #205 +- v1.3.3.144 - potions are operational. Please update your class definitions (if you did not use class chests) +- v1.3.3.143 - please use the same logic for saving and loading +- v1.3.3.142 - potions should work now. Please redo all your potionish classes (potions, splash potions, lingering, arrows, etc) +- v1.3.3.141 - try to fix armor supply +- v1.3.3.140 - properly fix Potion creation/saving broken by Spigot 1.9 API changes +- v1.3.3.139 - properly fix Inventory handling broken by Spigot 1.9 API changes +- v1.3.3.138 - move to Spigot 1.9.4 \ No newline at end of file diff --git a/doc/history/1.3.4.md b/doc/history/1.3.4.md new file mode 100644 index 000000000..e26bb8668 --- /dev/null +++ b/doc/history/1.3.4.md @@ -0,0 +1,52 @@ +== PVP-Arena v1.3.4 Changelog + +- v1.3.4.298 - attempt to properly back up NBT data of player's items in case of an unnatural leaving of the arena +- v1.3.4.297 - address github issue #351 - add yet another delay to fix Spigot +- v1.3.4.296 - address github issue #329 - actually change the scoreboard title :O +- v1.3.4.295 - fix the fact that the scoreboard did not update on losing the last life. Thanks to @Oruss7 +- v1.3.4.294 - add team size and total team count when joining +- v1.3.4.293 - address github issue #332 - display first checkpoint message, and display numbers starting from 1 +- v1.3.4.292 - address github issue #329 - use arena prefix instead of name, if still too long, shorten manually +- v1.3.4.291 - added debug to PotionSplashEvent for someone to have evidence to report a bug +- v1.3.4.290 - when setting up a region, check that it has actual resulting volume before saving +- v1.3.4.289 - address github issue #324 - call home asynchronously +- v1.3.4.288 - stop igniting your own TNT - and tell people that it is not okay +- v1.3.4.287 - update EventActions docs to properly reflect the node names +- v1.3.4.286 - update EventActions docs and fix github issue #314 by not stopping arenas twice on reload! +- v1.3.4.285 - allow to update spawn and blocks on the fly +- v1.3.4.284 - fix docs [remove colorteams and scoreboard] and add language and docs for BetterClass "respawnCommand" +- v1.3.4.283 - add EventActions addition (classchange hook) +- v1.3.4.282 - address github issue #305 - check max health before setting health +- v1.3.4.281 - address github issue #302 - prevent NPE for spectators when joining the arena +- v1.3.4.280 - remove debug output of time message nodes +- v1.3.4.279 - add github issue #249 - playSound (???) to add particle effect, DONE +- v1.3.4.278 - add github issue #124 - add timer configs to add/remove/change timer interval messages +- v1.3.4.277 - add github issue #117 - BossBar for Domination +- v1.3.4.276 - do not setup a scoreboard if spectating is cancelled/not possible +- v1.3.4.275 - allow right clicking blocks when LOST attempt 2 +- v1.3.4.274 - allow right clicking blocks when LOST and add Region Protection Tutorial +- v1.3.4.273 - update player equip function to support offhand slots +- v1.3.4.272 - properly protect and not overprotect, affected: MOBS [block lightning], TNT [prevent entity damage], GROW [actually block block growth] +- v1.3.4.271 - remove metrics and update the readme with new region shape tutorial +- v1.3.4.270 - do not add spectator names to the scoreboard +- v1.3.4.269 - update the spectator scoreboard +- v1.3.4.268 - create a scoreboard for spectators +- v1.3.4.267 - address github issue #291 by adding "perms.spectatorinteract" to allow spectators to interact +- v1.3.4.266 - remove debug and address github issue #292 by checking if a player already joined an arena before doing anything +- v1.3.4.265 - how I miss those debug times. IS THE PLAYER FLYING OR NOT!??!! +- v1.3.4.264 - why not try without delay? +- v1.3.4.263 - change fly mode saving and restoring +- v1.3.4.262 - do not restore flying state if specating on death +- v1.3.4.261 - delay flying mode setting by 5 ticks when restoring a player +- v1.3.4.260 - address github issue #290 - catch NPE about Spawn Eggs +- v1.3.4.259 - finish off github issue #280 by adding a proper message about reloading the languages +- v1.3.4.258 - finish the fix for issue #198 by supporting beacon block definitions +- v1.3.4.257 - address github issue #198 - make particle circle function goal independant +- v1.3.4.256 - address github issue #285 - catch NPE by checking for missing round argument +- v1.3.4.255 - address github issue #263 - properly cancel interact event - I assumed that they come uncancelled - wrong +- v1.3.4.254 - who ordered .lck files? Not me! Byebye! [debugging file handler not closed] +- v1.3.4.253 - hotfix about cancelling PlayerItemConsumeEvent - sorry @mibby, fasting is over now! +- v1.3.4.252 - fix issue #263 by cancelling PlayerItemConsumeEvent - since when is this a necessity? The interact event was cancelled :P +- v1.3.4.251 - fix spawn alignment glitches, some of which were fixed by restarting the server, fix double messages around right clicking +- v1.3.4.250 - update some things to the latest API - fix CheckPoints spawn set logic, fix PlayerDeathMatch required kill display +- v1.3.4.249 - update to Spigot 1.11 - address github issue #218 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1686c6b11..cce51d935 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ net.slipcor pvparena - 1.3.4-SNAPSHOT + 1.13-SNAPSHOT PVP Arena @@ -18,7 +18,7 @@ org.bukkit bukkit - 1.11.2-R0.1-SNAPSHOT + 1.13-R0.1-SNAPSHOT jar provided diff --git a/readme.md b/readme.md index 57be5ed8a..080b386a0 100644 --- a/readme.md +++ b/readme.md @@ -30,7 +30,7 @@ This flexibility is achieved on the one hand by a module loader created by Nodin ## Dependencies -- Spigot 1.11.2 +- Spigot 1.13 *** @@ -93,7 +93,7 @@ Users tutorials : ## Changelog -- v1.3.4.298 - attempt to properly back up NBT data of player's items in case of an unnatural leaving of the arena +- v1.13.0 - slowly work our way to Spigot 1.13 - [read more](doc/changelog.md) *** diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java index 9b6cd40b1..c4849928f 100644 --- a/src/net/slipcor/pvparena/arena/ArenaClass.java +++ b/src/net/slipcor/pvparena/arena/ArenaClass.java @@ -49,31 +49,47 @@ public final class ArenaClass { // static filling of the items array static { HELMETS_TYPE.add(Material.LEATHER_HELMET); - HELMETS_TYPE.add(Material.GOLD_HELMET); + HELMETS_TYPE.add(Material.GOLDEN_HELMET); HELMETS_TYPE.add(Material.CHAINMAIL_HELMET); HELMETS_TYPE.add(Material.IRON_HELMET); HELMETS_TYPE.add(Material.DIAMOND_HELMET); - HELMETS_TYPE.add(Material.WOOL); + HELMETS_TYPE.add(Material.BLACK_WOOL); + HELMETS_TYPE.add(Material.BLUE_WOOL); + HELMETS_TYPE.add(Material.BROWN_WOOL); + HELMETS_TYPE.add(Material.CYAN_WOOL); + HELMETS_TYPE.add(Material.GRAY_WOOL); + HELMETS_TYPE.add(Material.GREEN_WOOL); + HELMETS_TYPE.add(Material.LIGHT_BLUE_WOOL); + HELMETS_TYPE.add(Material.LIGHT_GRAY_WOOL); + HELMETS_TYPE.add(Material.LIME_WOOL); + HELMETS_TYPE.add(Material.MAGENTA_WOOL); + HELMETS_TYPE.add(Material.ORANGE_WOOL); + HELMETS_TYPE.add(Material.PINK_WOOL); + HELMETS_TYPE.add(Material.PURPLE_WOOL); + HELMETS_TYPE.add(Material.RED_WOOL); + HELMETS_TYPE.add(Material.WHITE_WOOL); + HELMETS_TYPE.add(Material.YELLOW_WOOL); + HELMETS_TYPE.add(Material.PUMPKIN); HELMETS_TYPE.add(Material.JACK_O_LANTERN); - HELMETS_TYPE.add(Material.SKULL_ITEM); + HELMETS_TYPE.add(Material.PLAYER_HEAD); CHESTPLATES_TYPE.add(Material.LEATHER_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.GOLD_CHESTPLATE); + CHESTPLATES_TYPE.add(Material.GOLDEN_CHESTPLATE); CHESTPLATES_TYPE.add(Material.CHAINMAIL_CHESTPLATE); CHESTPLATES_TYPE.add(Material.IRON_CHESTPLATE); CHESTPLATES_TYPE.add(Material.DIAMOND_CHESTPLATE); CHESTPLATES_TYPE.add(Material.ELYTRA); LEGGINGS_TYPE.add(Material.LEATHER_LEGGINGS); - LEGGINGS_TYPE.add(Material.GOLD_LEGGINGS); + LEGGINGS_TYPE.add(Material.GOLDEN_LEGGINGS); LEGGINGS_TYPE.add(Material.CHAINMAIL_LEGGINGS); LEGGINGS_TYPE.add(Material.IRON_LEGGINGS); LEGGINGS_TYPE.add(Material.DIAMOND_LEGGINGS); BOOTS_TYPE.add(Material.LEATHER_BOOTS); - BOOTS_TYPE.add(Material.GOLD_BOOTS); + BOOTS_TYPE.add(Material.GOLDEN_BOOTS); BOOTS_TYPE.add(Material.CHAINMAIL_BOOTS); BOOTS_TYPE.add(Material.IRON_BOOTS); BOOTS_TYPE.add(Material.DIAMOND_BOOTS); @@ -185,7 +201,7 @@ public static void equip(final Player player, final ItemStack[] items) { player.getInventory().setItemInOffHand(last); continue; } - if (item.getType() == Material.MONSTER_EGG && item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { final SpawnEggMeta egg = (SpawnEggMeta) item.getItemMeta(); try { diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index cd1fa5f60..7cf71ab56 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -207,12 +207,11 @@ public static void givePlayerFightItems(final Arena arena, final Player player) if (arena.getArenaConfig().getBoolean(CFG.USES_WOOLHEAD)) { final ArenaTeam aTeam = aPlayer.getArenaTeam(); - final String color = aTeam.getColor().name(); + final ChatColor color = aTeam.getColor(); arena.getDebugger().i("forcing woolhead: " + aTeam.getName() + '/' - + color, player); + + color.name(), player); player.getInventory().setHelmet( - new ItemStack(Material.WOOL, 1, StringParser - .getColorDataFromENUM(color))); + new ItemStack(StringParser.getWoolMaterialFromChatColor(color))); } } diff --git a/src/net/slipcor/pvparena/commands/PAA_Setup.java b/src/net/slipcor/pvparena/commands/PAA_Setup.java index d51c22016..ea6277f83 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Setup.java +++ b/src/net/slipcor/pvparena/commands/PAA_Setup.java @@ -15,6 +15,7 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -122,7 +123,8 @@ public void run() { final Set spawns = SpawnManager.getPASpawnsStartingWith(arena, word[2]); for (final PASpawn spawn : spawns) { final Location loc = spawn.getLocation().toLocation(); - player.sendBlockChange(loc, Material.WOOL, (byte) 0); + + player.sendBlockChange(loc, Material.WHITE_WOOL.createBlockData()); new Remover(loc); } return; @@ -131,7 +133,8 @@ public void run() { final Set blocks = SpawnManager.getPABlocksContaining(arena, word[2]); for (final PABlock block : blocks) { final Location loc = block.getLocation().toLocation(); - player.sendBlockChange(loc, Material.WOOL, (byte) 0); + + player.sendBlockChange(loc, Material.WHITE_WOOL.createBlockData()); new Remover(loc); } return; diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index cf0b19ce9..459c47a4f 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -1,17 +1,12 @@ package net.slipcor.pvparena.core; import net.slipcor.pvparena.PVPArena; -import org.bukkit.ChatColor; -import org.bukkit.Color; -import org.bukkit.DyeColor; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.block.BlockFace; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.*; -import org.bukkit.material.Dye; -import org.bukkit.material.Wool; import org.bukkit.potion.PotionData; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; @@ -219,8 +214,7 @@ public static ItemStack getItemStackFromString(final String string) { final String strEnch = temp2[i]; if (strEnch.contains("~")) { final String[] arrEnch = strEnch.split("~"); - final Enchantment ench = Enchantment.getById(Integer - .parseInt(arrEnch[0])); + final Enchantment ench = Enchantment.getByKey(NamespacedKey.minecraft(arrEnch[0])); final Integer enchLevel = Integer.parseInt(arrEnch[1]); DEBUG.i("adding enchantment " + ench.getName() + " lvl " + enchLevel); @@ -299,14 +293,6 @@ public static ItemStack getItemStackFromString(final String string) { } } - if (data.equals("")) { - // Data is messed up, let's try to fix it! - - if (mat == Material.INK_SACK || mat == Material.WOOL) { - data = temp[2]; // 2 or 3 definately is set as data, should work! - } - } - if (mat == Material.WRITTEN_BOOK) { data = temp[2]; } @@ -332,24 +318,8 @@ public static ItemStack getItemStackFromString(final String string) { itemStack.setItemMeta(meta); } - if (mat == Material.INK_SACK) { - try { - itemStack.setData(new Dye(Byte.parseByte(data))); - } catch (final Exception e) { - DEBUG.i( - "invalid dye data: " + data); - return itemStack; - } - } else if (mat == Material.WOOL) { - try { - itemStack.setData(new Wool(Byte.parseByte(data))); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning( - "invalid wool data: " + data); - return itemStack; - } - } else if (mat == Material.WRITTEN_BOOK - || mat == Material.BOOK_AND_QUILL) { + if (mat == Material.WRITTEN_BOOK + || mat == Material.WRITABLE_BOOK) { final BookMeta bookMeta = (BookMeta) itemStack.getItemMeta(); try { final String[] outer = data.split(SAFE_BREAK); @@ -377,7 +347,7 @@ public static ItemStack getItemStackFromString(final String string) { "invalid leather data: " + data); return itemStack; } - } else if (itemStack.getType() == Material.SKULL_ITEM) { + } else if (itemStack.getType() == Material.PLAYER_HEAD) { try { final SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); skullMeta.setOwner(data); @@ -419,7 +389,7 @@ public static ItemStack getItemStackFromString(final String string) { } if (lore != null - && !(mat == Material.WRITTEN_BOOK || mat == Material.BOOK_AND_QUILL)) { + && !(mat == Material.WRITTEN_BOOK || mat == Material.WRITABLE_BOOK)) { final List lLore = new ArrayList<>(); for (final String line : lore.split(SAFE_BREAK)) { lLore.add(codeCharacters(line, false)); @@ -434,22 +404,12 @@ public static ItemStack getItemStackFromString(final String string) { e.printStackTrace(); return itemStack; } - } else if (itemStack.getType() == Material.MONSTER_EGG) { - try { - final SpawnEggMeta meta = (SpawnEggMeta) itemStack.getItemMeta(); - meta.setSpawnedType(EntityType.fromName(data)); - itemStack.setItemMeta(meta); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning( - "invalid spawn egg data: " + data); - return itemStack; - } } else { DEBUG.i("data not available for: " + mat.name()); } if (lore != null - && !(mat == Material.WRITTEN_BOOK || mat == Material.BOOK_AND_QUILL)) { + && !(mat == Material.WRITTEN_BOOK || mat == Material.WRITABLE_BOOK)) { final List lLore = new ArrayList<>(); for (final String line : lore.split(SAFE_BREAK)) { lLore.add(codeCharacters(line, false)); @@ -550,16 +510,8 @@ public static String getStringFromItemStack(final ItemStack itemStack) { temp.append(itemStack.getDurability()); durability = true; } - if (itemStack.getType() == Material.INK_SACK || itemStack.getType() == Material.WOOL) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - temp.append('~'); - temp.append(itemStack.getData().getData()); - } else if (itemStack.getType() == Material.WRITTEN_BOOK - || itemStack.getType() == Material.BOOK_AND_QUILL) { + if (itemStack.getType() == Material.WRITTEN_BOOK + || itemStack.getType() == Material.WRITABLE_BOOK) { if (!durability) { temp.append('~'); temp.append(itemStack.getDurability()); @@ -587,7 +539,7 @@ public static String getStringFromItemStack(final ItemStack itemStack) { final LeatherArmorMeta leatherMeta = (LeatherArmorMeta) itemStack.getItemMeta(); temp.append('~'); temp.append(leatherMeta.getColor().asRGB()); - } else if (itemStack.getType() == Material.SKULL_ITEM) { + } else if (itemStack.getType() == Material.PLAYER_HEAD) { if (!durability) { temp.append('~'); temp.append(itemStack.getDurability()); @@ -614,17 +566,6 @@ public static String getStringFromItemStack(final ItemStack itemStack) { temp.append(pe.getType().getName()).append('x').append(pe.getAmplifier()).append('x').append(pe.getDuration()); temp.append(SAFE_BREAK); } - } else if (itemStack.getType() == Material.MONSTER_EGG){ - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - temp.append('~'); - final SpawnEggMeta meta = (SpawnEggMeta) itemStack.getItemMeta(); - if (meta != null && meta.getSpawnedType() != null && meta.getSpawnedType().name() != null) { - temp.append(meta.getSpawnedType().name()); - } } if (itemStack.hasItemMeta() && itemStack.getItemMeta().hasLore()) { @@ -650,7 +591,7 @@ public static String getStringFromItemStack(final ItemStack itemStack) { if (enchants != null && !enchants.isEmpty()) { for (final Map.Entry enchantmentIntegerEntry : enchants.entrySet()) { temp.append('|'); - temp.append(enchantmentIntegerEntry.getKey().getId()); + temp.append(enchantmentIntegerEntry.getKey().getKey().getKey()); temp.append('~'); temp.append(enchantmentIntegerEntry.getValue()); } @@ -673,6 +614,58 @@ private static String getWoolEnumFromChatColorEnum(final String color) { return parseDyeColorToChatColor(color, false); } + public static Material getWoolFallbackMaterialFromString(final String color) { + for (Material mat : Material.values()) { + if (mat.name().contains("WOOL") && mat.name().contains(color.toUpperCase())) { + return mat; + } + } + DEBUG.i(">> Material defaulting '"+color+"' to BROWN_WOOL!! <<"); + return Material.BROWN_WOOL; + } + + public static Material getWoolMaterialFromChatColor(final ChatColor color) { + /* + Unsupported: + ChatColor.AQUA + Material.BROWN_WOOL + */ + + switch (color) { + case BLACK: + return Material.BLACK_WOOL; + case DARK_BLUE: + return Material.BLUE_WOOL; + case DARK_GREEN: + return Material.GREEN_WOOL; + case DARK_AQUA: + return Material.CYAN_WOOL; + case DARK_RED: + return Material.RED_WOOL; + case DARK_PURPLE: + return Material.PURPLE_WOOL; + case GOLD: + return Material.ORANGE_WOOL; + case GRAY: + return Material.LIGHT_GRAY_WOOL; + case DARK_GRAY: + return Material.GRAY_WOOL; + case BLUE: + return Material.LIGHT_BLUE_WOOL; + case GREEN: + return Material.LIME_WOOL; + case RED: + return Material.PINK_WOOL; + case LIGHT_PURPLE: + return Material.MAGENTA_WOOL; + case YELLOW: + return Material.YELLOW_WOOL; + case WHITE: + default: + return Material.WHITE_WOOL; + } + } + public static String joinArray(final Object[] array, final String glue) { final StringBuilder result = new StringBuilder(""); for (final Object o : array) { diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java index fd7ff8c09..68ad9321e 100644 --- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java +++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java @@ -503,13 +503,7 @@ void takeBlock(final String blockColor, final PABlockLocation paBlockLocation) { if ("WOOL".equals(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE))) { paBlockLocation.toLocation() .getBlock() - .setTypeIdAndData( - Material.valueOf( - arena.getArenaConfig().getString( - CFG.GOAL_BLOCKDESTROY_BLOCKTYPE)) - .getId(), - StringParser.getColorDataFromENUM(blockColor), - false); + .setType(StringParser.getWoolFallbackMaterialFromString(blockColor)); } else { paBlockLocation.toLocation() .getBlock() diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java index 9f366c30b..b74edee46 100644 --- a/src/net/slipcor/pvparena/goals/GoalDomination.java +++ b/src/net/slipcor/pvparena/goals/GoalDomination.java @@ -450,7 +450,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block || !PAA_Region.activeSelections.containsKey(player.getName())) { return res; } - if (block == null || block.getType() != Material.WOOL) { + if (block == null || !block.getType().name().contains("WOOL")) { return res; } res.setPriority(this, PRIORITY); // success :) @@ -754,8 +754,7 @@ public void setDefaults(final YamlConfiguration config) { * * @param paBlockLocation the location to take/reset*/ void takeFlag(final PABlockLocation paBlockLocation) { - paBlockLocation.toLocation().getBlock() - .setData(StringParser.getColorDataFromENUM("WHITE")); + paBlockLocation.toLocation().getBlock().setType(Material.WHITE_WOOL); } @Override @@ -842,12 +841,10 @@ private void takeFlag(final Arena arena, final Location lBlock, final String nam } } if (team == null) { - lBlock.getBlock().setData( - StringParser.getColorDataFromENUM("WHITE")); + lBlock.getBlock().setType(Material.WHITE_WOOL); return; } - lBlock.getBlock().setData( - StringParser.getColorDataFromENUM(team.getColor().name())); + lBlock.getBlock().setType(StringParser.getWoolMaterialFromChatColor(team.getColor())); } } diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 129f5ef97..918e9de9c 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -1015,10 +1015,10 @@ void takeFlag(final String flagColor, final boolean take, final PABlockLocation } if (take) { paBlockLocation.toLocation().getBlock() - .setData(StringParser.getColorDataFromENUM("WHITE")); + .setType(Material.WHITE_WOOL); } else { paBlockLocation.toLocation().getBlock() - .setData(StringParser.getColorDataFromENUM(flagColor)); + .setType(StringParser.getWoolFallbackMaterialFromString(flagColor)); } } diff --git a/src/net/slipcor/pvparena/goals/GoalFood.java b/src/net/slipcor/pvparena/goals/GoalFood.java index 53874ef0b..1e12466e6 100644 --- a/src/net/slipcor/pvparena/goals/GoalFood.java +++ b/src/net/slipcor/pvparena/goals/GoalFood.java @@ -71,11 +71,13 @@ public String version() { private static final Map cookmap = new HashMap<>(); static { - cookmap.put(Material.RAW_BEEF, Material.COOKED_BEEF); - cookmap.put(Material.RAW_CHICKEN, Material.COOKED_CHICKEN); - cookmap.put(Material.RAW_FISH, Material.COOKED_FISH); - cookmap.put(Material.POTATO_ITEM, Material.BAKED_POTATO); - cookmap.put(Material.PORK, Material.GRILLED_PORK); + cookmap.put(Material.BEEF, Material.COOKED_BEEF); + cookmap.put(Material.CHICKEN, Material.COOKED_CHICKEN); + cookmap.put(Material.COD, Material.COOKED_COD); + cookmap.put(Material.MUTTON, Material.COOKED_MUTTON); + cookmap.put(Material.PORKCHOP, Material.COOKED_PORKCHOP); + cookmap.put(Material.POTATO, Material.BAKED_POTATO); + cookmap.put(Material.SALMON, Material.COOKED_SALMON); } @Override diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java index 8e1c035ac..b9e0cd82a 100644 --- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java @@ -950,15 +950,20 @@ void takeFlag(final String flagColor, final boolean take, final PABlockLocation } if (take) { paBlockLocation.toLocation().getBlock() - .setData(StringParser.getColorDataFromENUM("WHITE")); + .setType(Material.WHITE_WOOL); } else { - paBlockLocation.toLocation() - .getBlock() - .setTypeIdAndData( - Material.valueOf( - arena.getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE)).getId(), - StringParser.getColorDataFromENUM(flagColor), false); + Material attempt = Material.getMaterial(flagColor+"_"+arena.getArenaConfig().getString( + CFG.GOAL_FLAGS_FLAGTYPE)); + if (attempt == null) { + attempt = Material.valueOf( + arena.getArenaConfig().getString( + CFG.GOAL_FLAGS_FLAGTYPE)); + + if (attempt == null) { + attempt = StringParser.getWoolFallbackMaterialFromString(flagColor); + } + } + paBlockLocation.toLocation().getBlock().setType(attempt); } } diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java index 32d55d0ed..e26fec0d2 100644 --- a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java +++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java @@ -222,13 +222,6 @@ public void displayInfo(final CommandSender sender) { private void drop(final Player player, final ArenaTeam team) { final ItemStack item = StringParser.getItemStackFromString(arena.getArenaConfig().getString(CFG.GOAL_TDC_ITEM)); - if (item.getType() == Material.WOOL || item.getType() == Material.INK_SACK || - item.getType() == Material.STAINED_GLASS || item.getType() == Material.STAINED_CLAY) { - final MaterialData data = item.getData(); - data.setData(getDataFromTeam(team)); - item.setData(data); - item.setDurability(getDataFromTeam(team)); - } final ItemMeta meta = item.getItemMeta(); meta.setDisplayName(team.getColoredName()); diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 92ab5d06e..0dc252a44 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -73,7 +73,7 @@ private boolean checkAndCommitCancel(final Arena arena, final Player player, final Material mat = pie.getClickedBlock().getType(); final Material check = arena == null ? Material.IRON_BLOCK : arena .getReadyBlock(); - if (mat == Material.SIGN || mat == Material.SIGN_POST + if (mat == Material.SIGN || mat == Material.WALL_SIGN || mat == Material.WALL_SIGN || mat == check) { DEBUG.i("signs and ready blocks allowed!", player); DEBUG.i("> false", player); diff --git a/src/net/slipcor/pvparena/managers/ConfigurationManager.java b/src/net/slipcor/pvparena/managers/ConfigurationManager.java index fc88bc3d5..e8eb4293f 100644 --- a/src/net/slipcor/pvparena/managers/ConfigurationManager.java +++ b/src/net/slipcor/pvparena/managers/ConfigurationManager.java @@ -173,8 +173,6 @@ public static boolean configParse(final Arena arena, final Config cfg) { config.options().copyDefaults(true); - updateItemIDs(cfg, "1.0.6.198"); - cfg.set(CFG.Z, "1.3.3.217"); cfg.save(); cfg.load(); @@ -376,221 +374,4 @@ public static String isSetup(final Arena arena) { } return null; } - - private static void updateItemIDs(Config config, String... versions) { - final String version = config.getString(CFG.Z); - boolean saveNeeded = false; - - for (String v : versions) { - if (version.equals(v)) { - if (updateItemID(config, CFG.READY_BLOCK, Material.IRON_BLOCK)) { - saveNeeded = true; - } - if (updateItemID(config, CFG.GENERAL_WAND, Material.STICK)) { - saveNeeded = true; - } - if (updateItemID(config, CFG.GOAL_BLOCKDESTROY_BLOCKTYPE, Material.IRON_BLOCK)) { - saveNeeded = true; - } - if (updateItemID(config, CFG.GOAL_FLAGS_FLAGTYPE, Material.WOOL)) { - saveNeeded = true; - } - if (updateItemID(config, CFG.MODULES_WALLS_MATERIAL, Material.SAND)) { - saveNeeded = true; - } - if (replaceItemIDs(config, CFG.LISTS_WHITELIST)) { - saveNeeded = true; - } - if (replaceItemIDs(config, CFG.LISTS_BLACKLIST)) { - saveNeeded = true; - } - if (replaceClassDefinitions(config)) { - saveNeeded = true; - } - - final File classFile = new File(PVPArena.instance.getDataFolder(), "classes.yml"); - final YamlConfiguration cfg = YamlConfiguration.loadConfiguration(classFile); - final Map classMap = new HashMap<>(); - ConfigurationSection configurationSection = cfg.getConfigurationSection("classes"); - if (configurationSection != null && replaceConfig(configurationSection, classMap)) { - for (String key : classMap.keySet()) { - configurationSection.set(key, classMap.get(key)); - } - try { - cfg.save(classFile); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - if (saveNeeded) { - config.save(); - } - } - - private static boolean replaceClassDefinitions(Config config) { - final Map classMap = new HashMap<>(); - ConfigurationSection configurationSection = config.getYamlConfiguration().getConfigurationSection("classitems"); - if (replaceConfig(configurationSection, classMap)) { - for (String key : classMap.keySet()) { - configurationSection.set(key, classMap.get(key)); - } - return true; - } - return false; - } - - private static boolean replaceConfig(ConfigurationSection configurationSection, Map classMap) { - boolean needsUpdateResult = false; - for (String node : configurationSection.getKeys(true)) { - String definition = configurationSection.getString(node); - if (definition.contains(",")) { - String[] definitions = definition.split(","); - boolean needsUpdate = false; - for (int pos=0; pos>!<<")) { - return replaceItemDefinition(def, ">>!<<"); - } else if (def.contains(">>O<<")) { - return replaceItemDefinition(def, ">>O<<"); - } - return replaceItemDefinition(def); - } - - @SuppressWarnings("deprecation") - private static String replaceItemDefinition(String definition) { - if (definition.contains("|")) { - String[] split = definition.split("\\|"); - try { - Material material = Material.getMaterial(Integer.parseInt(split[0])); - split[0] = material.name(); - return StringParser.joinArray(split, "|"); - } catch (Exception e) { - return definition; - } - } else if (definition.contains("~")) { - String[] split = definition.split("~"); - try { - Material material = Material.getMaterial(Integer.parseInt(split[0])); - split[0] = material.name(); - return StringParser.joinArray(split, "~"); - } catch (Exception e) { - return definition; - } - } else if (definition.contains(":")) { - String[] split = definition.split(":"); - try { - Material material = Material.getMaterial(Integer.parseInt(split[0])); - split[0] = material.name(); - return StringParser.joinArray(split, ":"); - } catch (Exception e) { - return definition; - } - } - try { - Material material = Material.getMaterial(Integer.parseInt(definition)); - return material.name(); - } catch (Exception e) { - return definition; - } - } - - private static String replaceItemDefinition(String definition, String separator) { - String[] split = definition.split(separator); - split[1] = replaceItemDefinition(split[1]); - return StringParser.joinArray(split, separator); - } - - @SuppressWarnings("deprecation") - private static boolean replaceItemIDs(Config config, CFG node) { - boolean saveNeeded = false; - final List subNodes = Arrays.asList("break", "place"); - - for (String subNode : subNodes) { - final String path = node.getNode() + "." + subNode; - - final List configEntries = config.getStringList(path, new ArrayList()); - - final List oldEntries = new ArrayList<>(); - final List newEntries = new ArrayList<>(); - - for (String entry : configEntries) { - if (entry.matches("[0-9]+")) { - int id = Integer.parseInt(entry); - Material material = Material.getMaterial(id); - oldEntries.add(entry); - newEntries.add(material.name()); - } else if (entry.contains(":")){ - String first = entry.split(":")[0]; - if (first.matches("[0-9]+")) { - int id = Integer.parseInt(first); - Material material = Material.getMaterial(id); - oldEntries.add(entry); - newEntries.add(material.name()+entry.substring(entry.length())); - } - } - } - if (!oldEntries.isEmpty()) { - for (int pos=0; pos Date: Thu, 26 Jul 2018 02:29:16 +0200 Subject: [PATCH 002/115] v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions --- doc/changelog.md | 1 + pom.xml | 44 -- readme.md | 2 +- src/net/slipcor/pvparena/arena/Arena.java | 38 +- .../slipcor/pvparena/arena/ArenaClass.java | 92 ++- .../slipcor/pvparena/arena/ArenaPlayer.java | 14 +- .../slipcor/pvparena/arena/PlayerState.java | 2 +- src/net/slipcor/pvparena/classes/PACheck.java | 3 +- .../slipcor/pvparena/classes/PAClaimBar.java | 1 - .../slipcor/pvparena/commands/PAA_Class.java | 36 +- .../pvparena/commands/PAA_ForceWin.java | 9 +- .../pvparena/commands/PAA_PlayerClass.java | 37 +- .../slipcor/pvparena/commands/PAA_Set.java | 35 +- .../slipcor/pvparena/commands/PAA_Setup.java | 29 +- src/net/slipcor/pvparena/core/Config.java | 61 +- src/net/slipcor/pvparena/core/Language.java | 1 + .../slipcor/pvparena/core/StringParser.java | 563 +----------------- src/net/slipcor/pvparena/core/Utils.java | 73 +++ .../slipcor/pvparena/events/PAWinEvent.java | 13 +- .../pvparena/goals/GoalDomination.java | 47 +- src/net/slipcor/pvparena/goals/GoalFlags.java | 14 +- .../slipcor/pvparena/goals/GoalInfect.java | 5 +- .../pvparena/goals/GoalPhysicalFlags.java | 14 +- .../pvparena/goals/GoalPlayerKillReward.java | 120 ++-- .../pvparena/goals/GoalTeamDeathConfirm.java | 19 +- .../pvparena/listeners/BlockListener.java | 12 +- .../pvparena/listeners/EntityListener.java | 8 +- .../pvparena/listeners/PlayerListener.java | 8 +- .../slipcor/pvparena/loadables/ArenaGoal.java | 6 +- .../pvparena/loadables/ArenaGoalManager.java | 25 +- .../pvparena/loadables/ArenaModule.java | 8 +- .../loadables/ArenaModuleManager.java | 24 +- .../pvparena/loadables/ArenaRegion.java | 17 +- .../managers/ConfigurationManager.java | 106 ++-- .../slipcor/pvparena/modules/RegionTool.java | 3 - .../pvparena/regions/CuboidRegion.java | 2 +- .../pvparena/regions/CylindricRegion.java | 2 +- .../pvparena/regions/SphericRegion.java | 2 +- .../runnables/InventoryRefillRunnable.java | 11 +- 39 files changed, 453 insertions(+), 1054 deletions(-) create mode 100644 src/net/slipcor/pvparena/core/Utils.java diff --git a/doc/changelog.md b/doc/changelog.md index 5d6e1d1ed..d2efc08ee 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,4 +1,5 @@ == PVP-Arena v1.13 Changelog +- v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions - v1.13.0 - slowly work our way to Spigot 1.13 diff --git a/pom.xml b/pom.xml index cce51d935..313ed484c 100644 --- a/pom.xml +++ b/pom.xml @@ -45,30 +45,9 @@ plugin.yml - - . - true - ${basedir} - - README.creole - READMEv01.creole - READMEv010.creole - READMEv02.creole - READMEv03.creole - READMEv04.creole - READMEv05.creole - READMEv06.creole - READMEv07.creole - READMEv08.creole - READMEv09.creole - READMEv10.creole - SETUP.creole - - - org.apache.maven.plugins maven-compiler-plugin @@ -85,29 +64,6 @@ maven-jar-plugin 2.3.2 - - - com.google.code.maven-replacer-plugin - maven-replacer-plugin - 1.3.8 - - - prepare-package - - replace - - - - - target/classes/plugin.yml - - - jenkins-build-number - ${BUILD_NUMBER} - - - - \ No newline at end of file diff --git a/readme.md b/readme.md index 080b386a0..f4e132878 100644 --- a/readme.md +++ b/readme.md @@ -93,7 +93,7 @@ Users tutorials : ## Changelog -- v1.13.0 - slowly work our way to Spigot 1.13 +- v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions - [read more](doc/changelog.md) *** diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index 4e2e18e70..f6a20d4cc 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -19,6 +19,7 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.attribute.Attribute; import org.bukkit.block.Block; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; @@ -572,7 +573,7 @@ private Scoreboard getSpecialScoreboard() { } } - Objective obj = scoreboard.registerNewObjective("lives", "dummy"); //deathCount + String name = ChatColor.GREEN + "PVP Arena" + ChatColor.RESET + " - " + ChatColor.YELLOW + getName(); @@ -583,7 +584,7 @@ private Scoreboard getSpecialScoreboard() { name = name.substring(0, 32); } } - obj.setDisplayName(name); + Objective obj = scoreboard.registerNewObjective("lives", "dummy", name); //deathCount if (this.isFightInProgress()) { obj.setDisplaySlot(DisplaySlot.SIDEBAR); @@ -685,12 +686,8 @@ public void giveRewards(final Player player) { getDebugger().i("giving rewards to " + player.getName(), player); ArenaModuleManager.giveRewards(this, player); - final String sItems = cfg.getString(CFG.ITEMS_REWARDS, "none"); + ItemStack[] items = cfg.getItems(CFG.ITEMS_REWARDS); - String[] items = sItems.split(","); - if ("none".equals(sItems)) { - items = null; - } final boolean isRandom = cfg.getBoolean(CFG.ITEMS_RANDOM); final Random rRandom = new Random(); @@ -711,7 +708,7 @@ public void giveRewards(final Player player) { if (items[i] == null) { continue; } - final ItemStack stack = StringParser.getItemStackFromString(items[i]); + final ItemStack stack = items[i]; if (stack == null) { PVPArena.instance.getLogger().warning( "unrecognized item: " + items[i]); @@ -964,22 +961,6 @@ public static void pmsg(final CommandSender sender, final String msg) { sender.sendMessage(Language.parse(MSG.MESSAGES_GENERAL, PVPArena.instance.getConfig().getString("globalPrefix", "PVP Arena"), msg)); } - /** - * @deprecated use {@link #playerLeave(Player, CFG, boolean, boolean), boolean} - */ - @Deprecated - public void playerLeave(final Player player, final CFG location, final boolean silent) { - playerLeave(player, location, silent, !silent, silent); - } - - /** - * @deprecated use {@link #playerLeave(Player, CFG, boolean, boolean), boolean} - */ - @Deprecated - public void playerLeave(final Player player, final CFG location, final boolean silent, final boolean force) { - playerLeave(player, location, silent, force, !force); - } - /** * a player leaves from the arena * @@ -1551,7 +1532,6 @@ private void resetPlayer(final Player player, final String string, final boolean resetScoreboard(player, force, soft); //noinspection deprecation - ArenaModuleManager.resetPlayer(this, player, force); ArenaModuleManager.resetPlayer(this, player, soft, force); String sClass = ""; @@ -1710,10 +1690,10 @@ public void run() { public void unKillPlayer(final Player player, final DamageCause cause, final Entity damager) { getDebugger().i("respawning player " + player.getName(), player); - int iHealth = cfg.getInt(CFG.PLAYER_HEALTH, -1); + double iHealth = cfg.getInt(CFG.PLAYER_HEALTH, -1); if (iHealth < 1) { - iHealth = (int) player.getMaxHealth(); + iHealth = player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue(); } PlayerState.playersetHealth(player, iHealth); @@ -1869,7 +1849,7 @@ public void spawnCampPunish() { .setLastDamageCause( new EntityDamageEvent(locationArenaPlayerEntry.getValue().get(), DamageCause.CUSTOM, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(1002))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0)))); + 1002)); locationArenaPlayerEntry.getValue() .get() .damage(cfg.getInt( @@ -2104,7 +2084,7 @@ public void run() { public void run() { for (final ArenaPlayer player : getFighters()) { if (player.get() != null) { - player.get().showPlayer(aPlayer.get()); + player.get().showPlayer(PVPArena.instance, aPlayer.get()); } } } diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java index c4849928f..95912da0a 100644 --- a/src/net/slipcor/pvparena/arena/ArenaClass.java +++ b/src/net/slipcor/pvparena/arena/ArenaClass.java @@ -8,11 +8,11 @@ import org.bukkit.Material; import org.bukkit.block.Chest; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.meta.SpawnEggMeta; -import org.bukkit.material.SpawnEgg; import org.bukkit.plugin.IllegalPluginAccessException; import java.io.File; @@ -122,10 +122,17 @@ public static void addGlobalClasses() { } for (final String className : cfg.getConfigurationSection("classes").getKeys(false)) { - final String sItemList; + ItemStack[] items; + ItemStack offHand; + ItemStack[] armors; try { - sItemList = (String) cfg.getConfigurationSection("classes").get(className); + items = cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items").toArray(new ItemStack[0]); + offHand = cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items").toArray(new ItemStack[0])[0]; + armors = cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items").toArray(new ItemStack[0]); } catch (final Exception e) { Bukkit.getLogger().severe( "[PVP Arena] Error while parsing class, skipping: " @@ -138,49 +145,12 @@ public static void addGlobalClasses() { PABlockLocation loc = new PABlockLocation(classChest); Chest c = (Chest) loc.toLocation().getBlock().getState(); ItemStack[] contents = c.getInventory().getContents(); - final ItemStack[] items = Arrays.copyOfRange(contents, 0, contents.length-5); - final ItemStack offHand = contents[contents.length-5]; - final ItemStack[] armors = Arrays.copyOfRange(contents, contents.length-4, contents.length); + items = Arrays.copyOfRange(contents, 0, contents.length-5); + offHand = contents[contents.length-5]; + armors = Arrays.copyOfRange(contents, contents.length-4, contents.length); globals.put(className, new ArenaClass(className, items, offHand, armors)); } catch (Exception e) { - final String[] sItems = sItemList.split(","); - final ItemStack[] items = new ItemStack[sItems.length]; - final ItemStack[] offhand = new ItemStack[1]; - final ItemStack[] armors = new ItemStack[4]; - - for (int i = 0; i < sItems.length; i++) { - - if (sItems[i].contains(">>!<<")) { - final String[] split = sItems[i].split(">>!<<"); - - final int id = Integer.parseInt(split[0]); - armors[id] = StringParser.getItemStackFromString(split[1]); - - if (armors[id] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized armor item: " + split[1]); - } - - sItems[i] = "AIR"; - } else if (sItems[i].contains(">>O<<")) { - final String[] split = sItems[i].split(">>O<<"); - - final int id = Integer.parseInt(split[0]); - offhand[id] = StringParser.getItemStackFromString(split[1]); - - if (offhand[id] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized armor item: " + split[1]); - } - } - - items[i] = StringParser.getItemStackFromString(sItems[i]); - if (items[i] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized item: " + items[i]); - } - } - globals.put(className, new ArenaClass(className, items, offhand[0], armors)); + globals.put(className, new ArenaClass(className, items, offHand, armors)); } } } @@ -202,14 +172,14 @@ public static void equip(final Player player, final ItemStack[] items) { continue; } if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { - final SpawnEggMeta egg = (SpawnEggMeta) item.getItemMeta(); + final String eggType = item.getType().name().replace("_SPAWN_EGG", ""); try { Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable(){ @Override public void run() { ArenaPlayer.parsePlayer(player.getName()).getArena().addEntity( - player, player.getWorld().spawnEntity(player.getLocation(), egg.getSpawnedType())); + player, player.getWorld().spawnEntity(player.getLocation(), EntityType.valueOf(eggType))); } }, 20L); } catch(final IllegalPluginAccessException e) { @@ -218,7 +188,32 @@ public void run() { } else { player.getInventory().addItem(item); } - debug.i("- " + StringParser.getStringFromItemStack(item), player); + } + } + player.updateInventory(); + } + + public static void equip(final Player player, final ItemStack[][] itemArray) { + player.getInventory().setItemInOffHand(itemArray[1][0]); + player.getInventory().setArmorContents(itemArray[2]); + + for (final ItemStack item : itemArray[0]) { + if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { + final String eggType = item.getType().name().replace("_SPAWN_EGG", ""); + + try { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable(){ + @Override + public void run() { + ArenaPlayer.parsePlayer(player.getName()).getArena().addEntity( + player, player.getWorld().spawnEntity(player.getLocation(), EntityType.valueOf(eggType))); + } + }, 20L); + } catch(final IllegalPluginAccessException e) { + + } + } else { + player.getInventory().addItem(item); } } player.updateInventory(); @@ -228,7 +223,6 @@ public void equip(final Player player) { debug.i("Equipping player " + player.getName() + " with items!", player); for (ItemStack item : armors) { if (item != null) { - debug.i("armor: "+StringParser.getStringFromItemStack(item)); equipArmor(item, player.getInventory()); } } @@ -240,7 +234,6 @@ public void equip(final Player player) { equipArmor(item, player.getInventory()); } else { player.getInventory().addItem(item); - debug.i("- " + StringParser.getStringFromItemStack(item), player); } } player.getInventory().setItemInOffHand(offHand); @@ -248,7 +241,6 @@ public void equip(final Player player) { } private static void equipArmor(final ItemStack stack, final PlayerInventory inv) { - debug.i("- " + StringParser.getStringFromItemStack(stack), (Player) inv.getHolder()); final Material type = stack.getType(); if (HELMETS_TYPE.contains(type)) { if (inv.getHelmet() != null && inv.getHelmet().getType() != Material.AIR) { diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index 7cf71ab56..5231d9818 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -7,7 +7,7 @@ import net.slipcor.pvparena.core.Config; import net.slipcor.pvparena.core.Config.CFG; import net.slipcor.pvparena.core.Debug; -import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.events.PAPlayerClassChangeEvent; import net.slipcor.pvparena.loadables.ArenaModuleManager; import net.slipcor.pvparena.managers.ArenaManager; @@ -211,7 +211,7 @@ public static void givePlayerFightItems(final Arena arena, final Player player) arena.getDebugger().i("forcing woolhead: " + aTeam.getName() + '/' + color.name(), player); player.getInventory().setHelmet( - new ItemStack(StringParser.getWoolMaterialFromChatColor(color))); + new ItemStack(Utils.getWoolMaterialFromChatColor(color))); } } @@ -291,7 +291,8 @@ public static void reloadInventory(final Arena arena, final Player player, final final ArenaPlayer aPlayer = parsePlayer(player.getName()); if (!"none".equals(arena.getArenaConfig().getString(CFG.ITEMS_TAKEOUTOFGAME))) { - final ItemStack[] items = StringParser.getItemStacksFromString(arena.getArenaConfig().getString(CFG.ITEMS_TAKEOUTOFGAME)); + final ItemStack[] items = + arena.getArenaConfig().getItems(CFG.ITEMS_TAKEOUTOFGAME); final List allowedMats = new ArrayList<>(); @@ -337,7 +338,7 @@ public void run() { if (instant) { - debug.i("adding " + StringParser.getStringFromItemStacks(aPlayer.savedInventory), player); + debug.i("adding saved inventory", player); player.getInventory().setContents(aPlayer.savedInventory); } else { class GiveLater implements Runnable { @@ -347,7 +348,7 @@ class GiveLater implements Runnable { } @Override public void run() { - debug.i("adding " + StringParser.getStringFromItemStacks(inv), + debug.i("adding saved inventory", player); player.getInventory().setContents(inv); } @@ -434,9 +435,6 @@ public void debugPrint() { name); debug.i("location: " + location, name); debug.i("status: " + status.name(), name); - debug.i("savedInventory: " - + StringParser.getStringFromItemStacks(savedInventory), - name); debug.i("tempPermissions:", name); for (final PermissionAttachment pa : tempPermissions) { debug.i("> " + pa, name); diff --git a/src/net/slipcor/pvparena/arena/PlayerState.java b/src/net/slipcor/pvparena/arena/PlayerState.java index 8b6929556..d9c49a5f5 100644 --- a/src/net/slipcor/pvparena/arena/PlayerState.java +++ b/src/net/slipcor/pvparena/arena/PlayerState.java @@ -242,7 +242,7 @@ public void run() { * @param player the player to set * @param value the health value */ - public static void playersetHealth(final Player player, final int value) { + public static void playersetHealth(final Player player, final double value) { debug.i("setting health to " + value + "/20", player); if (Bukkit.getServer().getPluginManager().getPlugin("Heroes") == null) { player.setHealth(value); diff --git a/src/net/slipcor/pvparena/classes/PACheck.java b/src/net/slipcor/pvparena/classes/PACheck.java index 925505d48..46df6b529 100644 --- a/src/net/slipcor/pvparena/classes/PACheck.java +++ b/src/net/slipcor/pvparena/classes/PACheck.java @@ -533,8 +533,7 @@ public static void handlePlayerDeath(final Arena arena, ArenaPlayer.parsePlayer(player.getKiller().getName()).getArenaClass().equip(player.getKiller()); } if (!arena.getArenaConfig().getString(CFG.PLAYER_ITEMSONKILL).equals("none")) { - String definition = arena.getArenaConfig().getString(CFG.PLAYER_ITEMSONKILL); - ItemStack[] items = StringParser.getItemStacksFromString(definition); + ItemStack[] items = arena.getArenaConfig().getItems(CFG.PLAYER_ITEMSONKILL); for (ItemStack item : items) { if (item != null) { player.getKiller().getInventory().addItem(item.clone()); diff --git a/src/net/slipcor/pvparena/classes/PAClaimBar.java b/src/net/slipcor/pvparena/classes/PAClaimBar.java index 8b26a240f..49378890c 100644 --- a/src/net/slipcor/pvparena/classes/PAClaimBar.java +++ b/src/net/slipcor/pvparena/classes/PAClaimBar.java @@ -2,7 +2,6 @@ import net.slipcor.pvparena.PVPArena; import net.slipcor.pvparena.arena.Arena; -import net.slipcor.pvparena.arena.ArenaPlayer; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; diff --git a/src/net/slipcor/pvparena/commands/PAA_Class.java b/src/net/slipcor/pvparena/commands/PAA_Class.java index ce90b9220..507232140 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Class.java +++ b/src/net/slipcor/pvparena/commands/PAA_Class.java @@ -69,38 +69,12 @@ public void commit(final Arena arena, final CommandSender sender, final String[] final Player player = (Player) sender; final List items = new ArrayList<>(); - for (final ItemStack is : player.getInventory().getStorageContents()) { - if (is != null) { - items.add(is); - } - } - - final ItemStack[] isItems = new ItemStack[items.size()]; - int position = 0; - for (final ItemStack is : items) { - isItems[position++] = is; - } - - final String sItems = isItems.length < 1 ? "AIR" - : StringParser.getStringFromItemStacks(isItems); - final StringBuilder armor = new StringBuilder(""); - int pos = 0; - for (final ItemStack item : player.getInventory().getArmorContents()) { - armor.append(','); - armor.append(pos++); - armor.append(">>!<<"); - armor.append(StringParser.getStringFromItemStack(item)); - } - if (player.getInventory().getItemInOffHand() != null) { - armor.append(','); - armor.append(0); - armor.append(">>O<<"); - armor.append(StringParser.getStringFromItemStack(player.getInventory().getItemInOffHand())); - } - - arena.getArenaConfig().setManually("classitems." + args[1], sItems + armor); + arena.getArenaConfig().setManually("classitems." + args[1] + ".items", player.getInventory().getStorageContents()); + arena.getArenaConfig().setManually("classitems." + args[1] + ".offhand", new ItemStack[]{player.getInventory().getItemInOffHand()}); + arena.getArenaConfig().setManually("classitems." + args[1] + ".armor", player.getInventory().getArmorContents()); arena.getArenaConfig().save(); - arena.addClass(args[1], StringParser.getItemStacksFromString(sItems), player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents()); + + arena.addClass(args[1], player.getInventory().getStorageContents(), player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents()); Arena.pmsg(player, Language.parse(arena, MSG.CLASS_SAVED, args[1])); } else if ("load".equalsIgnoreCase(args[0])) { final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(sender.getName()); diff --git a/src/net/slipcor/pvparena/commands/PAA_ForceWin.java b/src/net/slipcor/pvparena/commands/PAA_ForceWin.java index f7b9b041e..cb22a6604 100644 --- a/src/net/slipcor/pvparena/commands/PAA_ForceWin.java +++ b/src/net/slipcor/pvparena/commands/PAA_ForceWin.java @@ -55,7 +55,8 @@ public void commit(final Arena arena, final CommandSender sender, final String[] for (final ArenaPlayer ap : team.getTeamMembers()) { if (ap.getStatus() == ArenaPlayer.Status.FIGHT) { ap.get().getWorld().strikeLightningEffect(ap.get().getLocation()); - final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf((double) 10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, -0.0D))); + final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, + 10.0); PlayerListener.finallyKillPlayer(arena, ap.get(), e); } } @@ -74,7 +75,8 @@ public void commit(final Arena arena, final CommandSender sender, final String[] } if (ap.getStatus() == ArenaPlayer.Status.FIGHT) { ap.get().getWorld().strikeLightningEffect(ap.get().getLocation()); - final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf((double) 10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, -0.0D))); + final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, + 10.0); PlayerListener.finallyKillPlayer(arena, ap.get(), e); } } @@ -87,7 +89,8 @@ public void commit(final Arena arena, final CommandSender sender, final String[] for (final ArenaPlayer ap : team.getTeamMembers()) { if (ap.getStatus() == ArenaPlayer.Status.FIGHT) { ap.get().getWorld().strikeLightningEffect(ap.get().getLocation()); - final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf((double) 10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, -0.0D))); + final EntityDamageEvent e = new EntityDamageEvent(ap.get(), EntityDamageEvent.DamageCause.LIGHTNING, + 10.0); PlayerListener.finallyKillPlayer(arena, ap.get(), e); } } diff --git a/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java b/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java index c57d1b44e..89a3b812e 100644 --- a/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java +++ b/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java @@ -66,40 +66,13 @@ public void commit(final Arena arena, final CommandSender sender, final String[] final Player player = (Player) sender; if ("save".equalsIgnoreCase(args[0])) { - final List items = new ArrayList<>(); - for (final ItemStack is : player.getInventory().getStorageContents()) { - if (is != null) { - items.add(is); - } - } - - final ItemStack[] isItems = new ItemStack[items.size()]; - int position = 0; - for (final ItemStack is : items) { - isItems[position++] = is; - } - - final String sItems = isItems.length < 1 ? "AIR" - : StringParser.getStringFromItemStacks(isItems); - final StringBuilder armor = new StringBuilder(""); - int pos = 0; - for (final ItemStack item : player.getInventory().getArmorContents()) { - armor.append(','); - armor.append(pos++); - armor.append(">>!<<"); - armor.append(StringParser.getStringFromItemStack(item)); - } - if (player.getInventory().getItemInOffHand() != null) { - armor.append(','); - armor.append(0); - armor.append(">>O<<"); - armor.append(StringParser.getStringFromItemStack(player.getInventory().getItemInOffHand())); - } - - arena.getArenaConfig().setManually("classitems." + className, sItems + armor); + arena.getArenaConfig().setManually("classitems." + className + ".items", player.getInventory().getStorageContents()); + arena.getArenaConfig().setManually("classitems." + className + ".offhand", new ItemStack[]{player.getInventory().getItemInOffHand()}); + arena.getArenaConfig().setManually("classitems." + className + ".armor", player.getInventory().getArmorContents()); arena.getArenaConfig().save(); - arena.addClass(className, isItems, player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents()); + + arena.addClass(className, player.getInventory().getStorageContents(), player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents()); Arena.pmsg(player, Language.parse(arena, MSG.CLASS_SAVED, className)); } else if ("remove".equalsIgnoreCase(args[0])) { diff --git a/src/net/slipcor/pvparena/commands/PAA_Set.java b/src/net/slipcor/pvparena/commands/PAA_Set.java index c0d907df4..f8ca35cef 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Set.java +++ b/src/net/slipcor/pvparena/commands/PAA_Set.java @@ -167,7 +167,7 @@ private void set(final CommandSender player, final Arena arena, final String nod if ("hand".equals(value)) { if (player instanceof Player) { - String itemDefinition = StringParser.getStringFromItemStack(((Player) player).getEquipment().getItemInMainHand()); + String itemDefinition = ((Player) player).getEquipment().getItemInMainHand().getType().name(); arena.getArenaConfig().setManually(node, itemDefinition); arena.msg( player, @@ -200,12 +200,11 @@ private void set(final CommandSender player, final Arena arena, final String nod if ("hand".equals(value)) { if (player instanceof Player) { - String itemDefinition = StringParser.getStringFromItemStack(((Player) player).getEquipment().getItemInMainHand()); - arena.getArenaConfig().setManually(node, itemDefinition); + ItemStack[] items = new ItemStack[]{(((Player) player).getEquipment().getItemInMainHand())}; + arena.getArenaConfig().setManually(node, items); arena.msg( player, - Language.parse(arena, MSG.SET_DONE, node, - itemDefinition)); + Language.parse(arena, MSG.SET_DONE, node, items[0].getType().name())); } else { arena.msg(player, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS)); } @@ -214,36 +213,18 @@ private void set(final CommandSender player, final Arena arena, final String nod if ("inventory".equals(value)) { if (player instanceof Player) { - final String newValue = StringParser.getStringFromItemStacks(((Player) player).getInventory().getContents()); - arena.getArenaConfig().setManually(node, newValue); + final ItemStack[] items = ((Player) player).getInventory().getContents(); + arena.getArenaConfig().setManually(node, items); arena.msg( player, - Language.parse(arena, MSG.SET_DONE, node, - newValue)); + Language.parse(arena, MSG.SET_DONE, node, "inventory")); arena.getArenaConfig().save(); } else { arena.msg(player, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS)); } return; } - - final String[] split = value.split(","); - final ItemStack[] items = new ItemStack[split.length]; - - for (int i = 0; i < split.length; i++) { - items[i] = StringParser.getItemStackFromString(split[i]); - if (items[i] == null) { - arena.msg(player, Language.parse(arena, MSG.ERROR_ARGUMENT_TYPE, String.valueOf(items[i]), - "item")); - return; - } - } - - arena.getArenaConfig().setManually(node, String.valueOf(value)); - arena.msg( - player, - Language.parse(arena, MSG.SET_DONE, node, - String.valueOf(value))); + arena.msg(player, Language.parse(arena, MSG.SET_ITEMS_NOT)); } else { arena.msg( player, diff --git a/src/net/slipcor/pvparena/commands/PAA_Setup.java b/src/net/slipcor/pvparena/commands/PAA_Setup.java index ea6277f83..0f1b35d82 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Setup.java +++ b/src/net/slipcor/pvparena/commands/PAA_Setup.java @@ -15,7 +15,6 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; -import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -75,15 +74,15 @@ public void displayHelp(final CommandSender sender) { public static void chat(final Player player, final String message) { final Arena arena = activeSetups.get(player.getName()); - /** - * help | ? - * - * show [region|spawn|block] | display a region/spawn/block with wool blocks", - * region [region] move 2 up | move region [region] 2 blocks up", - * region [region] expand 10 north | expand region [region] 10 block to the north", - * region [region] expand 15 | expand region [region] 15 blocks in all directions", - * all arguments can be abbreviated, e.g. 'r' = 'region', 'e' = 'expand', 'm' = 'move'", - * done | exit setup mode", + /* + help | ? + + show [region|spawn|block] | display a region/spawn/block with wool blocks", + region [region] move 2 up | move region [region] 2 blocks up", + region [region] expand 10 north | expand region [region] 10 block to the north", + region [region] expand 15 | expand region [region] 15 blocks in all directions", + all arguments can be abbreviated, e.g. 'r' = 'region', 'e' = 'expand', 'm' = 'move'", + done | exit setup mode", */ if (message.length() < 1) { return; @@ -108,7 +107,7 @@ class Remover implements Runnable { @Override public void run() { - player.sendBlockChange(location, location.getBlock().getType(), location.getBlock().getData()); + player.sendBlockChange(location, location.getBlock().getType().createBlockData()); } } @@ -141,10 +140,10 @@ public void run() { } } } else if (word[0].startsWith("r")) { - /** - * region [region] move 2 up | move region [region] 2 blocks up", - * region [region] expand 10 north | expand region [region] 10 block to the north", - * region [region] expand 15 out | expand region [region] 15 blocks in all directions", + /* + region [region] move 2 up | move region [region] 2 blocks up", + region [region] expand 10 north | expand region [region] 10 block to the north", + region [region] expand 15 out | expand region [region] 15 blocks in all directions", */ if (word.length == 5) { final ArenaRegion region = arena.getRegion(word[1]); diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index 051e3f4f8..a6a846e54 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -74,16 +74,16 @@ public enum CFG { GENERAL_SMARTSPAWN("general.smartspawn", false, null), GENERAL_TIME("general.time", -1, null), GENERAL_TYPE("general.type", "none", null), - GENERAL_WAND("general.wand", Material.STICK.name(), false, null), + GENERAL_WAND("general.wand", new ItemStack[]{new ItemStack(Material.STICK)}, false, null), GOAL_ADDLIVESPERPLAYER("goal.livesPerPlayer", false, null), - ITEMS_EXCLUDEFROMDROPS("items.excludeFromDrops", "none", true, null), - ITEMS_KEEPONRESPAWN("items.keepOnRespawn", "none", true, null), + ITEMS_EXCLUDEFROMDROPS("items.excludeFromDrops", new ItemStack[0], true, null), + ITEMS_KEEPONRESPAWN("items.keepOnRespawn", new ItemStack[0], true, null), ITEMS_MINPLAYERS("items.minplayers", 2, null), ITEMS_RANDOM("items.random", true, null), - ITEMS_REWARDS("items.rewards", "none", true, null), - ITEMS_TAKEOUTOFGAME("items.takeOutOfGame", "none", true, null), + ITEMS_REWARDS("items.rewards", new ItemStack[0], true, null), + ITEMS_TAKEOUTOFGAME("items.takeOutOfGame", new ItemStack[0], true, null), JOIN_RANGE("join.range", 0, null), JOIN_FORCE("join.forceregionjoin", false, null), @@ -124,7 +124,7 @@ public enum CFG { PLAYER_HEALTH("player.health", -1, null), PLAYER_HEALFORKILL("player.healforkill", false, null), PLAYER_HUNGER("player.hunger", true, null), - PLAYER_ITEMSONKILL("player.itemsonkill", "none", true, null), + PLAYER_ITEMSONKILL("player.itemsonkill", new ItemStack[0], true, null), PLAYER_MAYCHANGEARMOR("player.mayChangeArmor", true, null), PLAYER_MAXHEALTH("player.maxhealth", -1, null), PLAYER_PREVENTDEATH("player.preventDeath", true, null), @@ -140,7 +140,7 @@ public enum CFG { PROTECT_SPAWN("protection.spawn", 0, null), READY_AUTOCLASS("ready.autoClass", "none", null), - READY_BLOCK("ready.block", Material.IRON_BLOCK.name(), false, null), + READY_BLOCK("ready.block", new ItemStack[]{new ItemStack(Material.IRON_BLOCK)}, false, null), READY_CHECKEACHPLAYER("ready.checkEachPlayer", false, null), READY_CHECKEACHTEAM("ready.checkEachTeam", true, null), READY_ENFORCECOUNTDOWN("ready.enforceCountdown", false, null), @@ -190,7 +190,7 @@ public enum CFG { GOAL_BEACONS_TICKINTERVAL("goal.beacons.tickinterval", 60, "Beacons"), GOAL_BEACONS_TICKREWARD("goal.beacons.tickreward", 1, "Beacons"), - GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", "IRON_BLOCK", false, "BlockDestroy"), + GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", new ItemStack[]{new ItemStack(Material.IRON_BLOCK)}, false, "BlockDestroy"), GOAL_BLOCKDESTROY_LIVES("goal.blockdestroy.bdlives", 1, "BlockDestroy"), GOAL_CHECKPOINTS_CLAIMRANGE("goal.checkpoints.cpclaimrange", 5, "CheckPoints"), @@ -206,7 +206,7 @@ public enum CFG { GOAL_DOM_TICKINTERVAL("goal.dom.tickinterval", 60, "Domination"), GOAL_DOM_TICKREWARD("goal.dom.tickreward", 1, "Domination"), - GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", "WOOL", false, "Flags"), + GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", new ItemStack[]{new ItemStack(Material.WHITE_WOOL)}, false, "Flags"), GOAL_FLAGS_LIVES("goal.flags.flives", 3, "Flags"), GOAL_FLAGS_MUSTBESAFE("goal.flags.mustBeSafe", true, "Flags"), GOAL_FLAGS_WOOLFLAGHEAD("goal.flags.woolFlagHead", true, "Flags"), @@ -227,7 +227,7 @@ public enum CFG { GOAL_PLIVES_LIVES("goal.playerlives.plives", 3, "PlayerLives"), GOAL_TANK_LIVES("goal.tank.tlives", 1, "Tank"), GOAL_TDC_LIVES("goal.teamdc.tdclives", 10, "TeamDeathConfirm"), - GOAL_TDC_ITEM("goal.teamdc.tdcitem", "WOOL", false, "TeamDeathConfirm"), + GOAL_TDC_ITEM("goal.teamdc.tdcitem", new ItemStack[]{new ItemStack(Material.WHITE_WOOL)}, false, "TeamDeathConfirm"), GOAL_TDM_LIVES("goal.teamdm.tdlives", 10, "TeamDeathMatch"), GOAL_TDM_SUICIDESCORE("goal.teamdm.suicideScore", false, "TeamDeathMatch"), GOAL_TLIVES_LIVES("goal.teamlives.tlives", 10, "TeamLives"), @@ -304,13 +304,34 @@ public enum CFG { MODULES_BLOCKRESTORE_RESTORECHESTS("modules.blockrestore.restorechests", false, "BlockRestore"), MODULES_BLOCKDISSOLVE_CALCOFFSET("modules.blockdissolve.calcoffset", 0.333, "BlockDissolve"), - MODULES_BLOCKDISSOLVE_MATERIALS("modules.blockdissolve.materials", "SNOW,WOOL", true, "BlockDissolve"), + MODULES_BLOCKDISSOLVE_MATERIALS("modules.blockdissolve.materials", new ItemStack[]{ + new ItemStack(Material.SNOW_BLOCK, 1), + + new ItemStack(Material.BLACK_WOOL, 1), + new ItemStack(Material.BLUE_WOOL, 1), + new ItemStack(Material.CYAN_WOOL, 1), + new ItemStack(Material.BROWN_WOOL, 1), + + new ItemStack(Material.GRAY_WOOL, 1), + new ItemStack(Material.GREEN_WOOL, 1), + new ItemStack(Material.LIGHT_BLUE_WOOL, 1), + new ItemStack(Material.LIGHT_GRAY_WOOL, 1), + + new ItemStack(Material.LIME_WOOL, 1), + new ItemStack(Material.MAGENTA_WOOL, 1), + new ItemStack(Material.ORANGE_WOOL, 1), + new ItemStack(Material.RED_WOOL, 1), + + new ItemStack(Material.PINK_WOOL, 1), + new ItemStack(Material.PURPLE_WOOL, 1), + new ItemStack(Material.YELLOW_WOOL, 1), + new ItemStack(Material.WHITE_WOOL, 1)}, true, "BlockDissolve"), MODULES_BLOCKDISSOLVE_STARTSECONDS("modules.blockdissolve.startseconds", 10, "BlockDissolve"), MODULES_BLOCKDISSOLVE_TICKS("modules.blockdissolve.ticks", 40, "BlockDissolve"), MODULES_CHESTFILLER_CHESTLOCATION("modules.chestfiller.chestlocation", "none", "ChestFiller"), MODULES_CHESTFILLER_CLEAR("modules.chestfiller.clear", false, "ChestFiller"), - MODULES_CHESTFILLER_ITEMS("modules.chestfiller.cfitems", "1", true, "ChestFiller"), + MODULES_CHESTFILLER_ITEMS("modules.chestfiller.cfitems", new ItemStack[]{new ItemStack(Material.STONE)}, true, "ChestFiller"), MODULES_CHESTFILLER_MAXITEMS("modules.chestfiller.cfmaxitems", 5, "ChestFiller"), MODULES_CHESTFILLER_MINITEMS("modules.chestfiller.cfminitems", 0, "ChestFiller"), @@ -323,7 +344,7 @@ public enum CFG { MODULES_FIXINVENTORYLOSS_INVENTORY("modules.fixinventoryloss.inventory", false, "FixInventoryLoss"), MODULES_ITEMS_INTERVAL("modules.items.interval", 0, "Items"), - MODULES_ITEMS_ITEMS("modules.items.items", "none", true, "Items"), + MODULES_ITEMS_ITEMS("modules.items.items", new ItemStack[0], true, "Items"), MODULES_RESPAWNRELAY_INTERVAL("modules.respawnrelay.respawnseconds", 10, "RespawnRelay"), MODULES_RESPAWNRELAY_CHOOSESPAWN("modules.respawnrelay.choosespawn", false, "RespawnRelay"), @@ -386,7 +407,7 @@ public enum CFG { MODULES_VAULT_REWARD_TRIGGER("modules.vault.reward.trigger", 0.0d, "Vault"), MODULES_VAULT_REWARD_WIN("modules.vault.reward.playerWin", 0.0d, "Vault"), - MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", "SAND", false, "Walls"), + MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", new ItemStack[]{new ItemStack(Material.SAND, 1)}, false, "Walls"), MODULES_WALLS_SCOREBOARDCOUNTDOWN("modules.walls.scoreboardcountdown", false, "Walls"), MODULES_WALLS_SECONDS("modules.walls.wallseconds", 300, "Walls"), @@ -438,7 +459,7 @@ public static CFG getByNode(final String node) { module = source; } - CFG(final String node, final String value, final boolean multiple, final String source) { + CFG(final String node, final ItemStack[] value, final boolean multiple, final String source) { this.node = node; this.value = value; type = multiple ? "items" : "material"; @@ -736,16 +757,8 @@ public Material getMaterial(final CFG cfg, final Material def) { } public ItemStack[] getItems(final CFG cfg) { - return getItems(cfg, StringParser.getItemStacksFromString((String) cfg.getValue())); - } - - public ItemStack[] getItems(final CFG cfg, final ItemStack[] def) { final String path = cfg.getNode(); - final String result = strings.get(path); - if (result == null || "none".equals(result)) { - return def; - } - return StringParser.getItemStacksFromString(result); + return this.cfg.getList(path).toArray(new ItemStack[0]); } public Set getKeys(final String path) { diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 147377e4b..17e42efe1 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -410,6 +410,7 @@ public enum MSG { SET_DONE("nulang.set.done", "&a%1%&r set to &e%2%&r!"), SET_HELP("nulang.set.help", "Use /pa {arenaname} set [page] to get a node list."), SET_UNKNOWN("nulang.set.unknown", "Unknown node: &e%1%&r!"), + SET_ITEMS_NOT("nulang.set.items_not", "Please use either hand or inventory to set an item node!"), SETOWNER_DONE("nulang.setowner.done", "&a%1%&r is now owner of arena &a%2%&r!"), diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index 459c47a4f..938e70f63 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -4,7 +4,6 @@ import org.bukkit.*; import org.bukkit.block.BlockFace; import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.*; import org.bukkit.potion.PotionData; @@ -26,9 +25,6 @@ */ public final class StringParser { - private static final String SAFE_BREAK = ""; - private static final String SAFE_PAGE_BREAK = ""; - private static final String SAFE_LORE_BREAK = ""; private static final Debug DEBUG = new Debug(17); @@ -40,31 +36,6 @@ private StringParser() { public static final Set negative = new HashSet<>(Arrays.asList( "no", "off", "false", "0")); - private static String codeCharacters(final String string, final boolean forward) { - final Map findReplace = new HashMap<>(); - String result = string; - if (forward) { - findReplace.put(":", "<>"); - findReplace.put("~", "<>"); - findReplace.put("|", "<>"); - findReplace.put(",", "<>"); - findReplace.put(ChatColor.COLOR_CHAR + "", "&"); - } else { - findReplace.put("<>", ":"); - findReplace.put("<>", "~"); - findReplace.put("<>", "|"); - findReplace.put("<>", ","); - result = ChatColor.translateAlternateColorCodes('&', result); - result = ChatColor.translateAlternateColorCodes('?', result); - } - - for (final Map.Entry stringStringEntry : findReplace.entrySet()) { - result = result.replace(stringStringEntry.getKey(), stringStringEntry.getValue()); - } - - return result; - } - public static String colorize(final String string) { return ChatColor.translateAlternateColorCodes('&', string) .replace("&&", "&").replace("%%&%%", "&"); @@ -159,456 +130,6 @@ public static ChatColor getChatColorFromWoolEnum(final String color) { return ChatColor.valueOf(parseDyeColorToChatColor(color, true)); } - /** - * construct an itemstack out of a string - * - * @param string the formatted string: [itemid/name][~[dmg]]~[data]:[amount] - * @return the itemstack - */ - public static ItemStack getItemStackFromString(final String string) { - DEBUG.i("parsing itemstack string: " + string); - - // [itemid/name]~[dmg]|[enchantmentID]~level:[amount] - - - String[] temp = string.split(":"); - - String prefix = null; - - for (final String s : PVPArena.instance.getConfig().getStringList("materialprefixes")) { - if (string.startsWith(prefix+ ':')) { - prefix = s; - temp = string.substring(prefix.length()).split(":"); - } - } - - if (temp[0].startsWith("0>>O<<")) { - temp[0] = temp[0].substring(6); - } - - String desc = null; - int amount = 1; - if (temp.length > 1) { - try { - amount = Integer.parseInt(temp[1]); - } catch (final NumberFormatException e) { - PVPArena.instance.getLogger().severe("Material error. Maybe add " + temp[0] + " to materialprefixes?"); - return new ItemStack(Material.AIR); - } - if (temp.length > 2) { - desc = temp[2]; - } - } - - final Map enchants = new HashMap<>(); - if (temp[0].contains("|")) { - DEBUG.i("trying to add enchantment"); - final String[] temp2 = temp[0].split("\\|"); - DEBUG.i("temp2 length: " + temp2.length); - temp[0] = temp2[0]; - - DEBUG.i("correcting item temp to " + temp[0]); - - for (int i = 1; i < temp2.length; i++) { - - final String strEnch = temp2[i]; - if (strEnch.contains("~")) { - final String[] arrEnch = strEnch.split("~"); - final Enchantment ench = Enchantment.getByKey(NamespacedKey.minecraft(arrEnch[0])); - final Integer enchLevel = Integer.parseInt(arrEnch[1]); - DEBUG.i("adding enchantment " + ench.getName() + " lvl " - + enchLevel); - enchants.put(ench, enchLevel); - } - } - } - - temp = temp[0].split("~"); - - final Material mat = parseMat(prefix == null ? temp[0] : prefix + ':' + temp[0]); - if (mat != null) { - if (temp.length == 1) { - // [itemid/name]:[amount] - - final ItemStack itemStack = new ItemStack(mat, amount); - for (final Map.Entry enchantmentIntegerEntry : enchants.entrySet()) { - DEBUG.i("processing enchantment " + enchantmentIntegerEntry.getKey().getName()); - itemStack.addUnsafeEnchantment(enchantmentIntegerEntry.getKey(), enchantmentIntegerEntry.getValue()); - } - - if (desc != null) { - final ItemMeta meta = itemStack.getItemMeta(); - meta.setDisplayName(codeCharacters(desc, false)); - itemStack.setItemMeta(meta); - } - - return itemStack; - } - final short dmg = Short.parseShort(temp[1]); - if (temp.length == 2) { - // [itemid/name]~[dmg]:[amount] - final ItemStack itemStack = new ItemStack(mat, amount, dmg); - for (final Map.Entry enchantmentIntegerEntry : enchants.entrySet()) { - itemStack.addUnsafeEnchantment(enchantmentIntegerEntry.getKey(), enchantmentIntegerEntry.getValue()); - } - - if (desc != null) { - final ItemMeta meta = itemStack.getItemMeta(); - meta.setDisplayName(codeCharacters(desc, false)); - itemStack.setItemMeta(meta); - } - - return itemStack; - } - // string: POTION~0~INVISIBILITYx0x300~Duration 15 seconds.:2:Stealth - - // ---> split(":"); - - // temp[0] = POTION~0~INVISIBILITYx0x300~Duration 15 seconds. - // temp[1] = 2 - // temp[2] = Stealth - - // ---> split("~"); - - // temp[0] = POTION - // temp[1] = 0 - // temp[2] = INVISIBILITYx0x300 - // temp[3] = Duration 15 seconds. - - final int location; - - if (temp.length > 3 && temp[3].contains(SAFE_LORE_BREAK)) { - location = 3; - } else { - location = 2; - } - - final String[] dataSplit = temp[location].split(SAFE_LORE_BREAK); - String data = dataSplit[0]; - if (temp[2].contains(SAFE_BREAK)) { - if (hasPotionMeta(mat)) { - data = temp[2]; - } else { - data = temp[2].split(SAFE_BREAK)[0]; - } - } - - if (mat == Material.WRITTEN_BOOK) { - data = temp[2]; - } - - /** - * - private static final String SAFE_BREAK = ""; - private static final String SAFE_PAGE_BREAK = ""; - private static final String SAFE_LORE_BREAK = ""; - * - */ - - final String lore = dataSplit.length > 1 ? dataSplit[1] : null; - - if (temp.length >= 3) { - // [itemid/name]~[dmg]~[data]:[amount] - final ItemStack itemStack = new ItemStack(mat, amount, dmg); - - - if (desc != null) { - final ItemMeta meta = itemStack.getItemMeta(); - meta.setDisplayName(codeCharacters(desc, false)); - itemStack.setItemMeta(meta); - } - - if (mat == Material.WRITTEN_BOOK - || mat == Material.WRITABLE_BOOK) { - final BookMeta bookMeta = (BookMeta) itemStack.getItemMeta(); - try { - final String[] outer = data.split(SAFE_BREAK); - bookMeta.setAuthor(codeCharacters(outer[0], false)); - bookMeta.setTitle(codeCharacters(outer[1], false)); - final List pages = new ArrayList<>(); - final String[] inner = codeCharacters(outer[2], false).split( - SAFE_PAGE_BREAK); - Collections.addAll(pages, inner); - bookMeta.setPages(pages); - itemStack.setItemMeta(bookMeta); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning( - "invalid book data: " + data); - return itemStack; - } - } else if (itemStack.getType().name().startsWith("LEATHER_")) { - try { - final LeatherArmorMeta leatherMeta = (LeatherArmorMeta) itemStack - .getItemMeta(); - leatherMeta.setColor(Color.fromRGB(Integer.parseInt(data))); - itemStack.setItemMeta(leatherMeta); - } catch (final Exception e) { - DEBUG.i( - "invalid leather data: " + data); - return itemStack; - } - } else if (itemStack.getType() == Material.PLAYER_HEAD) { - try { - final SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); - skullMeta.setOwner(data); - itemStack.setItemMeta(skullMeta); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning( - "invalid skull data: " + data); - return itemStack; - } - } else if (hasPotionMeta(itemStack)) { - // data = NAMEx1x100NAMEx2x100 - // 1.9+ = NEWNAMEXtrueXtrueNAMEx1x100NAMEx2x100 - try { - final PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); - - final String[] defs = data.split(SAFE_BREAK); - - defs: for (final String def : defs) { - if (def.contains("X")) { - String[] vals = def.split("X"); - for (PotionType type : PotionType.values()) { - if (type == null || type.getEffectType() == null) { - continue; - } - if (vals[0].equals(type.getEffectType().getName())) { - PotionData pData = new PotionData(type, StringParser.positive.contains(vals[1]), StringParser.positive.contains(vals[2])); - potionMeta.setBasePotionData(pData); - continue defs; - } - } - PVPArena.instance.getLogger().warning("Invalid base potion data: "+def); - } - final String[] vals = def.split("x"); - potionMeta.addCustomEffect( - new PotionEffect( - PotionEffectType.getByName(vals[0]), - Integer.parseInt(vals[2]), - Integer.parseInt(vals[1])), true); - } - - if (lore != null - && !(mat == Material.WRITTEN_BOOK || mat == Material.WRITABLE_BOOK)) { - final List lLore = new ArrayList<>(); - for (final String line : lore.split(SAFE_BREAK)) { - lLore.add(codeCharacters(line, false)); - } - potionMeta.setLore(lLore); - } - - itemStack.setItemMeta(potionMeta); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning( - "invalid potion data: " + data); - e.printStackTrace(); - return itemStack; - } - } else { - DEBUG.i("data not available for: " + mat.name()); - } - - if (lore != null - && !(mat == Material.WRITTEN_BOOK || mat == Material.WRITABLE_BOOK)) { - final List lLore = new ArrayList<>(); - for (final String line : lore.split(SAFE_BREAK)) { - lLore.add(codeCharacters(line, false)); - } - final ItemMeta itemMeta = itemStack.getItemMeta(); - itemMeta.setLore(lLore); - itemStack.setItemMeta(itemMeta); - } - - for (final Map.Entry enchantmentIntegerEntry : enchants.entrySet()) { - itemStack.addUnsafeEnchantment(enchantmentIntegerEntry.getKey(), enchantmentIntegerEntry.getValue()); - } - - return itemStack; - } - } - return null; - } - - private static boolean hasPotionMeta(ItemStack itemStack) { - if (itemStack == null) { - return false; - } - if (itemStack.getItemMeta() instanceof PotionMeta) { - return true; - } - Material mat = itemStack.getType(); - return hasPotionMeta(mat); - } - - private static boolean hasPotionMeta(Material mat) { - return mat == Material.POTION || mat == Material.SPLASH_POTION || mat == Material.LINGERING_POTION || mat == Material.TIPPED_ARROW; - } - - public static ItemStack[] getItemStacksFromString(final String string) { - if ("none".equals(string)) { - return new ItemStack[0]; - } - - final String[] args = string.split(","); - - final ItemStack[] result = new ItemStack[args.length]; - - int pos = 0; - - for (final String s : args) { - result[pos++] = getItemStackFromString(s); - } - - return result; - } - - public static String getStringFromItemStacks(final ItemStack[] isItems) { - if (isItems == null) { - return "AIR"; - } - final String[] split = new String[isItems.length]; - - int pos = 0; - - for (final ItemStack is : isItems) { - split[pos++] = getStringFromItemStack(is); - } - - return joinArray(trimAir(split), ","); - } - - private static String[] trimAir(final String[] sArray) { - final List list = new ArrayList<>(); - for (final String item : sArray) { - if ("AIR".equals(item)) { - continue; - } - list.add(item); - } - - if (list.size() < 1) { - return new String[]{"AIR"}; - } - - final String[] result = new String[list.size()]; - int pos = 0; - for (final String item : list) { - result[pos++] = item; - } - - return result; - } - - public static String getStringFromItemStack(final ItemStack itemStack) { - if (itemStack == null || itemStack.getType() == Material.AIR) { - return "AIR"; - } - final StringBuilder temp = new StringBuilder(itemStack.getType().name()); - boolean durability = false; - if (itemStack.getDurability() != 0) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - if (itemStack.getType() == Material.WRITTEN_BOOK - || itemStack.getType() == Material.WRITABLE_BOOK) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - final BookMeta bookMeta = (BookMeta) itemStack.getItemMeta(); - if (bookMeta != null && bookMeta.getAuthor() != null && bookMeta.getTitle() != null - && bookMeta.getPages() != null) { - temp.append('~'); - temp.append(codeCharacters(bookMeta.getAuthor(), true)); - temp.append(SAFE_BREAK); - temp.append(codeCharacters(bookMeta.getTitle(), true)); - temp.append(SAFE_BREAK); - temp.append(codeCharacters( - joinArray(bookMeta.getPages().toArray(), - SAFE_PAGE_BREAK), true)); - - } - } else if (itemStack.getType().name().startsWith("LEATHER_")) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - final LeatherArmorMeta leatherMeta = (LeatherArmorMeta) itemStack.getItemMeta(); - temp.append('~'); - temp.append(leatherMeta.getColor().asRGB()); - } else if (itemStack.getType() == Material.PLAYER_HEAD) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - final SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); - temp.append('~'); - temp.append(skullMeta.getOwner()); - } else if (hasPotionMeta(itemStack)) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - final PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); - temp.append('~'); - PotionData pData = potionMeta.getBasePotionData(); - try { - temp.append(pData.getType().getEffectType().getName()).append('X').append(pData.isExtended()).append('X').append(pData.isUpgraded()); - temp.append(SAFE_BREAK); - } catch (Exception e) { - } - for (final PotionEffect pe : potionMeta.getCustomEffects()) { - temp.append(pe.getType().getName()).append('x').append(pe.getAmplifier()).append('x').append(pe.getDuration()); - temp.append(SAFE_BREAK); - } - } - - if (itemStack.hasItemMeta() && itemStack.getItemMeta().hasLore()) { - if (!durability) { - temp.append('~'); - temp.append(itemStack.getDurability()); - durability = true; - } - - temp.append('~'); - temp.append(SAFE_LORE_BREAK); - temp.append(codeCharacters( - joinArray(itemStack.getItemMeta().getLore() - .toArray(), SAFE_BREAK), true)); - } - Map enchants = null; - try { - enchants = itemStack.getEnchantments(); - } catch (Exception e) { - // Caused by: java.lang.NullPointerException: null key in entry: null=1 - } - - if (enchants != null && !enchants.isEmpty()) { - for (final Map.Entry enchantmentIntegerEntry : enchants.entrySet()) { - temp.append('|'); - temp.append(enchantmentIntegerEntry.getKey().getKey().getKey()); - temp.append('~'); - temp.append(enchantmentIntegerEntry.getValue()); - } - } - - if (itemStack.getAmount() > 1 || itemStack.getItemMeta().hasDisplayName()) { - temp.append(':'); - temp.append(itemStack.getAmount()); - } - - if (itemStack.getItemMeta().hasDisplayName()) { - temp.append(':'); - temp.append(codeCharacters(itemStack.getItemMeta().getDisplayName(), true)); - } - - return temp.toString().replace(ChatColor.COLOR_CHAR, '&'); - } private static String getWoolEnumFromChatColorEnum(final String color) { return parseDyeColorToChatColor(color, false); @@ -624,48 +145,6 @@ public static Material getWoolFallbackMaterialFromString(final String color) { return Material.BROWN_WOOL; } - public static Material getWoolMaterialFromChatColor(final ChatColor color) { - /* - Unsupported: - ChatColor.AQUA - Material.BROWN_WOOL - */ - - switch (color) { - case BLACK: - return Material.BLACK_WOOL; - case DARK_BLUE: - return Material.BLUE_WOOL; - case DARK_GREEN: - return Material.GREEN_WOOL; - case DARK_AQUA: - return Material.CYAN_WOOL; - case DARK_RED: - return Material.RED_WOOL; - case DARK_PURPLE: - return Material.PURPLE_WOOL; - case GOLD: - return Material.ORANGE_WOOL; - case GRAY: - return Material.LIGHT_GRAY_WOOL; - case DARK_GRAY: - return Material.GRAY_WOOL; - case BLUE: - return Material.LIGHT_BLUE_WOOL; - case GREEN: - return Material.LIME_WOOL; - case RED: - return Material.PINK_WOOL; - case LIGHT_PURPLE: - return Material.MAGENTA_WOOL; - case YELLOW: - return Material.YELLOW_WOOL; - case WHITE: - default: - return Material.WHITE_WOOL; - } - } - public static String joinArray(final Object[] array, final String glue) { final StringBuilder result = new StringBuilder(""); for (final Object o : array) { @@ -704,20 +183,18 @@ public static String joinSet(final Set set, final String glue) { private static String parseDyeColorToChatColor(final String color, final boolean forward) { - /** - * wool colors: ORANGE, MAGENTA, LIGHT_BLUE, LIME, PINK, GRAY, SILVER, - * PURPLE, BLUE, GREEN, RED, CYAN; - * - * chat colors: GOLD, LIGHT_PURPLE, BLUE, GREEN, RED, DARK_GRAY, GRAY, - * DARK_PURPLE, DARK_BLUE, DARK_GREEN, DARK_RED, DARK_AQUA - * - * - * - * both colors (ignore): WHITE, YELLOW, BLACK - * - * colors not being able to parse: - * - * chat-AQUA, wool-brown + /* + wool colors: ORANGE, MAGENTA, LIGHT_BLUE, LIME, PINK, GRAY, SILVER, + PURPLE, BLUE, GREEN, RED, CYAN; + + chat colors: GOLD, LIGHT_PURPLE, BLUE, GREEN, RED, DARK_GRAY, GRAY, + DARK_PURPLE, DARK_BLUE, DARK_GREEN, DARK_RED, DARK_AQUA + + both colors (ignore): WHITE, YELLOW, BLACK + + colors not being able to parse: + + chat-AQUA, wool-brown */ final String[] wool = {"ORANGE", "MAGENTA", "LIGHT_BLUE", "LIME", "PINK", "GRAY", "SILVER", "PURPLE", "BLUE", @@ -744,22 +221,6 @@ private static String parseDyeColorToChatColor(final String color, final boolean return color; } - /** - * retrieve a material from a string - * - * @param string the string to parse - * @return the material - */ - private static Material parseMat(final String string) { - DEBUG.i("parsing material: " + string); - Material mat = Material.getMaterial(string); - if (mat == null) { - PVPArena.instance.getLogger().warning( - "unrecognized material: " + string); - } - return mat; - } - public static String[] shiftArrayBy(final String[] args, final int offset) { final String[] newArgs = new String[args.length - offset]; System.arraycopy(args, offset, newArgs, 0, args.length - offset); diff --git a/src/net/slipcor/pvparena/core/Utils.java b/src/net/slipcor/pvparena/core/Utils.java new file mode 100644 index 000000000..f14045cbf --- /dev/null +++ b/src/net/slipcor/pvparena/core/Utils.java @@ -0,0 +1,73 @@ +package net.slipcor.pvparena.core; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +public final class Utils { + private Utils() { + } + + public static ItemStack[] getItemStacksFromMaterials(Material... mats) { + ItemStack[] result = new ItemStack[mats.length]; + for (int i=0; i< mats.length; i++) { + result[i] = new ItemStack(mats[i], mats[i]==Material.ARROW?64:1); + } + return result; + } + + public static Material getWoolMaterialFromChatColor(final ChatColor color) { + /* + Unsupported: + ChatColor.AQUA + Material.BROWN_WOOL + */ + + switch (color) { + case BLACK: + return Material.BLACK_WOOL; + case DARK_BLUE: + return Material.BLUE_WOOL; + case DARK_GREEN: + return Material.GREEN_WOOL; + case DARK_AQUA: + return Material.CYAN_WOOL; + case DARK_RED: + return Material.RED_WOOL; + case DARK_PURPLE: + return Material.PURPLE_WOOL; + case GOLD: + return Material.ORANGE_WOOL; + case GRAY: + return Material.LIGHT_GRAY_WOOL; + case DARK_GRAY: + return Material.GRAY_WOOL; + case BLUE: + return Material.LIGHT_BLUE_WOOL; + case GREEN: + return Material.LIME_WOOL; + case RED: + return Material.PINK_WOOL; + case LIGHT_PURPLE: + return Material.MAGENTA_WOOL; + case YELLOW: + return Material.YELLOW_WOOL; + case WHITE: + default: + return Material.WHITE_WOOL; + } + } + + public static boolean isSubType(Material type, Material check) { + if (type.name().endsWith("_WOOL") && check.name().endsWith("_WOOL")) { + return true; + } + if (type.name().endsWith("_CONCRETE") && check.name().endsWith("_CONCRETE")) { + return true; + } + if (type.name().endsWith("_STAINED_GLASS") && check.name().endsWith("_STAINED_GLASS")) { + return true; + } + return false; + } +} diff --git a/src/net/slipcor/pvparena/events/PAWinEvent.java b/src/net/slipcor/pvparena/events/PAWinEvent.java index 0f1071945..bae2662ce 100644 --- a/src/net/slipcor/pvparena/events/PAWinEvent.java +++ b/src/net/slipcor/pvparena/events/PAWinEvent.java @@ -4,6 +4,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.Arrays; @@ -24,9 +25,9 @@ public class PAWinEvent extends Event { private static final HandlerList HANDLERS = new HandlerList(); private final Arena arena; private final Player player; - private final List items; + private final List items; - public PAWinEvent(final Arena arena, final Player player, final String[] arrItems) { + public PAWinEvent(final Arena arena, final Player player, final ItemStack[] arrItems) { super(); this.arena = arena; this.player = player; @@ -38,7 +39,7 @@ public PAWinEvent(final Arena arena, final Player player, final String[] arrItem items.addAll(Arrays.asList(arrItems)); } - public void addItemString(final String item) { + public void addItemString(final ItemStack item) { items.add(item); } @@ -55,10 +56,10 @@ public HandlerList getHandlers() { return HANDLERS; } - public String[] getItems() { - final String[] output = new String[items.size()]; + public ItemStack[] getItems() { + final ItemStack[] output = new ItemStack[items.size()]; int pos = 0; - for (final String s : items) { + for (final ItemStack s : items) { output[pos++] = s; } return output; diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java index b74edee46..bd4df9ba9 100644 --- a/src/net/slipcor/pvparena/goals/GoalDomination.java +++ b/src/net/slipcor/pvparena/goals/GoalDomination.java @@ -13,6 +13,7 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.events.PAGoalEvent; import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModuleManager; @@ -196,28 +197,28 @@ private Set checkLocationPresentTeams(final Location loc, final int dist void checkMove() { - /** - * possible Situations - * - * >>- flag is unclaimed and no one is there - * >>- flag is unclaimed and team a is there - * >>- flag is unclaimed and multiple teams are there - * - * >>- flag is being claimed by team a, no one is present - * >>- flag is being claimed by team a, team a is present - * >>- flag is being claimed by team a, multiple teams are present - * >>- flag is being claimed by team a, team b is present - * - * >>- flag is claimed by team a, no one is present - * >>- flag is claimed by team a, team a is present - * >>- flag is claimed by team a, multiple teams are present - * >>- flag is claimed by team a, team b is present - * - * >>- flag is claimed by team a and being unclaimed, no one is present - * >>- flag is claimed by team a and being unclaimed, team a is present - * >>- flag is claimed by team a and being unclaimed, multiple teams are present - * >>- flag is claimed by team a and being unclaimed, team b is present - * + /* + possible Situations + + >>- flag is unclaimed and no one is there + >>- flag is unclaimed and team a is there + >>- flag is unclaimed and multiple teams are there + + >>- flag is being claimed by team a, no one is present + >>- flag is being claimed by team a, team a is present + >>- flag is being claimed by team a, multiple teams are present + >>- flag is being claimed by team a, team b is present + + >>- flag is claimed by team a, no one is present + >>- flag is claimed by team a, team a is present + >>- flag is claimed by team a, multiple teams are present + >>- flag is claimed by team a, team b is present + + >>- flag is claimed by team a and being unclaimed, no one is present + >>- flag is claimed by team a and being unclaimed, team a is present + >>- flag is claimed by team a and being unclaimed, multiple teams are present + >>- flag is claimed by team a and being unclaimed, team b is present + */ arena.getDebugger().i("------------------"); @@ -844,7 +845,7 @@ private void takeFlag(final Arena arena, final Location lBlock, final String nam lBlock.getBlock().setType(Material.WHITE_WOOL); return; } - lBlock.getBlock().setType(StringParser.getWoolMaterialFromChatColor(team.getColor())); + lBlock.getBlock().setType(Utils.getWoolMaterialFromChatColor(team.getColor())); } } diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 918e9de9c..15ad00e97 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -15,6 +15,7 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.events.PAGoalEvent; import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModuleManager; @@ -164,9 +165,8 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block return res; } - ItemStack flagType = StringParser.getItemStackFromString(arena.getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE)); - if (block.getType() != flagType.getType() || (flagType.getData().getData()>0 && flagType.getData().getData() != block.getData())) { + Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + if (!Utils.isSubType(block.getType(), flagType)) { arena.getDebugger().i("block, but not flag", player); return res; } @@ -328,9 +328,8 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block .getHelmet().clone()); } catch (final Exception e) { } - final ItemStack itemStack = block.getState().getData().toItemStack() + final ItemStack itemStack = block.getState().getData().toItemStack(1) .clone(); - itemStack.setAmount(1); if (arena.getArenaConfig().getBoolean( CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { itemStack.setDurability(getFlagOverrideTeamShort(arena, aTeam)); @@ -431,9 +430,8 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block return res; } - ItemStack flagType = StringParser.getItemStackFromString(arena.getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE)); - if (block == null || block.getType() != flagType.getType() || (flagType.getData().getData()>0 && flagType.getData().getData() != block.getData())) { + Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + if (block == null || !Utils.isSubType(block.getType(), flagType)) { return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java index 96eecf835..92e8ec57f 100644 --- a/src/net/slipcor/pvparena/goals/GoalInfect.java +++ b/src/net/slipcor/pvparena/goals/GoalInfect.java @@ -30,6 +30,7 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; +import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; @@ -213,8 +214,8 @@ public PACheck checkInventory(PACheck result, Arena arena, InventoryClickEvent e } @Override - public PACheck checkPickup(PACheck result, Arena arena, PlayerPickupItemEvent event) { - ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getPlayer().getName()); + public PACheck checkPickup(PACheck result, Arena arena, EntityPickupItemEvent event) { + ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getEntity().getName()); if (arena.equals(ap.getArena())) { if ("infected".equals(ap.getArenaTeam().getName())) { if (ArenaPlayer.PlayerPrevention.has( diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java index b9e0cd82a..111331618 100644 --- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java @@ -15,6 +15,7 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.events.PAGoalEvent; import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModuleManager; @@ -160,9 +161,8 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block } arena.getDebugger().i("checking interact", player); - ItemStack flagType = StringParser.getItemStackFromString(arena.getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE)); - if (block.getType() != flagType.getType() || (flagType.getData().getData()>0 && flagType.getData().getData() != block.getData())) { + Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + if (!Utils.isSubType(block.getType(), flagType)) { arena.getDebugger().i("block, but not flag", player); return res; } @@ -365,9 +365,8 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block return res; } - ItemStack flagType = StringParser.getItemStackFromString(arena.getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE)); - if (block == null || block.getType() != flagType.getType() || (flagType.getData().getData()>0 && flagType.getData().getData() != block.getData())) { + Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + if (block == null || !Utils.isSubType(block.getType(), flagType)) { return res; } @@ -1080,9 +1079,8 @@ public void onFlagClaim(final BlockBreakEvent event) { } catch (final Exception e) { } - final ItemStack itemStack = block.getState().getData().toItemStack() + final ItemStack itemStack = block.getState().getData().toItemStack(1) .clone(); - itemStack.setAmount(1); if (arena.getArenaConfig().getBoolean( CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { itemStack.setDurability(getFlagOverrideTeamShort(arena, aTeam)); diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java b/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java index 1cca88fa6..e2dd3a2d8 100644 --- a/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java +++ b/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java @@ -23,6 +23,7 @@ import net.slipcor.pvparena.runnables.EndRunnable; import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; @@ -50,7 +51,7 @@ public GoalPlayerKillReward() { debug = new Debug(102); } - private Map itemMap; + private Map itemMapCubed; private EndRunnable endRunner; @@ -189,18 +190,16 @@ public void commitCommand(final CommandSender sender, final String[] args) { return; } final Player player = (Player) sender; - final String contents = StringParser.getStringFromItemStacks(player - .getInventory().getArmorContents()) - + ',' - + StringParser.getStringFromItemStacks(player.getInventory() - .getStorageContents()) - + ',' - + StringParser.getStringFromItemStack(player.getInventory() - .getItemInOffHand()); - - getItemMap().put(value, StringParser.getItemStacksFromString(contents)); + + ItemStack[][] content = new ItemStack[][]{ + player.getInventory().getStorageContents(), + new ItemStack[]{player.getInventory().getItemInOffHand()}, + player.getInventory().getArmorContents() + }; + + getItemMap().put(value, content); arena.msg(sender, Language.parse(arena, MSG.GOAL_KILLREWARD_ADDED, - args[1], contents)); + args[1])); } @@ -356,19 +355,11 @@ private void reset(final Player player) { } } - @Override - public void displayInfo(final CommandSender sender) { - for (final int i : getItemMap().keySet()) { - final ItemStack[] items = getItemMap().get(i); - sender.sendMessage("kill #" + i + ": " + StringParser.getStringFromItemStacks(items)); - } - } - - private Map getItemMap() { - if (itemMap == null) { - itemMap = new HashMap<>(); + private Map getItemMap() { + if (itemMapCubed == null) { + itemMapCubed = new HashMap<>(); } - return itemMap; + return itemMapCubed; } @Override @@ -474,8 +465,12 @@ public void setDefaults(final YamlConfiguration config) { if (cs != null) { for (final String line : cs.getKeys(false)) { try { - getItemMap().put(Integer.parseInt(line.substring(2)), StringParser - .getItemStacksFromString(cs.getString(line))); + getItemMap().put(Integer.parseInt(line.substring(2)), + new ItemStack[][] { + cs.getList(line + ".items").toArray(new ItemStack[0]), + cs.getList(line + ".offhand").toArray(new ItemStack[]{new ItemStack(Material.AIR, 1)}), + cs.getList(line + ".armor").toArray(new ItemStack[0]) + }); } catch (final Exception e) { } } @@ -483,16 +478,61 @@ public void setDefaults(final YamlConfiguration config) { if (getItemMap().size() < 1) { - getItemMap().put(5, - StringParser.getItemStacksFromString("298,299,300,301,268")); // leather - getItemMap().put(4, - StringParser.getItemStacksFromString("302,303,304,305,272")); // chain - getItemMap().put(3, - StringParser.getItemStacksFromString("314,315,316,317,267")); // gold - getItemMap().put(2, - StringParser.getItemStacksFromString("306,307,308,309,276")); // iron - getItemMap().put(1, - StringParser.getItemStacksFromString("310,311,312,313,276")); // diamond + getItemMap().put(5, new ItemStack[][]{ + new ItemStack[]{}, + new ItemStack[]{}, + new ItemStack[]{ + new ItemStack(Material.LEATHER_HELMET, 1), + new ItemStack(Material.LEATHER_CHESTPLATE, 1), + new ItemStack(Material.LEATHER_LEGGINGS, 1), + new ItemStack(Material.LEATHER_BOOTS, 1), + new ItemStack(Material.WOODEN_SWORD, 1) + }, + }); + getItemMap().put(4, new ItemStack[][]{ + new ItemStack[]{}, + new ItemStack[]{new ItemStack(Material.AIR, 1)}, + new ItemStack[]{ + new ItemStack(Material.CHAINMAIL_HELMET, 1), + new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1), + new ItemStack(Material.CHAINMAIL_LEGGINGS, 1), + new ItemStack(Material.CHAINMAIL_BOOTS, 1), + new ItemStack(Material.STONE_SWORD, 1) + }, + }); + getItemMap().put(3, new ItemStack[][]{ + new ItemStack[]{}, + new ItemStack[]{new ItemStack(Material.AIR, 1)}, + new ItemStack[]{ + new ItemStack(Material.GOLDEN_HELMET, 1), + new ItemStack(Material.GOLDEN_CHESTPLATE, 1), + new ItemStack(Material.GOLDEN_LEGGINGS, 1), + new ItemStack(Material.GOLDEN_BOOTS, 1), + new ItemStack(Material.IRON_SWORD, 1) + }, + }); + getItemMap().put(2, new ItemStack[][]{ + new ItemStack[]{}, + new ItemStack[]{new ItemStack(Material.AIR, 1)}, + new ItemStack[]{ + new ItemStack(Material.IRON_HELMET, 1), + new ItemStack(Material.IRON_CHESTPLATE, 1), + new ItemStack(Material.IRON_LEGGINGS, 1), + new ItemStack(Material.IRON_BOOTS, 1), + new ItemStack(Material.DIAMOND_SWORD, 1) + }, + }); + getItemMap().put(1, new ItemStack[][]{ + new ItemStack[]{}, + new ItemStack[]{new ItemStack(Material.AIR, 1)}, + new ItemStack[]{ + new ItemStack(Material.DIAMOND_HELMET, 1), + new ItemStack(Material.DIAMOND_CHESTPLATE, 1), + new ItemStack(Material.DIAMOND_LEGGINGS, 1), + new ItemStack(Material.DIAMOND_BOOTS, 1), + new ItemStack(Material.DIAMOND_SWORD, 1) + }, + }); saveItems(); } @@ -500,8 +540,12 @@ public void setDefaults(final YamlConfiguration config) { private void saveItems() { for (final int i : getItemMap().keySet()) { - arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i, - StringParser.getStringFromItemStacks(getItemMap().get(i))); + arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".items", + getItemMap().get(i)[0]); + arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".offhand", + getItemMap().get(i)[1]); + arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".armor", + getItemMap().get(i)[2]); } arena.getArenaConfig().save(); } diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java index e26fec0d2..f244d6a05 100644 --- a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java +++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java @@ -20,15 +20,14 @@ import net.slipcor.pvparena.runnables.EndRunnable; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.material.MaterialData; import java.util.ArrayList; import java.util.List; @@ -220,7 +219,7 @@ public void displayInfo(final CommandSender sender) { } private void drop(final Player player, final ArenaTeam team) { - final ItemStack item = StringParser.getItemStackFromString(arena.getArenaConfig().getString(CFG.GOAL_TDC_ITEM)); + final ItemStack item = arena.getArenaConfig().getItems(CFG.GOAL_TDC_ITEM)[0]; final ItemMeta meta = item.getItemMeta(); @@ -279,12 +278,12 @@ public boolean isInternal() { } @Override - public void onPlayerPickUp(final PlayerPickupItemEvent event) { + public void onPlayerPickUp(final EntityPickupItemEvent event) { final ItemStack item = event.getItem().getItemStack(); - final ItemStack check = StringParser.getItemStackFromString(arena.getArenaConfig().getString(CFG.GOAL_TDC_ITEM)); + final ItemStack check = arena.getArenaConfig().getItems(CFG.GOAL_TDC_ITEM)[0]; - final ArenaPlayer player = ArenaPlayer.parsePlayer(event.getPlayer().getName()); + final ArenaPlayer player = ArenaPlayer.parsePlayer(event.getEntity().getName()); if (item.getType() == check.getType() && item.hasItemMeta()) { for (final ArenaTeam team : arena.getTeams()) { @@ -296,12 +295,12 @@ public void onPlayerPickUp(final PlayerPickupItemEvent event) { if (team.equals(player.getArenaTeam())) { // denied a kill - arena.broadcastExcept(event.getPlayer(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_DENIED, player.toString())); - arena.msg(event.getPlayer(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_YOUDENIED, player.toString())); + arena.broadcastExcept(event.getEntity(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_DENIED, player.toString())); + arena.msg(event.getEntity(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_YOUDENIED, player.toString())); } else { // scored a kill - arena.broadcastExcept(event.getPlayer(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_SCORED, player.toString())); - arena.msg(event.getPlayer(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_YOUSCORED, player.toString())); + arena.broadcastExcept(event.getEntity(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_SCORED, player.toString())); + arena.msg(event.getEntity(), Language.parse(arena, MSG.GOAL_TEAMDEATHCONFIRM_YOUSCORED, player.toString())); reduceLives(arena, team); } return; diff --git a/src/net/slipcor/pvparena/listeners/BlockListener.java b/src/net/slipcor/pvparena/listeners/BlockListener.java index 8dc4f334c..f5fffc778 100644 --- a/src/net/slipcor/pvparena/listeners/BlockListener.java +++ b/src/net/slipcor/pvparena/listeners/BlockListener.java @@ -128,8 +128,7 @@ public void onBlockBreak(final BlockBreakEvent event) { && !list.contains(String.valueOf(event.getBlock().getType() .name())) && !list.contains(String.valueOf(event.getBlock().getType() - .name()) - + ':' + event.getBlock().getData())) { + .name()))) { arena.msg( event.getPlayer(), Language.parse(arena, MSG.ERROR_WHITELIST_DISALLOWED, @@ -151,8 +150,7 @@ public void onBlockBreak(final BlockBreakEvent event) { new ArrayList())); if (list.contains(String.valueOf(event.getBlock().getType().name())) - || list.contains(String.valueOf(event.getBlock().getType().name()) - + ':' + event.getBlock().getData())) { + || list.contains(String.valueOf(event.getBlock().getType().name()))) { arena.msg( event.getPlayer(), Language.parse(arena, MSG.ERROR_BLACKLIST_DISALLOWED, @@ -443,8 +441,7 @@ public void run() { && !list.contains(String.valueOf(event.getBlockPlaced() .getType().name())) && !list.contains(String.valueOf(event.getBlockPlaced() - .getType().name()) - + ':' + event.getBlock().getData())) { + .getType().name()))) { arena.msg( event.getPlayer(), Language.parse(arena, MSG.ERROR_WHITELIST_DISALLOWED, @@ -476,8 +473,7 @@ public void run() { if (list.contains(String.valueOf(event.getBlockPlaced().getType().name())) || list.contains(String.valueOf(event.getBlockPlaced() - .getType().name()) - + ':' + event.getBlock().getData())) { + .getType().name()))) { arena.msg( event.getPlayer(), Language.parse(arena, MSG.ERROR_BLACKLIST_DISALLOWED, diff --git a/src/net/slipcor/pvparena/listeners/EntityListener.java b/src/net/slipcor/pvparena/listeners/EntityListener.java index 8bc9c57ff..f6182ce07 100644 --- a/src/net/slipcor/pvparena/listeners/EntityListener.java +++ b/src/net/slipcor/pvparena/listeners/EntityListener.java @@ -448,10 +448,10 @@ public void onPotionSplash(final PotionSplashEvent event) { if (damagee.getArena() == null || shooter.getArena() == null || (damagee.getArena() != shooter.getArena()) || damagee.getArenaTeam() == null || shooter.getArenaTeam() == null) { - /** - * some people obviously allow non arena players to mess with potions around arena players - * - * this check should cover any of the entities not being in the same arena, or not arena at all + /* + some people obviously allow non arena players to mess with potions around arena players + + this check should cover any of the entities not being in the same arena, or not arena at all */ DEBUG.i("skipping "+e.getName()); continue; diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 0dc252a44..dc1192e8a 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -320,8 +320,6 @@ public void onPlayerDropItem(final PlayerDropItemEvent event) { return; // no drop protection } - arena.getDebugger().i("item: "+ StringParser.getStringFromItemStack(event.getItemDrop().getItemStack())); - if (Bukkit.getPlayer(player.getName()) == null || aPlayer.getStatus() == Status.DEAD || aPlayer.getStatus() == Status.LOST) { arena.getDebugger().i("Player is dead. allowing drops!"); return; @@ -796,8 +794,8 @@ public void onPlayerRespawn(final PlayerRespawnEvent event) { } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onPlayerPickupItem(final PlayerPickupItemEvent event) { - final Player player = event.getPlayer(); + public void onPlayerPickupItem(final EntityPickupItemEvent event) { + final Player player = (Player) event.getEntity(); if (willBeCancelled(player, event)) { return; @@ -927,7 +925,7 @@ class RunLater implements Runnable { public void run() { for (final ArenaPlayer otherPlayer : arena.getFighters()) { if (otherPlayer.get() != null) { - otherPlayer.get().showPlayer(player); + otherPlayer.get().showPlayer(PVPArena.instance, player); } } } diff --git a/src/net/slipcor/pvparena/loadables/ArenaGoal.java b/src/net/slipcor/pvparena/loadables/ArenaGoal.java index 470a1672e..50e4cf018 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaGoal.java +++ b/src/net/slipcor/pvparena/loadables/ArenaGoal.java @@ -17,11 +17,11 @@ import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import java.util.*; @@ -115,7 +115,7 @@ public PACheck checkInventory(PACheck result, Arena arena, InventoryClickEvent e return result; } - public PACheck checkPickup(PACheck result, Arena arena, PlayerPickupItemEvent event) { + public PACheck checkPickup(PACheck result, Arena arena, EntityPickupItemEvent event) { return result; } @@ -408,7 +408,7 @@ public void lateJoin(final Player player) { public void onThisLoad() { } - public void onPlayerPickUp(final PlayerPickupItemEvent event) { + public void onPlayerPickUp(final EntityPickupItemEvent event) { } /** diff --git a/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java b/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java index 0aa81a998..e60d7847c 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java +++ b/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java @@ -16,6 +16,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerDropItemEvent; @@ -133,10 +134,12 @@ public static PACheck checkInventory(Arena arena, InventoryClickEvent event) { return result; } - public static PACheck checkPickup(Arena arena, PlayerPickupItemEvent event) { + public static PACheck checkPickup(Arena arena, EntityPickupItemEvent event) { PACheck result = new PACheck(); - for (final ArenaGoal type : arena.getGoals()) { - result = type.checkPickup(result, arena, event); + if (event.getEntity() instanceof Player) { + for (final ArenaGoal type : arena.getGoals()) { + result = type.checkPickup(result, arena, event); + } } return result; } @@ -245,10 +248,10 @@ public void setPlayerLives(final Arena arena, final ArenaPlayer player, public void timedEnd(final Arena arena) { - /** - * name/team => score points - * - * handed over to each module + /* + name/team => score points + + handed over to each module */ arena.getDebugger().i("timed end!"); @@ -504,9 +507,11 @@ public static void lateJoin(final Arena arena, final Player player) { } } - public static void onPlayerPickUp(final Arena arena, final PlayerPickupItemEvent event) { - for (final ArenaGoal goal : arena.getGoals()) { - goal.onPlayerPickUp(event); + public static void onPlayerPickUp(final Arena arena, final EntityPickupItemEvent event) { + if (event.getEntity() instanceof Player) { + for (final ArenaGoal goal : arena.getGoals()) { + goal.onPlayerPickUp(event); + } } } } diff --git a/src/net/slipcor/pvparena/loadables/ArenaModule.java b/src/net/slipcor/pvparena/loadables/ArenaModule.java index 61210a6cc..fd7149667 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaModule.java +++ b/src/net/slipcor/pvparena/loadables/ArenaModule.java @@ -20,13 +20,9 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Hanging; import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.*; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerVelocityEvent; import org.bukkit.inventory.ItemStack; @@ -332,7 +328,7 @@ public boolean onPlayerInteract(final PlayerInteractEvent event) { * * @param event the pickup event */ - public void onPlayerPickupItem(final PlayerPickupItemEvent event) { + public void onPlayerPickupItem(final EntityPickupItemEvent event) { } /** diff --git a/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java b/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java index 4fc4aebfe..0c380e757 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java +++ b/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java @@ -15,13 +15,9 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.Hanging; import org.bukkit.entity.Player; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.*; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.event.player.PlayerVelocityEvent; import java.io.File; @@ -204,9 +200,11 @@ public static boolean onPlayerInteract(final Arena arena, final PlayerInteractEv return false; } - public static void onPlayerPickupItem(final Arena arena, final PlayerPickupItemEvent event) { - for (final ArenaModule mod : arena.getMods()) { - mod.onPlayerPickupItem(event); + public static void onPlayerPickupItem(final Arena arena, final EntityPickupItemEvent event) { + if (event.getEntity() instanceof Player) { + for (final ArenaModule mod : arena.getMods()) { + mod.onPlayerPickupItem(event); + } } } @@ -269,16 +267,6 @@ public static void reset(final Arena arena, final boolean force) { } } - /** - * @deprecated use {@link #resetPlayer(Arena, Player, boolean, boolean)} - */ - @Deprecated - public static void resetPlayer(final Arena arena, final Player player, final boolean force) { - for (final ArenaModule mod : arena.getMods()) { - mod.resetPlayer(player, force); - } - } - public static void resetPlayer(final Arena arena, final Player player, final boolean soft, final boolean force) { for (final ArenaModule mod : arena.getMods()) { mod.resetPlayer(player, soft, force); diff --git a/src/net/slipcor/pvparena/loadables/ArenaRegion.java b/src/net/slipcor/pvparena/loadables/ArenaRegion.java index 10b01edc6..677e36c69 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaRegion.java +++ b/src/net/slipcor/pvparena/loadables/ArenaRegion.java @@ -521,7 +521,7 @@ public void tick() { } ap.get().setLastDamageCause( new EntityDamageEvent(ap.get(), DamageCause.CUSTOM, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(1003))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0)))); + 1003.0)); ap.get().damage(1000); } if (flags.contains(RegionFlag.WIN) && shape.contains(pLoc)) { @@ -540,8 +540,7 @@ public void tick() { Bukkit.getWorld(world).strikeLightningEffect( ap2.get().getLocation()); final EntityDamageEvent event = new EntityDamageEvent( - ap2.get(), DamageCause.LIGHTNING, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0))); + ap2.get(), DamageCause.LIGHTNING, 10.0); PlayerListener.finallyKillPlayer(arena, ap2.get(), event); } @@ -555,8 +554,7 @@ public void tick() { Bukkit.getWorld(world).strikeLightningEffect( ap.get().getLocation()); final EntityDamageEvent event = new EntityDamageEvent( - ap.get(), DamageCause.LIGHTNING, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0))); + ap.get(), DamageCause.LIGHTNING, 10.0); PlayerListener .finallyKillPlayer(arena, ap.get(), event); } @@ -572,8 +570,7 @@ public void tick() { .strikeLightningEffect( ap2.get().getLocation()); final EntityDamageEvent event = new EntityDamageEvent( - ap2.get(), DamageCause.LIGHTNING, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(10))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0))); + ap2.get(), DamageCause.LIGHTNING,10.0); PlayerListener.finallyKillPlayer(arena, ap2.get(), event); } @@ -592,8 +589,7 @@ public void tick() { if (loc.distance(ap.get().getLocation()) < 3) { ap.get().setLastDamageCause( new EntityDamageEvent(ap.get(), - DamageCause.CUSTOM, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(arena.getArenaConfig().getInt(CFG.DAMAGE_SPAWNCAMP)))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0)))); + DamageCause.CUSTOM, arena.getArenaConfig().getInt(CFG.DAMAGE_SPAWNCAMP))); ap.get().damage( arena.getArenaConfig().getInt( CFG.DAMAGE_SPAWNCAMP)); @@ -627,8 +623,7 @@ public void tick() { CFG.GENERAL_LEAVEDEATH)) { ap.get().setLastDamageCause( new EntityDamageEvent(ap.get(), - DamageCause.CUSTOM, - new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, Double.valueOf(1004))), new EnumMap(ImmutableMap.of(EntityDamageEvent.DamageModifier.BASE, 0)))); + DamageCause.CUSTOM, 1004.0)); // ap.get().setHealth(0); ap.get().damage(1000); } else { diff --git a/src/net/slipcor/pvparena/managers/ConfigurationManager.java b/src/net/slipcor/pvparena/managers/ConfigurationManager.java index e8eb4293f..9b237417a 100644 --- a/src/net/slipcor/pvparena/managers/ConfigurationManager.java +++ b/src/net/slipcor/pvparena/managers/ConfigurationManager.java @@ -12,6 +12,7 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModule; import net.slipcor.pvparena.loadables.ArenaModuleManager; @@ -19,12 +20,9 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Chest; -import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; -import java.io.File; -import java.io.IOException; import java.util.*; /** @@ -130,19 +128,34 @@ public static boolean configParse(final Arena arena, final Config cfg) { if (config.get("classitems") == null) { if (PVPArena.instance.getConfig().get("classitems") == null) { - config.addDefault("classitems.Ranger", - "BOW,ARROW:64,LEATHER_HELMET,LEATHER_CHESTPLATE,LEATHER_LEGGINGS,LEATHER_BOOTS"); - config.addDefault("classitems.Swordsman", - "DIAMOND_SWORD,IRON_HELMET,IRON_CHESTPLATE,IRON_LEGGINGS,IRON_BOOTS"); - config.addDefault("classitems.Tank", - "STONE_SWORD,DIAMOND_HELMET,DIAMOND_CHESTPLATE,DIAMOND_LEGGINGS,DIAMOND_BOOTS"); - config.addDefault("classitems.Pyro", - "FLINT_AND_STEEL,TNT:3,LEATHER_HELMET,LEATHER_CHESTPLATE,LEATHER_LEGGINGS,LEATHER_BOOTS"); - } else { - for (final String key : PVPArena.instance.getConfig().getKeys(false)) { - config.addDefault("classitems." + key, PVPArena.instance - .getConfig().get("classitems." + key)); - } + config.addDefault("classitems.Ranger.items", + Utils.getItemStacksFromMaterials(Material.BOW, Material.ARROW)); + config.addDefault("classitems.Ranger.offhand", + Utils.getItemStacksFromMaterials(Material.AIR)); + config.addDefault("classitems.Ranger.armor", + Utils.getItemStacksFromMaterials(Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS)); + + config.addDefault("classitems.Swordsman.items", + Utils.getItemStacksFromMaterials(Material.DIAMOND_SWORD)); + config.addDefault("classitems.Swordsman.offhand", + Utils.getItemStacksFromMaterials(Material.AIR)); + config.addDefault("classitems.Swordsman.armor", + Utils.getItemStacksFromMaterials(Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS)); + + config.addDefault("classitems.Tank.items", + Utils.getItemStacksFromMaterials(Material.STONE_SWORD)); + config.addDefault("classitems.Tank.offhand", + Utils.getItemStacksFromMaterials(Material.AIR)); + config.addDefault("classitems.Tank.armor", + Utils.getItemStacksFromMaterials(Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS)); + + config.addDefault("classitems.Pyro.items", + Utils.getItemStacksFromMaterials(Material.FLINT_AND_STEEL, Material.TNT, Material.TNT, Material.TNT)); + config.addDefault("classitems.Pyro.offhand", + Utils.getItemStacksFromMaterials(Material.AIR)); + config.addDefault("classitems.Pyro.armor", + Utils.getItemStacksFromMaterials(Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS)); + } } @@ -183,10 +196,14 @@ public static boolean configParse(final Arena arena, final Config cfg) { arena.getDebugger().i("reading class items"); ArenaClass.addGlobalClasses(arena); for (final Map.Entry stringObjectEntry1 : classes.entrySet()) { - final String sItemList; + ItemStack[] items; + ItemStack offHand = new ItemStack(Material.AIR, 1); + ItemStack[] armors = new ItemStack[]{new ItemStack(Material.AIR, 1)}; try { - sItemList = (String) stringObjectEntry1.getValue(); + items = config.getList("classitems."+stringObjectEntry1.getKey()+".items").toArray(new ItemStack[0]); + offHand = config.getList("classitems."+stringObjectEntry1.getKey()+".offhand").toArray(new ItemStack[]{new ItemStack(Material.AIR, 1)})[0]; + armors = config.getList("classitems."+stringObjectEntry1.getKey()+".armor").toArray(new ItemStack[0]); } catch (final Exception e) { Bukkit.getLogger().severe( "[PVP Arena] Error while parsing class, skipping: " @@ -199,56 +216,23 @@ public static boolean configParse(final Arena arena, final Config cfg) { PABlockLocation loc = new PABlockLocation(classChest); Chest c = (Chest) loc.toLocation().getBlock().getState(); ItemStack[] contents = c.getInventory().getContents(); - final ItemStack[] items = Arrays.copyOfRange(contents, 0, contents.length - 5); - final ItemStack offHand = contents[contents.length - 5]; - final ItemStack[] armors = Arrays.copyOfRange(contents, contents.length - 4, contents.length); + + items = Arrays.copyOfRange(contents, 0, contents.length - 5); + offHand = contents[contents.length - 5]; + armors = Arrays.copyOfRange(contents, contents.length - 4, contents.length); + arena.addClass(stringObjectEntry1.getKey(), items, offHand, armors); arena.getDebugger().i("adding class chest items to class " + stringObjectEntry1.getKey()); } catch (Exception e) { - final String[] sItems = sItemList.split(","); - final ItemStack[] items = new ItemStack[sItems.length]; - final ItemStack[] offHand = new ItemStack[1]; - final ItemStack[] armors = new ItemStack[4]; - - for (int i = 0; i < sItems.length; i++) { - - if (sItems[i].contains(">>!<<")) { - final String[] split = sItems[i].split(">>!<<"); - - final int id = Integer.parseInt(split[0]); - armors[id] = StringParser.getItemStackFromString(split[1]); - - if (armors[id] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized armor item: " + split[1]); - } - - sItems[i] = "AIR"; - } else if (sItems[i].contains(">>O<<")) { - final String[] split = sItems[i].split(">>O<<"); - - final int id = Integer.parseInt(split[0]); - offHand[id] = StringParser.getItemStackFromString(split[1]); - - if (offHand[id] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized offhand item: " + split[1]); - } - sItems[i] = "AIR"; - } - - items[i] = StringParser.getItemStackFromString(sItems[i]); - if (items[i] == null) { - PVPArena.instance.getLogger().warning( - "unrecognized item: " + items[i]); - } - } - arena.addClass(stringObjectEntry1.getKey(), items, offHand[0], armors); + arena.addClass(stringObjectEntry1.getKey(), items, offHand, armors); arena.getDebugger().i("adding class items to class " + stringObjectEntry1.getKey()); } } - arena.addClass("custom", StringParser.getItemStacksFromString("AIR"), StringParser.getItemStackFromString("AIR"), StringParser.getItemStacksFromString("AIR")); + arena.addClass("custom", + new ItemStack[]{new ItemStack(Material.AIR, 1)}, + new ItemStack(Material.AIR, 1), + new ItemStack[]{new ItemStack(Material.AIR, 1)}); arena.setOwner(cfg.getString(CFG.GENERAL_OWNER)); arena.setLocked(!cfg.getBoolean(CFG.GENERAL_ENABLED)); arena.setFree("free".equals(cfg.getString(CFG.GENERAL_TYPE))); diff --git a/src/net/slipcor/pvparena/modules/RegionTool.java b/src/net/slipcor/pvparena/modules/RegionTool.java index c5e872688..cef900fe5 100644 --- a/src/net/slipcor/pvparena/modules/RegionTool.java +++ b/src/net/slipcor/pvparena/modules/RegionTool.java @@ -5,12 +5,9 @@ import net.slipcor.pvparena.classes.PABlockLocation; import net.slipcor.pvparena.core.Config.CFG; import net.slipcor.pvparena.core.Debug; -import net.slipcor.pvparena.core.Language; -import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.loadables.ArenaModule; import net.slipcor.pvparena.loadables.ArenaRegion; import net.slipcor.pvparena.managers.ArenaManager; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.event.player.PlayerInteractEvent; diff --git a/src/net/slipcor/pvparena/regions/CuboidRegion.java b/src/net/slipcor/pvparena/regions/CuboidRegion.java index 369e24de7..03584bb69 100644 --- a/src/net/slipcor/pvparena/regions/CuboidRegion.java +++ b/src/net/slipcor/pvparena/regions/CuboidRegion.java @@ -224,7 +224,7 @@ public void showBorder(final Player player) { public void run() { for (final Block b : border) { player.sendBlockChange(b.getLocation(), - b.getType(), b.getData()); + b.getType().createBlockData()); } border.clear(); } diff --git a/src/net/slipcor/pvparena/regions/CylindricRegion.java b/src/net/slipcor/pvparena/regions/CylindricRegion.java index 91397f719..19b2bf6f6 100644 --- a/src/net/slipcor/pvparena/regions/CylindricRegion.java +++ b/src/net/slipcor/pvparena/regions/CylindricRegion.java @@ -266,7 +266,7 @@ public void showBorder(final Player player) { public void run() { for (final Block b : border) { player.sendBlockChange(b.getLocation(), - b.getType(), b.getData()); + b.getType().createBlockData()); } border.clear(); } diff --git a/src/net/slipcor/pvparena/regions/SphericRegion.java b/src/net/slipcor/pvparena/regions/SphericRegion.java index 5907972a7..d38220ed4 100644 --- a/src/net/slipcor/pvparena/regions/SphericRegion.java +++ b/src/net/slipcor/pvparena/regions/SphericRegion.java @@ -273,7 +273,7 @@ public void showBorder(final Player player) { public void run() { for (final Block b : border) { player.sendBlockChange(b.getLocation(), - b.getType(), b.getData()); + b.getType().createBlockData()); } border.clear(); } diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java index 6eddfe180..e1ccbbd31 100644 --- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java +++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java @@ -7,11 +7,10 @@ import net.slipcor.pvparena.arena.ArenaPlayer.Status; import net.slipcor.pvparena.arena.ArenaTeam; import net.slipcor.pvparena.core.Config.CFG; -import net.slipcor.pvparena.core.StringParser; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.managers.InventoryManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -46,7 +45,7 @@ public InventoryRefillRunnable(final Arena arena, final Player player, final Lis boolean keepAll = "all".equalsIgnoreCase(this.arena.getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN)); if (!"none".equals(this.arena.getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN))) { - final ItemStack[] items = StringParser.getItemStacksFromString(this.arena.getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN)); + final ItemStack[] items = this.arena.getArenaConfig().getItems(CFG.ITEMS_KEEPONRESPAWN); for (final ItemStack item : itemList) { if (item != null) { @@ -60,10 +59,6 @@ public InventoryRefillRunnable(final Arena arena, final Player player, final Lis continue; } - if (item.getData().getData() != iItem.getData().getData()) { - continue; - } - additions.add(item); break; } @@ -98,7 +93,7 @@ public void run() { arena.getDebugger().i("forcing woolhead: " + aTeam.getName() + '/' + chatColor.name(), player); player.getInventory().setHelmet( - new ItemStack(StringParser.getWoolMaterialFromChatColor(chatColor), 1)); + new ItemStack(Utils.getWoolMaterialFromChatColor(chatColor), 1)); PVPArena.instance.getAgm().refillInventory(arena, player); } } else if (refill && "custom".equals(aPlayer.getArenaClass().getName())) { From a3eafb3540c0e4accf7455655204c868bdd737b3 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 26 Jul 2018 02:36:31 +0200 Subject: [PATCH 003/115] v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index f4e132878..bf43328c5 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,9 @@ ![PVP-Arena](/doc/images/logo.png) +```diff +- NOTE FOR TESTERS! - YOU NEED TO START WITH A FRESH CONFIGURATION! ITEM DEFINITIONS HAVE CHANGED. USE THE SET COMMAND TO SET ITEMS/MATERIALS +``` + **Enhance your server by adding a new dimension of PVP battles!** From 43f8dce3d3b000db18fb5bbe6d51f61a0bc56a34 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 30 Sep 2018 00:29:54 +0200 Subject: [PATCH 004/115] v1.13.2 - plugin.yml api update --- doc/changelog.md | 1 + readme.md | 2 +- src/plugin.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/changelog.md b/doc/changelog.md index d2efc08ee..7dd792952 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,5 +1,6 @@ == PVP-Arena v1.13 Changelog +- v1.13.2 - plugin.yml api update - v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions - v1.13.0 - slowly work our way to Spigot 1.13 diff --git a/readme.md b/readme.md index bf43328c5..1063d2512 100644 --- a/readme.md +++ b/readme.md @@ -97,7 +97,7 @@ Users tutorials : ## Changelog -- v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions +- v1.13.2 - plugin.yml api update - [read more](doc/changelog.md) *** diff --git a/src/plugin.yml b/src/plugin.yml index b46c0b94c..1b626f218 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -4,6 +4,7 @@ authors: [slipcor] prefix: PVP Arena main: net.slipcor.pvparena.PVPArena version: 1.13.0 +api-version: 1.13 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot] description: create, manage and enhance PvP arenas website: http://dev.bukkit.org/server-mods/pvparena From 4554a948f337b9abb0ab6304e24c033f463d4c8c Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 25 Oct 2018 22:46:28 +0200 Subject: [PATCH 005/115] 1.13.3 - WIP - the core game should be operational, region setup tested, blockrestore fixed --- pom.xml | 2 +- src/net/slipcor/pvparena/arena/Arena.java | 6 ++---- .../slipcor/pvparena/arena/ArenaPlayer.java | 2 +- src/net/slipcor/pvparena/classes/PACheck.java | 2 +- .../slipcor/pvparena/commands/PAI_Info.java | 2 +- src/net/slipcor/pvparena/core/Config.java | 13 +++++++------ .../slipcor/pvparena/core/StringParser.java | 18 ++++++++++++++++++ .../pvparena/goals/GoalBlockDestroy.java | 9 ++++----- .../slipcor/pvparena/goals/GoalDomination.java | 2 +- .../pvparena/loadables/ArenaRegion.java | 2 +- .../runnables/InventoryRefillRunnable.java | 4 ++-- src/plugin.yml | 2 +- 12 files changed, 40 insertions(+), 24 deletions(-) diff --git a/pom.xml b/pom.xml index 313ed484c..c38e99bd5 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,7 @@ org.bukkit bukkit - 1.13-R0.1-SNAPSHOT + 1.13.1-R0.1-SNAPSHOT jar provided diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index f6a20d4cc..1b2dcc689 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -486,14 +486,12 @@ public String getPrefix() { public Material getReadyBlock() { getDebugger().i("reading ready block"); - final String sMat = cfg.getString(CFG.READY_BLOCK); try { - Material mMat; - mMat = Material.getMaterial(sMat); + Material mMat = cfg.getMaterial(CFG.READY_BLOCK, Material.STICK); getDebugger().i("mMat now is " + mMat.name()); return mMat; } catch (final Exception e) { - Language.logWarn(MSG.ERROR_MAT_NOT_FOUND, sMat); + Language.logWarn(MSG.ERROR_MAT_NOT_FOUND, "ready block"); } return Material.IRON_BLOCK; } diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index 5231d9818..e208245e1 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -290,7 +290,7 @@ public static void reloadInventory(final Arena arena, final Player player, final final ArenaPlayer aPlayer = parsePlayer(player.getName()); - if (!"none".equals(arena.getArenaConfig().getString(CFG.ITEMS_TAKEOUTOFGAME))) { + if (arena.getArenaConfig().getYamlConfiguration().get(CFG.ITEMS_TAKEOUTOFGAME.getNode()) != null) { final ItemStack[] items = arena.getArenaConfig().getItems(CFG.ITEMS_TAKEOUTOFGAME); diff --git a/src/net/slipcor/pvparena/classes/PACheck.java b/src/net/slipcor/pvparena/classes/PACheck.java index 46df6b529..b604d4fb5 100644 --- a/src/net/slipcor/pvparena/classes/PACheck.java +++ b/src/net/slipcor/pvparena/classes/PACheck.java @@ -532,7 +532,7 @@ public static void handlePlayerDeath(final Arena arena, InventoryManager.clearInventory(player.getKiller()); ArenaPlayer.parsePlayer(player.getKiller().getName()).getArenaClass().equip(player.getKiller()); } - if (!arena.getArenaConfig().getString(CFG.PLAYER_ITEMSONKILL).equals("none")) { + if (arena.getArenaConfig().getItems(CFG.PLAYER_ITEMSONKILL) != null) { ItemStack[] items = arena.getArenaConfig().getItems(CFG.PLAYER_ITEMSONKILL); for (ItemStack item : items) { if (item != null) { diff --git a/src/net/slipcor/pvparena/commands/PAI_Info.java b/src/net/slipcor/pvparena/commands/PAI_Info.java index 4ea4e2fae..42ce9da7b 100644 --- a/src/net/slipcor/pvparena/commands/PAI_Info.java +++ b/src/net/slipcor/pvparena/commands/PAI_Info.java @@ -123,7 +123,7 @@ public void commit(final Arena arena, final CommandSender sender, final String[] arena.msg(sender, "minplayers: " + arena.getArenaConfig().getInt(CFG.ITEMS_MINPLAYERS) + " | " + "rewards: " + - arena.getArenaConfig().getString(CFG.ITEMS_REWARDS) + " | " + + StringParser.getItems(arena.getArenaConfig().getItems(CFG.ITEMS_REWARDS)) + " | " + StringParser.colorVar("random", arena.getArenaConfig().getBoolean(CFG.ITEMS_RANDOM))); diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index a6a846e54..e2498fabd 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -74,12 +74,13 @@ public enum CFG { GENERAL_SMARTSPAWN("general.smartspawn", false, null), GENERAL_TIME("general.time", -1, null), GENERAL_TYPE("general.type", "none", null), - GENERAL_WAND("general.wand", new ItemStack[]{new ItemStack(Material.STICK)}, false, null), + GENERAL_WAND("general.wand", Material.STICK.toString(), null), GOAL_ADDLIVESPERPLAYER("goal.livesPerPlayer", false, null), ITEMS_EXCLUDEFROMDROPS("items.excludeFromDrops", new ItemStack[0], true, null), ITEMS_KEEPONRESPAWN("items.keepOnRespawn", new ItemStack[0], true, null), + ITEMS_KEEPALLONRESPAWN("items.keepAllOnRespawn", false, null), ITEMS_MINPLAYERS("items.minplayers", 2, null), ITEMS_RANDOM("items.random", true, null), ITEMS_REWARDS("items.rewards", new ItemStack[0], true, null), @@ -140,7 +141,7 @@ public enum CFG { PROTECT_SPAWN("protection.spawn", 0, null), READY_AUTOCLASS("ready.autoClass", "none", null), - READY_BLOCK("ready.block", new ItemStack[]{new ItemStack(Material.IRON_BLOCK)}, false, null), + READY_BLOCK("ready.block", Material.IRON_BLOCK.toString(), null), READY_CHECKEACHPLAYER("ready.checkEachPlayer", false, null), READY_CHECKEACHTEAM("ready.checkEachTeam", true, null), READY_ENFORCECOUNTDOWN("ready.enforceCountdown", false, null), @@ -190,7 +191,7 @@ public enum CFG { GOAL_BEACONS_TICKINTERVAL("goal.beacons.tickinterval", 60, "Beacons"), GOAL_BEACONS_TICKREWARD("goal.beacons.tickreward", 1, "Beacons"), - GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", new ItemStack[]{new ItemStack(Material.IRON_BLOCK)}, false, "BlockDestroy"), + GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", Material.IRON_BLOCK.toString(), "BlockDestroy"), GOAL_BLOCKDESTROY_LIVES("goal.blockdestroy.bdlives", 1, "BlockDestroy"), GOAL_CHECKPOINTS_CLAIMRANGE("goal.checkpoints.cpclaimrange", 5, "CheckPoints"), @@ -206,7 +207,7 @@ public enum CFG { GOAL_DOM_TICKINTERVAL("goal.dom.tickinterval", 60, "Domination"), GOAL_DOM_TICKREWARD("goal.dom.tickreward", 1, "Domination"), - GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", new ItemStack[]{new ItemStack(Material.WHITE_WOOL)}, false, "Flags"), + GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", Material.WHITE_WOOL.toString(), "Flags"), GOAL_FLAGS_LIVES("goal.flags.flives", 3, "Flags"), GOAL_FLAGS_MUSTBESAFE("goal.flags.mustBeSafe", true, "Flags"), GOAL_FLAGS_WOOLFLAGHEAD("goal.flags.woolFlagHead", true, "Flags"), @@ -227,7 +228,7 @@ public enum CFG { GOAL_PLIVES_LIVES("goal.playerlives.plives", 3, "PlayerLives"), GOAL_TANK_LIVES("goal.tank.tlives", 1, "Tank"), GOAL_TDC_LIVES("goal.teamdc.tdclives", 10, "TeamDeathConfirm"), - GOAL_TDC_ITEM("goal.teamdc.tdcitem", new ItemStack[]{new ItemStack(Material.WHITE_WOOL)}, false, "TeamDeathConfirm"), + GOAL_TDC_ITEM("goal.teamdc.tdcitem", Material.WHITE_WOOL.toString(), "TeamDeathConfirm"), GOAL_TDM_LIVES("goal.teamdm.tdlives", 10, "TeamDeathMatch"), GOAL_TDM_SUICIDESCORE("goal.teamdm.suicideScore", false, "TeamDeathMatch"), GOAL_TLIVES_LIVES("goal.teamlives.tlives", 10, "TeamLives"), @@ -407,7 +408,7 @@ public enum CFG { MODULES_VAULT_REWARD_TRIGGER("modules.vault.reward.trigger", 0.0d, "Vault"), MODULES_VAULT_REWARD_WIN("modules.vault.reward.playerWin", 0.0d, "Vault"), - MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", new ItemStack[]{new ItemStack(Material.SAND, 1)}, false, "Walls"), + MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", Material.SAND.toString(), "Walls"), MODULES_WALLS_SCOREBOARDCOUNTDOWN("modules.walls.scoreboardcountdown", false, "Walls"), MODULES_WALLS_SECONDS("modules.walls.wallseconds", 300, "Walls"), diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index 938e70f63..74e0e8367 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -279,4 +279,22 @@ public static String[] splitForScoreBoard(String key) { split[pos] = buffer.toString(); return split; } + + public static String getItems(ItemStack[] items) { + if (items == null || items.length < 1) { + return "none"; + } + StringBuffer buff = new StringBuffer(); + for (ItemStack item : items) { + buff.append(", "); + try { + buff.append(item.getType()); + buff.append('x'); + buff.append(item.getAmount()); + } catch (Exception e) { + buff.append("!error!"); + } + } + return buff.substring(2); + } } diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java index 68ad9321e..c915e786c 100644 --- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java +++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java @@ -38,10 +38,7 @@ import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.util.Vector; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** *
@@ -96,8 +93,10 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Collections.singletonList("blocktype");
+        List result = Collections.singletonList("blocktype");
         if (arena != null) {
+            result = new ArrayList<>();
+            result.add("blocktype");
             for (final ArenaTeam team : arena.getTeams()) {
                 final String sTeam = team.getName();
                 result.add(sTeam + "block");
diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java
index bd4df9ba9..0c8698671 100644
--- a/src/net/slipcor/pvparena/goals/GoalDomination.java
+++ b/src/net/slipcor/pvparena/goals/GoalDomination.java
@@ -573,7 +573,7 @@ public boolean commitSetFlag(final Player player, final Block block) {
         if (PVPArena.hasAdminPerms(player)
                 || PVPArena.hasCreatePerms(player, arena)
                 && player.getEquipment().getItemInMainHand() != null
-                && player.getEquipment().getItemInMainHand().getType().name().equals(arena
+                && player.getEquipment().getItemInMainHand().getType().toString().equals(arena
                 .getArenaConfig().getString(CFG.GENERAL_WAND))) {
 
             final Set flags = SpawnManager.getBlocksStartingWith(arena,
diff --git a/src/net/slipcor/pvparena/loadables/ArenaRegion.java b/src/net/slipcor/pvparena/loadables/ArenaRegion.java
index 677e36c69..a352371dd 100644
--- a/src/net/slipcor/pvparena/loadables/ArenaRegion.java
+++ b/src/net/slipcor/pvparena/loadables/ArenaRegion.java
@@ -200,7 +200,7 @@ public static boolean checkRegionSetPosition(final PlayerInteractEvent event,
                 && (PVPArena.hasAdminPerms(player) || PVPArena.hasCreatePerms(
                 player, arena))
                 && player.getEquipment().getItemInMainHand() != null
-                && player.getEquipment().getItemInMainHand().getType().name().equals(arena
+                && player.getEquipment().getItemInMainHand().getType().toString().equals(arena
                 .getArenaConfig().getString(CFG.GENERAL_WAND))) {
             // - modify mode is active
             // - player has admin perms
diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
index e1ccbbd31..2a7790438 100644
--- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
+++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
@@ -42,9 +42,9 @@ public InventoryRefillRunnable(final Arena arena, final Player player, final Lis
         }
         this.arena = arena == null ? aPlayer.getArena() : arena;
 
-        boolean keepAll = "all".equalsIgnoreCase(this.arena.getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN));
+        boolean keepAll = this.arena.getArenaConfig().getBoolean(CFG.ITEMS_KEEPALLONRESPAWN);
 
-        if (!"none".equals(this.arena.getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN))) {
+        if (this.arena.getArenaConfig().getItems(CFG.ITEMS_KEEPONRESPAWN) != null) {
             final ItemStack[] items = this.arena.getArenaConfig().getItems(CFG.ITEMS_KEEPONRESPAWN);
 
             for (final ItemStack item : itemList) {
diff --git a/src/plugin.yml b/src/plugin.yml
index 1b626f218..ca2667ec8 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -3,7 +3,7 @@ author: slipcor
 authors: [slipcor]
 prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
-version: 1.13.0
+version: 1.13.3
 api-version: 1.13
 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas

From de6a53623c0f8f3535263513d5fa7d43c4321555 Mon Sep 17 00:00:00 2001
From: Chris 
Date: Wed, 16 Jan 2019 19:42:05 +0100
Subject: [PATCH 006/115] v1.13.4 - various exceptions caught, addressing
 issues #351 and #352

---
 doc/changelog.md                              |  2 ++
 readme.md                                     |  2 +-
 src/net/slipcor/pvparena/PVPArena.java        |  2 ++
 src/net/slipcor/pvparena/core/Config.java     | 13 +++++++++-
 .../slipcor/pvparena/core/StringParser.java   | 25 ++++++++++++++----
 .../pvparena/goals/GoalBlockDestroy.java      | 17 ++++++------
 src/net/slipcor/pvparena/goals/GoalFlags.java | 26 +++++++++----------
 .../pvparena/goals/GoalPhysicalFlags.java     | 26 +++++++++----------
 .../pvparena/listeners/PlayerListener.java    |  3 +++
 src/plugin.yml                                |  2 +-
 10 files changed, 76 insertions(+), 42 deletions(-)

diff --git a/doc/changelog.md b/doc/changelog.md
index 7dd792952..91ac1fceb 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -1,5 +1,7 @@
 == PVP-Arena v1.13 Changelog
 
+- v1.13.4 - various exceptions caught, addressing issues #351 and #352
+- v1.13.3 - [WIP] the core game should be operational, region setup tested, blockrestore fixed
 - v1.13.2 - plugin.yml api update
 - v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions
 - v1.13.0 - slowly work our way to Spigot 1.13
diff --git a/readme.md b/readme.md
index 1063d2512..ee31df690 100644
--- a/readme.md
+++ b/readme.md
@@ -97,7 +97,7 @@ Users tutorials :
 
 ## Changelog
 
-- v1.13.2 - plugin.yml api update
+- v1.13.4 - various exceptions caught, addressing issues #351 and #352
 - [read more](doc/changelog.md)
 
 ***
diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java
index e62b6d324..bf5b76003 100644
--- a/src/net/slipcor/pvparena/PVPArena.java
+++ b/src/net/slipcor/pvparena/PVPArena.java
@@ -395,10 +395,12 @@ public boolean onCommand(final CommandSender sender, final Command cmd,
         return false;
     }
 
+    /*
     @Override
     public List onTabComplete(final CommandSender sender, final Command cmd, final String alias, final String[] args) {
         return TabManager.getMatches(sender, arenaCommands, globalCommands, args);
     }
+    */
 
     @Override
     public void onDisable() {
diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java
index e2498fabd..33793bfb8 100644
--- a/src/net/slipcor/pvparena/core/Config.java
+++ b/src/net/slipcor/pvparena/core/Config.java
@@ -759,7 +759,18 @@ public Material getMaterial(final CFG cfg, final Material def) {
 
     public ItemStack[] getItems(final CFG cfg) {
         final String path = cfg.getNode();
-        return this.cfg.getList(path).toArray(new ItemStack[0]);
+        try {
+            String test = this.cfg.getString(path);
+            if ("none".equals(test)) {
+                return new ItemStack[0];
+            }
+        } catch (Exception e) {
+        }
+        try {
+            return this.cfg.getList(path).toArray(new ItemStack[0]);
+        } catch (NullPointerException e) {
+            return new ItemStack[0];
+        }
     }
 
     public Set getKeys(final String path) {
diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java
index 74e0e8367..b2e94f27f 100644
--- a/src/net/slipcor/pvparena/core/StringParser.java
+++ b/src/net/slipcor/pvparena/core/StringParser.java
@@ -135,11 +135,26 @@ private static String getWoolEnumFromChatColorEnum(final String color) {
         return parseDyeColorToChatColor(color, false);
     }
 
-    public static Material getWoolFallbackMaterialFromString(final String color) {
-        for (Material mat : Material.values()) {
-            if (mat.name().contains("WOOL") && mat.name().contains(color.toUpperCase())) {
-                return mat;
-            }
+    public static Material getWoolFallbackMaterialFromString(final ChatColor color)  {
+        Map results = new HashMap<>();
+        results.put(ChatColor.BLACK, Material.BLACK_WOOL);
+        results.put(ChatColor.DARK_BLUE, Material.BLUE_WOOL);
+        results.put(ChatColor.DARK_AQUA, Material.LIGHT_BLUE_WOOL);
+        results.put(ChatColor.DARK_RED, Material.RED_WOOL);
+        results.put(ChatColor.DARK_PURPLE, Material.PURPLE_WOOL);
+        results.put(ChatColor.GOLD, Material.BROWN_WOOL);
+        results.put(ChatColor.GRAY, Material.LIGHT_GRAY_WOOL);
+        results.put(ChatColor.DARK_GRAY, Material.GRAY_WOOL);
+        results.put(ChatColor.BLUE, Material.LIGHT_BLUE_WOOL);
+        results.put(ChatColor.GREEN, Material.LIME_WOOL);
+        results.put(ChatColor.AQUA, Material.CYAN_WOOL);
+        results.put(ChatColor.RED, Material.PINK_WOOL);
+        results.put(ChatColor.LIGHT_PURPLE, Material.MAGENTA_WOOL);
+        results.put(ChatColor.YELLOW, Material.YELLOW_WOOL);
+        results.put(ChatColor.WHITE, Material.WHITE_WOOL);
+
+        if (results.containsKey(color)) {
+            return results.get(color);
         }
         DEBUG.i(">> Material defaulting '"+color+"' to BROWN_WOOL!! <<");
         return Material.BROWN_WOOL;
diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
index c915e786c..54ae618e5 100644
--- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
+++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
@@ -16,6 +16,7 @@
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
 import net.slipcor.pvparena.core.StringParser;
+import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -423,7 +424,7 @@ public void initate(final Player player) {
             final Set blocks = SpawnManager.getBlocksContaining(arena, "block");
 
             for (final PABlockLocation block : blocks) {
-                takeBlock(team.getColor().name(), block);
+                takeBlock(team.getColor(), block);
             }
         }
     }
@@ -448,7 +449,7 @@ public void parseStart() {
             final Set blocks = SpawnManager.getBlocksContaining(arena, "block");
 
             for (final PABlockLocation block : blocks) {
-                takeBlock(team.getColor().name(), block);
+                takeBlock(team.getColor(), block);
             }
         }
     }
@@ -495,11 +496,11 @@ public void setDefaults(final YamlConfiguration config) {
      * @param blockColor      the teamcolor to reset
      * @param paBlockLocation the location to take/reset
      */
-    void takeBlock(final String blockColor, final PABlockLocation paBlockLocation) {
+    void takeBlock(final ChatColor blockColor, final PABlockLocation paBlockLocation) {
         if (paBlockLocation == null) {
             return;
         }
-        if ("WOOL".equals(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE))) {
+        if (!Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(StringParser.getWoolFallbackMaterialFromString(blockColor));
@@ -622,10 +623,10 @@ public void onBlockBreak(final BlockBreakEvent event) {
                         "score:" + player.getName() + ':' + aPlayer.getArenaTeam().getName() + ":1");
                 Bukkit.getPluginManager().callEvent(gEvent);
                 class RunLater implements Runnable {
-                    String localColor;
+                    ChatColor localColor;
                     PABlockLocation localLoc;
 
-                    RunLater(final String color, final PABlockLocation loc) {
+                    RunLater(final ChatColor color, final PABlockLocation loc) {
                         localColor = color;
                         localLoc = loc;
                     }
@@ -642,7 +643,7 @@ && getLifeMap().get(blockTeam) > SpawnManager.getBlocksStartingWith(arena, block
                     Bukkit.getScheduler().runTaskLater(
                             PVPArena.instance,
                             new RunLater(
-                                    arena.getTeam(blockTeam).getColor().name(),
+                                    arena.getTeam(blockTeam).getColor(),
                                     new PABlockLocation(event.getBlock().getLocation())), 5L);
                 }
                 reduceLivesCheckEndAndCommit(arena, blockTeam);
@@ -693,7 +694,7 @@ public void onEntityExplode(final EntityExplodeEvent event) {
                                 "[PVP Arena] team unknown/no lives: " + blockTeam);
                         e.printStackTrace();
                     }
-                    takeBlock(arena.getTeam(blockTeam).getColor().name(),
+                    takeBlock(arena.getTeam(blockTeam).getColor(),
                             pb.getLocation());
 
                     reduceLivesCheckEndAndCommit(arena, blockTeam);
diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java
index 15ad00e97..4e94c0391 100644
--- a/src/net/slipcor/pvparena/goals/GoalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalFlags.java
@@ -239,10 +239,10 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
                     e.printStackTrace();
                 }
                 if ("touchdown".equals(flagTeam)) {
-                    takeFlag(ChatColor.BLACK.name(), false,
+                    takeFlag(ChatColor.BLACK, false,
                             SpawnManager.getBlockByExactName(arena, "touchdownflag"));
                 } else {
-                    takeFlag(arena.getTeam(flagTeam).getColor().name(), false,
+                    takeFlag(arena.getTeam(flagTeam).getColor(), false,
                             SpawnManager.getBlockByExactName(arena, flagTeam + "flag"));
                 }
                 removeEffects(player);
@@ -337,7 +337,7 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
                     player.getInventory().setHelmet(itemStack);
                     applyEffects(player);
 
-                    takeFlag(team.getColor().name(), true,
+                    takeFlag(team.getColor(), true,
                             new PABlockLocation(block.getLocation()));
                     getFlagMap().put(aTeam, player.getName()); // TODO move to
                     // "commit" ?
@@ -698,7 +698,7 @@ public void disconnect(final ArenaPlayer aPlayer) {
                 getHeadGearMap().remove(aPlayer.getName());
             }
 
-            takeFlag(ChatColor.BLACK.name(), false,
+            takeFlag(ChatColor.BLACK, false,
                     SpawnManager.getBlockByExactName(arena, "touchdownflag"));
 
             return;
@@ -716,7 +716,7 @@ public void disconnect(final ArenaPlayer aPlayer) {
             getHeadGearMap().remove(aPlayer.getName());
         }
 
-        takeFlag(flagTeam.getColor().name(), false,
+        takeFlag(flagTeam.getColor(), false,
                 SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
     }
 
@@ -823,9 +823,9 @@ public void initate(final Player player) {
             getLifeMap().put(aPlayer.getArenaTeam().getName(), arena.getArenaConfig()
                     .getInt(CFG.GOAL_FLAGS_LIVES));
 
-            takeFlag(team.getColor().name(), false,
+            takeFlag(team.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
-            takeFlag(ChatColor.BLACK.name(), false,
+            takeFlag(ChatColor.BLACK, false,
                     SpawnManager.getBlockByExactName(arena, "touchdownflag"));
         }
     }
@@ -865,7 +865,7 @@ public void parsePlayerDeath(final Player player,
                 getHeadGearMap().remove(aPlayer.getName());
             }
 
-            takeFlag(ChatColor.BLACK.name(), false,
+            takeFlag(ChatColor.BLACK, false,
                     SpawnManager.getBlockByExactName(arena, "touchdownflag"));
             return;
         }
@@ -880,7 +880,7 @@ && getHeadGearMap().get(player.getName()) != null) {
             getHeadGearMap().remove(player.getName());
         }
 
-        takeFlag(flagTeam.getColor().name(), false,
+        takeFlag(flagTeam.getColor(), false,
                 SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
     }
 
@@ -894,10 +894,10 @@ public void parseStart() {
                 getLifeMap().put(team.getName(),
                         arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES, 3));
             }
-            takeFlag(team.getColor().name(), false,
+            takeFlag(team.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
         }
-        takeFlag(ChatColor.BLACK.name(), false,
+        takeFlag(ChatColor.BLACK, false,
                 SpawnManager.getBlockByExactName(arena, "touchdownflag"));
     }
 
@@ -998,11 +998,11 @@ public void setDefaults(final YamlConfiguration config) {
      * @param take            true if take, else reset
      * @param paBlockLocation the location to take/reset
      */
-    void takeFlag(final String flagColor, final boolean take, final PABlockLocation paBlockLocation) {
+    void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocation paBlockLocation) {
         if (paBlockLocation == null) {
             return;
         }
-        if (!"WOOL".equals(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE))) {
+        if (!Utils.isSubType(Material.getMaterial(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(
diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
index 111331618..58ebaaf24 100644
--- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
@@ -252,10 +252,10 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
                     e.printStackTrace();
                 }
                 if ("touchdown".equals(flagTeam)) {
-                    takeFlag(ChatColor.BLACK.name(), false,
+                    takeFlag(ChatColor.BLACK, false,
                             SpawnManager.getBlockByExactName(arena, "touchdownflag"));
                 } else {
-                    takeFlag(arena.getTeam(flagTeam).getColor().name(), false,
+                    takeFlag(arena.getTeam(flagTeam).getColor(), false,
                             SpawnManager.getBlockByExactName(arena, flagTeam + "flag"));
                 }
                 removeEffects(player);
@@ -630,7 +630,7 @@ public void disconnect(final ArenaPlayer aPlayer) {
                     getHeadGearMap().remove(aPlayer.getName());
                 }
 
-                takeFlag(ChatColor.BLACK.name(), false,
+                takeFlag(ChatColor.BLACK, false,
                         SpawnManager.getBlockByExactName(arena, "touchdownflag"));
             }
         } else {
@@ -647,7 +647,7 @@ public void disconnect(final ArenaPlayer aPlayer) {
                 getHeadGearMap().remove(aPlayer.getName());
             }
 
-            takeFlag(flagTeam.getColor().name(), false,
+            takeFlag(flagTeam.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
         }
     }
@@ -758,9 +758,9 @@ public void initate(final Player player) {
             getLifeMap().put(aPlayer.getArenaTeam().getName(), arena.getArenaConfig()
                     .getInt(CFG.GOAL_FLAGS_LIVES));
 
-            takeFlag(team.getColor().name(), false,
+            takeFlag(team.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
-            takeFlag(ChatColor.BLACK.name(), false,
+            takeFlag(ChatColor.BLACK, false,
                     SpawnManager.getBlockByExactName(arena, "touchdownflag"));
         }
     }
@@ -798,7 +798,7 @@ public void parsePlayerDeath(final Player player,
                     getHeadGearMap().remove(aPlayer.getName());
                 }
 
-                takeFlag(ChatColor.BLACK.name(), false,
+                takeFlag(ChatColor.BLACK, false,
                         SpawnManager.getBlockByExactName(arena, "touchdownflag"));
             }
         } else {
@@ -813,7 +813,7 @@ && getHeadGearMap().get(player.getName()) != null) {
                 getHeadGearMap().remove(player.getName());
             }
 
-            takeFlag(flagTeam.getColor().name(), false,
+            takeFlag(flagTeam.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
         }
     }
@@ -828,10 +828,10 @@ public void parseStart() {
                 getLifeMap().put(team.getName(),
                         arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES, 3));
             }
-            takeFlag(team.getColor().name(), false,
+            takeFlag(team.getColor(), false,
                     SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
         }
-        takeFlag(ChatColor.BLACK.name(), false,
+        takeFlag(ChatColor.BLACK, false,
                 SpawnManager.getBlockByExactName(arena, "touchdownflag"));
     }
 
@@ -934,11 +934,11 @@ public void setDefaults(final YamlConfiguration config) {
      * @param take            true if take, else reset
      * @param paBlockLocation the location to take/reset
      */
-    void takeFlag(final String flagColor, final boolean take, final PABlockLocation paBlockLocation) {
+    void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocation paBlockLocation) {
         if (paBlockLocation == null) {
             return;
         }
-        if (!"WOOL".equals(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE))) {
+        if (!Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(
@@ -1088,7 +1088,7 @@ public void onFlagClaim(final BlockBreakEvent event) {
                 player.getInventory().setHelmet(itemStack);
                 applyEffects(player);
 
-                takeFlag(team.getColor().name(), true,
+                takeFlag(team.getColor(), true,
                         new PABlockLocation(block.getLocation()));
                 getFlagMap().put(aTeam, player.getName());
 
diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java
index dc1192e8a..6b7b5395e 100644
--- a/src/net/slipcor/pvparena/listeners/PlayerListener.java
+++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java
@@ -795,6 +795,9 @@ public void onPlayerRespawn(final PlayerRespawnEvent event) {
 
     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
     public void onPlayerPickupItem(final EntityPickupItemEvent event) {
+        if (!(event.getEntity() instanceof Player)) {
+            return;
+        }
         final Player player = (Player) event.getEntity();
 
         if (willBeCancelled(player, event)) {
diff --git a/src/plugin.yml b/src/plugin.yml
index ca2667ec8..8fc9c75bb 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -3,7 +3,7 @@ author: slipcor
 authors: [slipcor]
 prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
-version: 1.13.3
+version: 1.13.4
 api-version: 1.13
 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas

From 6bfffe089c926f63272c2ef580ef14d6ab5e35fe Mon Sep 17 00:00:00 2001
From: Chris 
Date: Thu, 17 Jan 2019 00:18:30 +0100
Subject: [PATCH 007/115] v1.13.5 - address #355 - set some more scoreboard
 settings to hopefully get colors going

---
 doc/changelog.md                          | 1 +
 readme.md                                 | 2 +-
 src/net/slipcor/pvparena/arena/Arena.java | 8 ++++++++
 src/plugin.yml                            | 2 +-
 4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/doc/changelog.md b/doc/changelog.md
index 91ac1fceb..c7b7f70c2 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -1,5 +1,6 @@
 == PVP-Arena v1.13 Changelog
 
+- v1.13.5 - address #355 - set some more scoreboard settings to hopefully get colors going
 - v1.13.4 - various exceptions caught, addressing issues #351 and #352
 - v1.13.3 - [WIP] the core game should be operational, region setup tested, blockrestore fixed
 - v1.13.2 - plugin.yml api update
diff --git a/readme.md b/readme.md
index ee31df690..c4494df0f 100644
--- a/readme.md
+++ b/readme.md
@@ -97,7 +97,7 @@ Users tutorials :
 
 ## Changelog
 
-- v1.13.4 - various exceptions caught, addressing issues #351 and #352
+- v1.13.5 - address #355 - set some more scoreboard settings to hopefully get colors going
 - [read more](doc/changelog.md)
 
 ***
diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index 1b2dcc689..a6a9b9065 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -555,6 +555,8 @@ private Scoreboard getSpecialScoreboard() {
                         bukkitTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
                     }
                     bukkitTeam.setPrefix(team.getColor().toString());
+                    bukkitTeam.setSuffix(ChatColor.RESET.toString());
+                    bukkitTeam.setColor(team.getColor());
                     bukkitTeam.addEntry(team.getName());
                     bukkitTeam.setAllowFriendlyFire(getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL));
 
@@ -597,6 +599,8 @@ private Scoreboard getStandardScoreboard() {
             for (final ArenaTeam team : getTeams()) {
                 final Team sTeam = scoreboard.registerNewTeam(team.getName());
                 sTeam.setPrefix(team.getColor().toString());
+                sTeam.setSuffix(ChatColor.RESET.toString());
+                sTeam.setColor(team.getColor());
                 sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
                 if (!getArenaConfig().getBoolean(CFG.PLAYER_COLLISION)) {
                     sTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
@@ -1637,6 +1641,8 @@ public void run() {
                         scoreboard.registerNewTeam(team.getName());
                         final Team bukkitTeam = scoreboard.getTeam(team.getName());
                         bukkitTeam.setPrefix(team.getColor().toString());
+                        bukkitTeam.setSuffix(ChatColor.RESET.toString());
+                        bukkitTeam.setColor(team.getColor());
                         bukkitTeam.addEntry(team.getName());
                         bukkitTeam.setAllowFriendlyFire(getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL));
                         bukkitTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
@@ -1675,6 +1681,8 @@ public void run() {
             }
             final Team sTeam = board.registerNewTeam(team.getName());
             sTeam.setPrefix(team.getColor().toString());
+            sTeam.setColor(team.getColor());
+            sTeam.setSuffix(ChatColor.RESET.toString());
             sTeam.addEntry(player.getName());
             sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
         }
diff --git a/src/plugin.yml b/src/plugin.yml
index 8fc9c75bb..b3e9beb33 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -3,7 +3,7 @@ author: slipcor
 authors: [slipcor]
 prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
-version: 1.13.4
+version: 1.13.5
 api-version: 1.13
 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas

From f5d0135f368cf57047221e3d57f2cb6b389f2740 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 14 Mar 2019 20:49:42 +0100
Subject: [PATCH 008/115] fix blockDestroy takeBlock

---
 src/net/slipcor/pvparena/goals/GoalBlockDestroy.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
index 54ae618e5..8776b2bea 100644
--- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
+++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
@@ -500,7 +500,7 @@ void takeBlock(final ChatColor blockColor, final PABlockLocation paBlockLocation
         if (paBlockLocation == null) {
             return;
         }
-        if (!Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE)), Material.WHITE_WOOL)) {
+        if (Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(StringParser.getWoolFallbackMaterialFromString(blockColor));

From 19776802e475e243ba73b1b94e0c8331afb24cf7 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 21 Feb 2019 22:41:51 +0100
Subject: [PATCH 009/115] v1.13.6 - Change inventory serializer

---
 pom.xml                                       |   2 +-
 .../slipcor/pvparena/arena/ArenaClass.java    |  17 +-
 .../slipcor/pvparena/commands/PAA_Class.java  |   9 +-
 .../pvparena/commands/PAA_PlayerClass.java    |  11 +-
 src/net/slipcor/pvparena/core/Config.java     |   9 +-
 .../slipcor/pvparena/core/ItemStackUtils.java | 146 ++++++++++++++++++
 src/net/slipcor/pvparena/core/Utils.java      |  29 +++-
 .../managers/ConfigurationManager.java        |  10 +-
 src/plugin.yml                                |   2 +-
 9 files changed, 204 insertions(+), 31 deletions(-)
 create mode 100644 src/net/slipcor/pvparena/core/ItemStackUtils.java

diff --git a/pom.xml b/pom.xml
index c38e99bd5..38ce76923 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,7 @@
 		
 			org.bukkit
 			bukkit
-			1.13.1-R0.1-SNAPSHOT
+			1.13.2-R0.1-SNAPSHOT
 			jar
 			provided
 		
diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java
index 95912da0a..37fdc9ea0 100644
--- a/src/net/slipcor/pvparena/arena/ArenaClass.java
+++ b/src/net/slipcor/pvparena/arena/ArenaClass.java
@@ -3,7 +3,6 @@
 import net.slipcor.pvparena.PVPArena;
 import net.slipcor.pvparena.classes.PABlockLocation;
 import net.slipcor.pvparena.core.Debug;
-import net.slipcor.pvparena.core.StringParser;
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.block.Chest;
@@ -12,13 +11,14 @@
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.PlayerInventory;
-import org.bukkit.inventory.meta.SpawnEggMeta;
 import org.bukkit.plugin.IllegalPluginAccessException;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.*;
 
+import static net.slipcor.pvparena.core.ItemStackUtils.getItemStacksFromConfig;
+
 /**
  * 
Arena Class class
*

@@ -127,16 +127,17 @@ public static void addGlobalClasses() { ItemStack[] armors; try { - items = cfg.getConfigurationSection("classes").getConfigurationSection(className) - .getList("items").toArray(new ItemStack[0]); - offHand = cfg.getConfigurationSection("classes").getConfigurationSection(className) - .getList("items").toArray(new ItemStack[0])[0]; - armors = cfg.getConfigurationSection("classes").getConfigurationSection(className) - .getList("items").toArray(new ItemStack[0]); + items = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items")); + offHand = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items"))[0]; + armors = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className) + .getList("items")); } catch (final Exception e) { Bukkit.getLogger().severe( "[PVP Arena] Error while parsing class, skipping: " + className); + e.printStackTrace(); continue; } final String classChest; diff --git a/src/net/slipcor/pvparena/commands/PAA_Class.java b/src/net/slipcor/pvparena/commands/PAA_Class.java index 507232140..8b13862a9 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Class.java +++ b/src/net/slipcor/pvparena/commands/PAA_Class.java @@ -8,7 +8,6 @@ import net.slipcor.pvparena.core.Help.HELP; import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; -import net.slipcor.pvparena.core.StringParser; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -17,6 +16,8 @@ import java.util.Collections; import java.util.List; +import static net.slipcor.pvparena.core.Utils.getSerializableItemStacks; + /** *

  * PVP Arena CLASS Command class
@@ -69,9 +70,9 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
             final Player player = (Player) sender;
             final List items = new ArrayList<>();
 
-            arena.getArenaConfig().setManually("classitems." + args[1] + ".items", player.getInventory().getStorageContents());
-            arena.getArenaConfig().setManually("classitems." + args[1] + ".offhand", new ItemStack[]{player.getInventory().getItemInOffHand()});
-            arena.getArenaConfig().setManually("classitems." + args[1] + ".armor", player.getInventory().getArmorContents());
+            arena.getArenaConfig().setManually("classitems." + args[1] + ".items", getSerializableItemStacks(player.getInventory().getStorageContents()));
+            arena.getArenaConfig().setManually("classitems." + args[1] + ".offhand", getSerializableItemStacks(player.getInventory().getItemInOffHand()));
+            arena.getArenaConfig().setManually("classitems." + args[1] + ".armor", getSerializableItemStacks(player.getInventory().getArmorContents()));
             arena.getArenaConfig().save();
 
             arena.addClass(args[1], player.getInventory().getStorageContents(), player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents());
diff --git a/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java b/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java
index 89a3b812e..13439c8f3 100644
--- a/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java
+++ b/src/net/slipcor/pvparena/commands/PAA_PlayerClass.java
@@ -7,15 +7,14 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
-import org.bukkit.inventory.ItemStack;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import static net.slipcor.pvparena.core.Utils.getSerializableItemStacks;
+
 /**
  * 
  * PVP Arena PLAYERCLASS Command class
@@ -67,9 +66,9 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
 
         if ("save".equalsIgnoreCase(args[0])) {
 
-            arena.getArenaConfig().setManually("classitems." + className + ".items", player.getInventory().getStorageContents());
-            arena.getArenaConfig().setManually("classitems." + className + ".offhand", new ItemStack[]{player.getInventory().getItemInOffHand()});
-            arena.getArenaConfig().setManually("classitems." + className + ".armor", player.getInventory().getArmorContents());
+            arena.getArenaConfig().setManually("classitems." + className + ".items", getSerializableItemStacks(player.getInventory().getStorageContents()));
+            arena.getArenaConfig().setManually("classitems." + className + ".offhand",  getSerializableItemStacks(player.getInventory().getItemInOffHand()));
+            arena.getArenaConfig().setManually("classitems." + className + ".armor", getSerializableItemStacks(player.getInventory().getArmorContents()));
             arena.getArenaConfig().save();
 
             arena.addClass(className, player.getInventory().getStorageContents(), player.getInventory().getItemInOffHand(), player.getInventory().getArmorContents());
diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java
index 33793bfb8..117453acb 100644
--- a/src/net/slipcor/pvparena/core/Config.java
+++ b/src/net/slipcor/pvparena/core/Config.java
@@ -20,6 +20,9 @@
 import java.io.File;
 import java.util.*;
 
+import static net.slipcor.pvparena.core.ItemStackUtils.getItemStacksFromConfig;
+import static net.slipcor.pvparena.core.Utils.getSerializableItemStacks;
+
 /**
  * 
  * Configuration class
@@ -462,7 +465,7 @@ public static CFG getByNode(final String node) {
 
         CFG(final String node, final ItemStack[] value, final boolean multiple, final String source) {
             this.node = node;
-            this.value = value;
+            this.value = getSerializableItemStacks(value);
             type = multiple ? "items" : "material";
             module = source;
         }
@@ -761,13 +764,13 @@ public ItemStack[] getItems(final CFG cfg) {
         final String path = cfg.getNode();
         try {
             String test = this.cfg.getString(path);
-            if ("none".equals(test)) {
+            if ("none".equalsIgnoreCase(test)) {
                 return new ItemStack[0];
             }
         } catch (Exception e) {
         }
         try {
-            return this.cfg.getList(path).toArray(new ItemStack[0]);
+            return getItemStacksFromConfig(this.cfg.getList(path));
         } catch (NullPointerException e) {
             return new ItemStack[0];
         }
diff --git a/src/net/slipcor/pvparena/core/ItemStackUtils.java b/src/net/slipcor/pvparena/core/ItemStackUtils.java
new file mode 100644
index 000000000..197c14907
--- /dev/null
+++ b/src/net/slipcor/pvparena/core/ItemStackUtils.java
@@ -0,0 +1,146 @@
+package net.slipcor.pvparena.core;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Color;
+import org.bukkit.Material;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.inventory.meta.LeatherArmorMeta;
+
+import java.util.*;
+
+import static org.bukkit.configuration.serialization.ConfigurationSerialization.deserializeObject;
+
+public class ItemStackUtils  {
+    /**
+     * List of "meta-type" config keys which can be drop
+     */
+    private enum HandledMetaType {
+        POTION, ENCHANTED, BOOK_SIGNED, BOOK, BANNER, MAP, FIREWORK, LEATHER_ARMOR, UNSPECIFIC
+    }
+
+    private static boolean isAnHandledMetaType(String metaTypeString) {
+        try{
+            HandledMetaType.valueOf(metaTypeString);
+            return true;
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Check the meta keyset to deduce which meta-type is associated
+     * @param keySet The meta config node values
+     * @return Right "meta-type" value
+     */
+    private static HandledMetaType getRightMetaType(Collection keySet) {
+        if(keySet.contains("potion-type")) {
+            return HandledMetaType.POTION;
+        }
+        if(keySet.contains("stored-enchants")) {
+            return HandledMetaType.ENCHANTED;
+        }
+        if(keySet.contains("map-id")) {
+            return HandledMetaType.MAP;
+        }
+        if(keySet.contains("patterns")) {
+            return HandledMetaType.BANNER;
+        }
+        if(keySet.contains("pages")) {
+            if(keySet.contains("author")) {
+                return HandledMetaType.BOOK_SIGNED;
+            }
+            return HandledMetaType.BOOK;
+        }
+        if(keySet.contains("firework-effects")) {
+            return HandledMetaType.FIREWORK;
+        }
+        if(keySet.contains("color")) {
+            return HandledMetaType.LEATHER_ARMOR;
+        }
+        return HandledMetaType.UNSPECIFIC;
+    }
+
+
+    /**
+     * Pseudo-serializer which creates a map version of objects in order to prettify the yaml after serialization
+     * @param itemStack A bukkit ItemStack object
+     * @return Serializable map
+     */
+    public static Map getItemStackMap(ItemStack itemStack) {
+        Map result = new LinkedHashMap<>();
+        result.put("type", itemStack.getType().name());
+        if (itemStack.getAmount() != 1) {
+            result.put("amount", itemStack.getAmount());
+        }
+
+        ItemMeta meta = itemStack.getItemMeta();
+        if (!Bukkit.getItemFactory().equals(meta, null)) {
+            Map metaMap = new LinkedHashMap<>(meta.serialize());
+            if(isAnHandledMetaType(metaMap.get("meta-type").toString())) {
+                metaMap.remove("meta-type");
+
+                if(meta instanceof LeatherArmorMeta) {
+                    metaMap.put("color", ((LeatherArmorMeta) meta).getColor().serialize());
+                }
+            }
+            result.put("meta", metaMap);
+        }
+
+        return result;
+    }
+
+    /**
+     * A custom deserializer which convert prettified yaml config to bukkit objects
+     * Mainly based on the bukkit ConfigurationSerializable deserializer
+     * @param args An ItemStack config node
+     * @return A bukkit ItemStack object
+     */
+    private static ItemStack deserialize(Map args) {
+        int amount = 1;
+
+        Material type = Material.getMaterial((String) args.get("type"));
+
+        if (args.containsKey("amount")) {
+            amount = ((Number) args.get("amount")).intValue();
+        }
+
+        ItemStack result = new ItemStack(type, amount);
+
+        if (args.containsKey("meta")) {
+            Map metaMap = new LinkedHashMap<>((Map) args.get("meta"));
+            metaMap.put("==", ItemMeta.class.getSimpleName());
+            if(!metaMap.containsKey("meta-type")) {
+                metaMap.put("meta-type", getRightMetaType(metaMap.keySet()).name());
+
+                //Simplify Leather Armour colors
+                if(metaMap.containsKey("color")) {
+                    Color color = Color.deserialize((Map) metaMap.get("color"));
+                    metaMap.put("color", color);
+                }
+            }
+
+
+            ConfigurationSerializable raw = deserializeObject(metaMap);
+            if (raw instanceof ItemMeta) {
+                result.setItemMeta((ItemMeta) raw);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Deserialize an ItemSTack list config node
+     * @param mapList List of ItemStack nodes
+     * @return An array of bukkit ItemStack objects
+     */
+    public static ItemStack[] getItemStacksFromConfig(List mapList) {
+        ItemStack[] result = new ItemStack[mapList.size()];
+        for(int i = 0; i < mapList.size(); i++) {
+            result[i] = deserialize((Map) mapList.get(i));
+        }
+        return result;
+    }
+}
diff --git a/src/net/slipcor/pvparena/core/Utils.java b/src/net/slipcor/pvparena/core/Utils.java
index f14045cbf..7d92f7ed8 100644
--- a/src/net/slipcor/pvparena/core/Utils.java
+++ b/src/net/slipcor/pvparena/core/Utils.java
@@ -4,18 +4,39 @@
 import org.bukkit.Material;
 import org.bukkit.inventory.ItemStack;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static net.slipcor.pvparena.core.ItemStackUtils.getItemStackMap;
+
 public final class Utils {
     private Utils() {
     }
 
-    public static ItemStack[] getItemStacksFromMaterials(Material... mats) {
-        ItemStack[] result = new ItemStack[mats.length];
-        for (int i=0; i< mats.length; i++) {
-            result[i] = new ItemStack(mats[i], mats[i]==Material.ARROW?64:1);
+    public static List> getItemStacksFromMaterials(Material... mats) {
+        List> result = new ArrayList<>();
+        for(Material mat : mats) {
+            result.add(getItemStackMap(new ItemStack(mat, mat == Material.ARROW ? 64 : 1)));
         }
         return result;
     }
 
+
+    public static List> getSerializableItemStacks(ItemStack[] itemStacks) {
+        List> result = new ArrayList<>();
+        for(ItemStack itemStack : itemStacks) {
+            if(itemStack != null) {
+                result.add(getItemStackMap(itemStack));
+            }
+        }
+        return result;
+    }
+
+    public static List> getSerializableItemStacks(ItemStack itemStack) {
+        return getSerializableItemStacks(new ItemStack[]{itemStack});
+    }
+
     public static Material getWoolMaterialFromChatColor(final ChatColor color) {
         /*
         Unsupported:
diff --git a/src/net/slipcor/pvparena/managers/ConfigurationManager.java b/src/net/slipcor/pvparena/managers/ConfigurationManager.java
index 9b237417a..58e8124e5 100644
--- a/src/net/slipcor/pvparena/managers/ConfigurationManager.java
+++ b/src/net/slipcor/pvparena/managers/ConfigurationManager.java
@@ -11,7 +11,6 @@
 import net.slipcor.pvparena.core.Config.CFG;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
 import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModule;
@@ -25,6 +24,8 @@
 
 import java.util.*;
 
+import static net.slipcor.pvparena.core.ItemStackUtils.getItemStacksFromConfig;
+
 /**
  * 
  * Configuration Manager class
@@ -201,13 +202,14 @@ public static boolean configParse(final Arena arena, final Config cfg) {
             ItemStack[] armors = new ItemStack[]{new ItemStack(Material.AIR, 1)};
 
             try {
-                items = config.getList("classitems."+stringObjectEntry1.getKey()+".items").toArray(new ItemStack[0]);
-                offHand = config.getList("classitems."+stringObjectEntry1.getKey()+".offhand").toArray(new ItemStack[]{new ItemStack(Material.AIR, 1)})[0];
-                armors = config.getList("classitems."+stringObjectEntry1.getKey()+".armor").toArray(new ItemStack[0]);
+                items = getItemStacksFromConfig(config.getList("classitems."+stringObjectEntry1.getKey()+".items"));
+                offHand = getItemStacksFromConfig(config.getList("classitems."+stringObjectEntry1.getKey()+".offhand"))[0];
+                armors = getItemStacksFromConfig(config.getList("classitems."+stringObjectEntry1.getKey()+".armor"));
             } catch (final Exception e) {
                 Bukkit.getLogger().severe(
                         "[PVP Arena] Error while parsing class, skipping: "
                                 + stringObjectEntry1.getKey());
+                        arena.getDebugger().i(e.getMessage());
                 continue;
             }
             try {
diff --git a/src/plugin.yml b/src/plugin.yml
index b3e9beb33..0d5101d63 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -3,7 +3,7 @@ author: slipcor
 authors: [slipcor]
 prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
-version: 1.13.5
+version: 1.13.6
 api-version: 1.13
 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas

From e04c5355f583155925c8538117b5a4867b3bcebb Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 21 Mar 2019 21:11:00 +0100
Subject: [PATCH 010/115] v1.13.7 - manage item errors in deserializer

---
 .../slipcor/pvparena/core/ItemStackUtils.java | 43 +++++++++++--------
 src/plugin.yml                                |  2 +-
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/net/slipcor/pvparena/core/ItemStackUtils.java b/src/net/slipcor/pvparena/core/ItemStackUtils.java
index 197c14907..4a71c65b7 100644
--- a/src/net/slipcor/pvparena/core/ItemStackUtils.java
+++ b/src/net/slipcor/pvparena/core/ItemStackUtils.java
@@ -1,5 +1,6 @@
 package net.slipcor.pvparena.core;
 
+import net.slipcor.pvparena.PVPArena;
 import org.bukkit.Bukkit;
 import org.bukkit.Color;
 import org.bukkit.Material;
@@ -102,33 +103,37 @@ private static ItemStack deserialize(Map args) {
 
         Material type = Material.getMaterial((String) args.get("type"));
 
-        if (args.containsKey("amount")) {
-            amount = ((Number) args.get("amount")).intValue();
-        }
+        if(type != null) {
+            if (args.containsKey("amount")) {
+                amount = ((Number) args.get("amount")).intValue();
+            }
 
-        ItemStack result = new ItemStack(type, amount);
+            ItemStack result = new ItemStack(type, amount);
 
-        if (args.containsKey("meta")) {
-            Map metaMap = new LinkedHashMap<>((Map) args.get("meta"));
-            metaMap.put("==", ItemMeta.class.getSimpleName());
-            if(!metaMap.containsKey("meta-type")) {
-                metaMap.put("meta-type", getRightMetaType(metaMap.keySet()).name());
+            if (args.containsKey("meta")) {
+                Map metaMap = new LinkedHashMap<>((Map) args.get("meta"));
+                metaMap.put("==", ItemMeta.class.getSimpleName());
+                if(!metaMap.containsKey("meta-type")) {
+                    metaMap.put("meta-type", getRightMetaType(metaMap.keySet()).name());
 
-                //Simplify Leather Armour colors
-                if(metaMap.containsKey("color")) {
-                    Color color = Color.deserialize((Map) metaMap.get("color"));
-                    metaMap.put("color", color);
+                    //Simplify Leather Armour colors
+                    if(metaMap.containsKey("color")) {
+                        Color color = Color.deserialize((Map) metaMap.get("color"));
+                        metaMap.put("color", color);
+                    }
                 }
-            }
 
 
-            ConfigurationSerializable raw = deserializeObject(metaMap);
-            if (raw instanceof ItemMeta) {
-                result.setItemMeta((ItemMeta) raw);
+                ConfigurationSerializable raw = deserializeObject(metaMap);
+                if (raw instanceof ItemMeta) {
+                    result.setItemMeta((ItemMeta) raw);
+                }
             }
+            return result;
+        } else {
+            PVPArena.instance.getLogger().warning("Invalid item type : " + args.get("type"));
+            return new ItemStack(Material.AIR);
         }
-
-        return result;
     }
 
     /**
diff --git a/src/plugin.yml b/src/plugin.yml
index 0d5101d63..b85b948cd 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -3,7 +3,7 @@ author: slipcor
 authors: [slipcor]
 prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
-version: 1.13.6
+version: 1.13.7
 api-version: 1.13
 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas

From 3ef4b52fd1161c4d727562f4d1cf2efcedb68dd2 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 25 Mar 2019 21:51:22 +0100
Subject: [PATCH 011/115] update items readme

---
 doc/items.md | 134 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 97 insertions(+), 37 deletions(-)

diff --git a/doc/items.md b/doc/items.md
index dd95164c2..2de209fac 100644
--- a/doc/items.md
+++ b/doc/items.md
@@ -1,38 +1,98 @@
 
-Dealing with item strings is a pain, I know. But as there are so many different ways, amount, data value, enchantment, it was hard to implement that inside a short sentence ;)
-
-JavaDoc : [Bukkit Material ENUMs 1.8.8](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html)
-
-## Examples:
-
-**Swiftness Potion II**
-
-- items: 373~8226
-
-**5x Colored wool**
-
-- items: 35~4:5
-
-Minecraft Wiki : [Data Values => Potions](http://minecraft.gamepedia.com/Data_values#Potions)
-
-
-***
-
-
-If you want to add enchantments, you will need to add a pipe as separator : `|`
-
-## Examples:
-
-**Diamond Sword with Sharpness LVL 3**
-
-- items: 276|16~3
-
-**Iron Pick with Efficiency I**
-
-- items: 257|32~1
-
-**Iron Pick with Efficiency I and Sharpness III**
-
-- items: 257|32~1|16~3
-
-Minecraft Wiki : [Enchanting](http://minecraft.gamepedia.com/Enchantment#Enchantment_Types)
+If you are brave, you can set items for inventories or enhancements directly in 
+arena config files. It's quite verbose but not really hard. If you aren't at ease with YAML
+config files, please use [/pa class](commands/class.md) commands.
+
+JavaDoc : [Bukkit Material ENUMs](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html)
+
+## Create a simple item list:
+
+In order to create a basic list of items (without enchant or any enhancements), create a simple
+YAML list with two keys : "type" and "amount".
+
+"Type" is the items name, it **must be** from the material enum page - *cf. above link*
+
+"amount" is the number of items you want to give. *This parameter is optional and,
+ if not set, equals to 1 (and 64 for arrows)*
+ 
+#### Example:
+
+```yaml
+items:
+    - type: BOW
+    - type: ARROW
+      amount: 64
+    - type: IRON_SWORD
+    - type: COOKED_BEEF
+      amount: 2
+```
+
+## Create an advanced item list
+
+The principle is the same, you just have to add a **meta** key to list items and add the good 
+properties.
+
+### Enchantments
+
+You can add enchantments according the following instance. The enchantment names must be picked
+from this page : [Bukkit enchantments](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/enchantments/Enchantment.html) 
+
+```yaml
+  myclassname:
+    items:
+    - type: IRON_SWORD
+      meta:
+        enchants:
+          DURABILITY: 3
+          KNOCKBACK: 1
+    offhand:
+    - type: SHIELD
+    armor:
+    - type: IRON_CHESTPLATE
+      meta:
+        enchants:
+          PROTECTION_ENVIRONMENTAL: 3
+```
+
+### Custom names
+
+Add a *display-name* key with the name you want, it works with every item.
+
+```yaml
+    - type: COOKED_PORKCHOP
+      amount: 8
+      meta:
+        display-name: Delicious bacon
+``` 
+
+### Potion effects
+
+You can use potion effects on these four items :
+* POTION
+* SPLASH_POTION
+* LINGERING_POTION
+* TIPPED_ARROW
+
+You can set a potion type like in the following example :
+
+```yaml
+    - type: TIPPED_ARROW
+      amount: 5
+      meta:
+        potion-type: minecraft:slowness
+    - type: SPLASH_POTION
+      meta:
+        potion-type: minecraft:healing
+    - type: LINGERING_POTION
+      amount: 2
+      meta:
+        potion-type: minecraft:strong_speed
+    - type: POTION
+      meta:
+        potion-type: minecraft:long_invisibilty
+``` 
+
+You can get potion effects on this page : [Minecraft effect list](https://www.digminecraft.com/lists/effect_list_pc.php)
+
+Be careful to prefix the effect with "minecraft:". You can give level 2 potions (like heath II) 
+prefixing the effect with **strong_** or long duration potions with the **long_**

From 29b58c0feceade4f0f527c62a9e1f9952e14ec60 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 26 Mar 2019 21:25:42 +0100
Subject: [PATCH 012/115] v1.13.8 - fix /pa set command to use new serializer

---
 src/net/slipcor/pvparena/commands/PAA_Set.java | 7 ++++---
 src/plugin.yml                                 | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/net/slipcor/pvparena/commands/PAA_Set.java b/src/net/slipcor/pvparena/commands/PAA_Set.java
index f8ca35cef..1ad2bbc7f 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Set.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Set.java
@@ -6,7 +6,6 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
 import org.bukkit.ChatColor;
 import org.bukkit.Material;
 import org.bukkit.command.CommandSender;
@@ -18,6 +17,8 @@
 import java.util.List;
 import java.util.Map;
 
+import static net.slipcor.pvparena.core.Utils.getSerializableItemStacks;
+
 /**
  * 
PVP Arena SET Command class
*

@@ -201,7 +202,7 @@ private void set(final CommandSender player, final Arena arena, final String nod if (player instanceof Player) { ItemStack[] items = new ItemStack[]{(((Player) player).getEquipment().getItemInMainHand())}; - arena.getArenaConfig().setManually(node, items); + arena.getArenaConfig().setManually(node, getSerializableItemStacks(items)); arena.msg( player, Language.parse(arena, MSG.SET_DONE, node, items[0].getType().name())); @@ -214,7 +215,7 @@ private void set(final CommandSender player, final Arena arena, final String nod if (player instanceof Player) { final ItemStack[] items = ((Player) player).getInventory().getContents(); - arena.getArenaConfig().setManually(node, items); + arena.getArenaConfig().setManually(node, getSerializableItemStacks(items)); arena.msg( player, Language.parse(arena, MSG.SET_DONE, node, "inventory")); diff --git a/src/plugin.yml b/src/plugin.yml index b85b948cd..4252979c5 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -3,7 +3,7 @@ author: slipcor authors: [slipcor] prefix: PVP Arena main: net.slipcor.pvparena.PVPArena -version: 1.13.7 +version: 1.13.8 api-version: 1.13 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot] description: create, manage and enhance PvP arenas From 86a22497cd3bfda13ae8764cae17a665ab6e411b Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 26 Mar 2019 21:24:35 +0100 Subject: [PATCH 013/115] update readme --- doc/update-from-1-3-x.md | 23 +++++++++++++++++++++++ readme.md | 9 ++++----- 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 doc/update-from-1-3-x.md diff --git a/doc/update-from-1-3-x.md b/doc/update-from-1-3-x.md new file mode 100644 index 000000000..53ea8d859 --- /dev/null +++ b/doc/update-from-1-3-x.md @@ -0,0 +1,23 @@ +# Upgrading from 1.3.x + +If you want to upgrade your arena configurations to PVPArena 1.13 version or above, you have +to update two things : Item Lists and Schematics + +## Item lists + +Probably the worst thing to upgrade, just clear the inventories of your arena classes and +re-create them. Be also careful to remove items list of pvparena modules like **chestfiller** +or **blockdissolve**. + +## WorldEdit + +You have to remove Worldedit schematics too. A big part of blocks will not be pasted if you +keep it as it is and chest orientation will be broken. + +So just remove your schematics files and re-create them with `/pa [arena] regsave [regionname]` + + +## Miscellaneous + +**In "flags" goal :** Just replace `WOOL` block name by `WHITE_WOOL`. The color will be +automatically defined with the color of the team. \ No newline at end of file diff --git a/readme.md b/readme.md index c4494df0f..72f315f19 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,8 @@ ![PVP-Arena](/doc/images/logo.png) -```diff -- NOTE FOR TESTERS! - YOU NEED TO START WITH A FRESH CONFIGURATION! ITEM DEFINITIONS HAVE CHANGED. USE THE SET COMMAND TO SET ITEMS/MATERIALS -``` - +*** +**IF YOU'RE UPGRADING FROM 1.3.x VERSION OR BELOW, PLEASE READ [UPGRADE DOCUMENTATION](doc/update-from-1-3-x.md)** +*** **Enhance your server by adding a new dimension of PVP battles!** @@ -41,7 +40,6 @@ This flexibility is achieved on the one hand by a module loader created by Nodin ## Downloads - [spigotmc.org](https://www.spigotmc.org/resources/pvp-arena.16584/) -- [jenkins - dev builds](https://ci2.craftyn.com/job/PVP%20Arena/) *** @@ -147,6 +145,7 @@ That's it! If you want to disable that, set "tracker" to false in the config! ## Credits +- SlipCor, the wonderful guy who created this plugin - Deminetix for the very root, the Fight plugin - Bradley Hilton for the fork until version v0.0.3 - Carbon131 for adding features until version v0.0.5 From 75555b959548a2665c90f7bf63ba20606ac88f72 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 27 Mar 2019 20:30:34 +0100 Subject: [PATCH 014/115] v1.13.9 - fix /pa set with hand option --- src/net/slipcor/pvparena/commands/PAA_Set.java | 7 ++++--- src/plugin.yml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/net/slipcor/pvparena/commands/PAA_Set.java b/src/net/slipcor/pvparena/commands/PAA_Set.java index 1ad2bbc7f..2d3b26541 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Set.java +++ b/src/net/slipcor/pvparena/commands/PAA_Set.java @@ -201,11 +201,12 @@ private void set(final CommandSender player, final Arena arena, final String nod if ("hand".equals(value)) { if (player instanceof Player) { - ItemStack[] items = new ItemStack[]{(((Player) player).getEquipment().getItemInMainHand())}; - arena.getArenaConfig().setManually(node, getSerializableItemStacks(items)); + ItemStack item = ((Player) player).getInventory().getItemInMainHand(); + arena.getArenaConfig().setManually(node, getSerializableItemStacks(item)); arena.msg( player, - Language.parse(arena, MSG.SET_DONE, node, items[0].getType().name())); + Language.parse(arena, MSG.SET_DONE, node, item.getType().name())); + arena.getArenaConfig().save(); } else { arena.msg(player, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS)); } diff --git a/src/plugin.yml b/src/plugin.yml index 4252979c5..1a17060f5 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -3,7 +3,7 @@ author: slipcor authors: [slipcor] prefix: PVP Arena main: net.slipcor.pvparena.PVPArena -version: 1.13.8 +version: 1.13.9 api-version: 1.13 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot] description: create, manage and enhance PvP arenas From d8a300ea3f00b2a649fd27898054f575e8203701 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 3 Apr 2019 20:37:58 +0200 Subject: [PATCH 015/115] v1.13.9.301 - Fix keepInventory config on respawn and fix infected colors on scoreboards --- src/net/slipcor/pvparena/arena/Arena.java | 5 ++++- src/net/slipcor/pvparena/managers/InventoryManager.java | 2 +- src/plugin.yml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index a6a9b9065..9e5fce457 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -1,6 +1,5 @@ package net.slipcor.pvparena.arena; -import com.google.common.collect.ImmutableMap; import net.slipcor.pvparena.PVPArena; import net.slipcor.pvparena.arena.ArenaPlayer.Status; import net.slipcor.pvparena.classes.*; @@ -2459,6 +2458,8 @@ public void run() { } final Team sTeam = board.registerNewTeam(newTeam.getName()); sTeam.setPrefix(newTeam.getColor().toString()); + sTeam.setSuffix(ChatColor.RESET.toString()); + sTeam.setColor(newTeam.getColor()); sTeam.addEntry(player.getName()); sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll()); } @@ -2479,6 +2480,8 @@ public void run() { } final Team sTeam = board.registerNewTeam(newTeam.getName()); sTeam.setPrefix(newTeam.getColor().toString()); + sTeam.setSuffix(ChatColor.RESET.toString()); + sTeam.setColor(newTeam.getColor()); sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll()); sTeam.addEntry(player.getName()); } diff --git a/src/net/slipcor/pvparena/managers/InventoryManager.java b/src/net/slipcor/pvparena/managers/InventoryManager.java index fa9a357c8..e15e0ae8c 100644 --- a/src/net/slipcor/pvparena/managers/InventoryManager.java +++ b/src/net/slipcor/pvparena/managers/InventoryManager.java @@ -79,7 +79,7 @@ public static List drop(final Player player) { exclude.add(item.getType()); } } - keepAll = ap.getArena().getArenaConfig().getString(CFG.ITEMS_KEEPONRESPAWN).equalsIgnoreCase("all"); + keepAll = ap.getArena().getArenaConfig().getBoolean(CFG.ITEMS_KEEPALLONRESPAWN); if (keepAll) { keep = new ArrayList<>(); } else { diff --git a/src/plugin.yml b/src/plugin.yml index 1a17060f5..a51948a92 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -3,7 +3,7 @@ author: slipcor authors: [slipcor] prefix: PVP Arena main: net.slipcor.pvparena.PVPArena -version: 1.13.9 +version: 1.13.9.301 api-version: 1.13 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot] description: create, manage and enhance PvP arenas From 6979d735b05a8477eb59bae889cc96480d414518 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Sat, 6 Apr 2019 15:20:04 +0200 Subject: [PATCH 016/115] Update readme --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 72f315f19..926712d69 100644 --- a/readme.md +++ b/readme.md @@ -40,6 +40,7 @@ This flexibility is achieved on the one hand by a module loader created by Nodin ## Downloads - [spigotmc.org](https://www.spigotmc.org/resources/pvp-arena.16584/) +- [Dev builds on Jenkins](https://ci.craftyn.com/view/Spigot%20PVP%20Arena/) *** From 8582e253b97b020ab4fb89d637976e7d2b35ee78 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 8 May 2019 20:30:45 +0200 Subject: [PATCH 017/115] v1.13.9.302 - fix refill inventory exception --- src/net/slipcor/pvparena/arena/ArenaClass.java | 7 ++++--- .../pvparena/runnables/InventoryRefillRunnable.java | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java index 37fdc9ea0..4ecb8b161 100644 --- a/src/net/slipcor/pvparena/arena/ArenaClass.java +++ b/src/net/slipcor/pvparena/arena/ArenaClass.java @@ -163,13 +163,13 @@ public static void addGlobalClasses(final Arena arena) { } public static void equip(final Player player, final ItemStack[] items) { - ItemStack last = items[items.length-1]; + int i = 0; for (final ItemStack item : items) { if (ARMORS_TYPE.contains(item.getType())) { equipArmor(item, player.getInventory()); } else { - if (last != null && last == item) { - player.getInventory().setItemInOffHand(last); + if (i == items.length - 1) { + player.getInventory().setItemInOffHand(item); continue; } if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { @@ -190,6 +190,7 @@ public void run() { player.getInventory().addItem(item); } } + i++; } player.updateInventory(); } diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java index 2a7790438..6bf2dbda9 100644 --- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java +++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java @@ -85,7 +85,12 @@ public void run() { for (final ItemStack item : additions) { items[pos++] = item; } - ArenaClass.equip(player, items); + if(items.length > 0){ + ArenaClass.equip(player, items); + } else { + PVPArena.instance.getLogger().info("Can't refill inventory, please set " + CFG.ITEMS_KEEPONRESPAWN.getNode() + + ", " + CFG.ITEMS_KEEPALLONRESPAWN.getNode() + " or " + CFG.PLAYER_REFILLCUSTOMINVENTORY.getNode() + " parameter"); + } } if (arena.getArenaConfig().getBoolean(CFG.USES_WOOLHEAD)) { final ArenaTeam aTeam = aPlayer.getArenaTeam(); From edd199bf8ea23cf5030572031ec0dd2aebae0f18 Mon Sep 17 00:00:00 2001 From: Oruss7 Date: Sat, 11 May 2019 20:17:12 +0200 Subject: [PATCH 018/115] cancel damage if player not fighting --- .../pvparena/listeners/PlayerListener.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 6b7b5395e..b7fd581da 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -450,6 +450,29 @@ public void onPlayerHunger(final FoodLevelChangeEvent event) { } } + /** + * Cancel damages when: + * + * - target has not (Status.FIGHT) + * - damager has not (Status.FIGHT) + * + * @param event EntityDamageByEntityEvent + */ + @EventHandler + public void onPlayerDamage(EntityDamageByEntityEvent event){ + + if (event.getEntityType() == EntityType.PLAYER || event.getDamager().getType() == EntityType.PLAYER) { + // parse arena players + final ArenaPlayer damager = ArenaPlayer.parsePlayer(event.getDamager().getName()); + final ArenaPlayer target = ArenaPlayer.parsePlayer(event.getEntity().getName()); + + // cancel if damager or target not fighting + if (damager.getStatus() != Status.FIGHT || target.getStatus() != Status.FIGHT ) { + event.setCancelled(true); + } + } + } + @EventHandler(priority = EventPriority.LOW) public void onPlayerInteract(final PlayerInteractEvent event) { final Player player = event.getPlayer(); From ad0a5ce194e14f670311730bcb3eb130dae1bdb7 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 15 May 2019 20:38:34 +0200 Subject: [PATCH 019/115] fix null message in console --- src/net/slipcor/pvparena/classes/PACheck.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/net/slipcor/pvparena/classes/PACheck.java b/src/net/slipcor/pvparena/classes/PACheck.java index b604d4fb5..ae89d4c12 100644 --- a/src/net/slipcor/pvparena/classes/PACheck.java +++ b/src/net/slipcor/pvparena/classes/PACheck.java @@ -11,7 +11,6 @@ import net.slipcor.pvparena.core.Debug; import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; -import net.slipcor.pvparena.core.StringParser; import net.slipcor.pvparena.events.PAJoinEvent; import net.slipcor.pvparena.events.PAStartEvent; import net.slipcor.pvparena.loadables.ArenaGoal; @@ -517,7 +516,7 @@ public static void handlePlayerDeath(final Arena arena, StatisticsManager.kill(arena, player.getKiller(), player, doesRespawn); if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES) || arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGESCUSTOM)) { - event.setDeathMessage(null); + event.setDeathMessage(""); } if (player.getKiller() != null) { From 7c3bafd97c0247ac43cebc8d0fc92a378fb36c7f Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 15 May 2019 20:39:21 +0200 Subject: [PATCH 020/115] v1.13.10.306 - fix on latest merge --- src/net/slipcor/pvparena/listeners/PlayerListener.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index b7fd581da..46d84942d 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -16,7 +16,6 @@ import net.slipcor.pvparena.core.Debug; import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; -import net.slipcor.pvparena.core.StringParser; import net.slipcor.pvparena.events.PAGoalEvent; import net.slipcor.pvparena.loadables.ArenaGoalManager; import net.slipcor.pvparena.loadables.ArenaModule; @@ -461,9 +460,12 @@ public void onPlayerHunger(final FoodLevelChangeEvent event) { @EventHandler public void onPlayerDamage(EntityDamageByEntityEvent event){ - if (event.getEntityType() == EntityType.PLAYER || event.getDamager().getType() == EntityType.PLAYER) { - // parse arena players + if (event.getEntityType() == EntityType.PLAYER && event.getDamager().getType() == EntityType.PLAYER) { final ArenaPlayer damager = ArenaPlayer.parsePlayer(event.getDamager().getName()); + if(damager.getArena() == null) { + return; // no fighting player => OUT + } + final ArenaPlayer target = ArenaPlayer.parsePlayer(event.getEntity().getName()); // cancel if damager or target not fighting From 8ac1f66a3b63a7af6d81c9269443bf29d447c188 Mon Sep 17 00:00:00 2001 From: Oruss7 Date: Fri, 31 May 2019 10:55:19 +0200 Subject: [PATCH 021/115] add lang for dom bossbar --- src/net/slipcor/pvparena/core/Language.java | 2 ++ src/net/slipcor/pvparena/goals/GoalDomination.java | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 17e42efe1..a00345d1a 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -491,6 +491,8 @@ public enum MSG { GOAL_CHECKPOINTS_SCORE("nulang.goal.checkpoints.score", "%1% &ereached checkpoint #%2%!"), GOAL_CHECKPOINTS_YOUMISSED("nulang.goal.checkpoints.youmissed", "You missed checkpoint #%1%! This is #%2%"), + GOAL_DOMINATION_BOSSBAR_CLAIMING("nulang.goal.dom.bossbar_claiming", "Claiming..."), + GOAL_DOMINATION_BOSSBAR_UNCLAIMING("nulang.goal.dom.bossbar_claiming", "Unclaiming..."), GOAL_DOMINATION_CLAIMING("nulang.goal.dom.claiming", "&eTeam %1% is claiming a flag!"), GOAL_DOMINATION_CLAIMED("nulang.goal.dom.claimed", "&eTeam %1% has claimed a flag!"), GOAL_DOMINATION_SCORE("nulang.goal.dom.score", "&eTeam %1% scored %2% points by holding a flag!"), diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java index 0c8698671..43d8f6b2a 100644 --- a/src/net/slipcor/pvparena/goals/GoalDomination.java +++ b/src/net/slipcor/pvparena/goals/GoalDomination.java @@ -290,7 +290,8 @@ void checkMove() { PVPArena.instance, domRunner, 10 * 20L, 10 * 20L); getRunnerMap().put(loc, domRunner); - barStart(loc, "unclaiming", ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), 200L); + barStart(loc, Language.parse(arena, + MSG.GOAL_DOMINATION_UNCLAIMING), ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), 200L); } } else { // just the owning team is there @@ -342,7 +343,8 @@ void checkMove() { running.runID = Bukkit.getScheduler().scheduleSyncRepeatingTask( PVPArena.instance, running, interval, interval); getRunnerMap().put(loc, running); - barStart(loc, "unclaiming", ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval); + barStart(loc, Language.parse(arena, + MSG.GOAL_DOMINATION_UNCLAIMING), ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval); } else { // flag not taken arena.getDebugger().i("- flag not taken"); @@ -394,7 +396,8 @@ void checkMove() { PVPArena.instance, running, interval, interval); getRunnerMap().put(loc, running); - barStart(loc, "claiming...", team.getColor(), arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval); + barStart(loc, Language.parse(arena, + MSG.GOAL_DOMINATION_CLAIMING), team.getColor(), arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval); } } else { arena.getDebugger().i(" - more than one team present. continue!"); From 773f6f69e21253c5bc68988e18e6e85963ec9c22 Mon Sep 17 00:00:00 2001 From: Oruss7 Date: Fri, 31 May 2019 20:12:59 +0200 Subject: [PATCH 022/115] add lang folder --- lang/lang_en.yml | 644 +++++++++++++++++++++++++++++++++++++++++ lang/lang_fr.yml | 734 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1378 insertions(+) create mode 100644 lang/lang_en.yml create mode 100644 lang/lang_fr.yml diff --git a/lang/lang_en.yml b/lang/lang_en.yml new file mode 100644 index 000000000..6a0236968 --- /dev/null +++ b/lang/lang_en.yml @@ -0,0 +1,644 @@ +nulang: + arena: + create: + done: arena '%1%' created! + disable: + done: Arena disabled! + edit: + disabled: 'Disabled edit mode for arena: %1%' + enabled: 'Enabled edit mode for arena: %1%' + enable: + done: Arena enabled! + arenalist: 'Arenas: &a%1%&r' + regionshapeunknown: 'Arena Shape ''%1%'' unknown. consult the forums: http://goo.gl/IfLOh' + reload: + done: Arena reloaded! + remove: + done: 'Arena removed: &e%1%&r' + setup: + disabled: 'Disabled setup mode for arena: %1%' + enabled: 'Enabled setup mode for arena: %1%' + startingin: Enough players ready. Starting in %1%! + start: + done: Arena force started! + stop: + done: Arena force stopped! + autosetup: + automanual: Do you want the wizard to be &a%1%&r or &a%2%&r? + automatic: automatic + manual: manual + modeselected: '&a%1%&r mode selected!' + welcome: |- + Welcome to the PVP Arena setup wizard! + Please just type the colored answers into the chat. No commands needed! + blacklist: + added: Added &a%1%&r to &e%2%&r blacklist! + allcleared: All blacklists cleared! + cleared: Blacklist &e%1%&r cleared! + help: 'Usage: blacklist clear | blacklist [type] [clear|add|remove] [id]' + removed: Removed &a%1%&r from &e%2%&r blacklist! + show: 'Blacklist &e%1%&r:' + check: + done: Check done! No errors! + class: + list: 'Available classes: %1%' + preview: You are now previewing the class %1% + removed: 'Class removed: %1%' + saved: 'Class saved: %1%' + selected: You have switched to &e%1%&e class + selectedrespawn: You will switch to the &e%1%&f class on next respawn. + deathcause: + BLOCK_EXPLOSION: an explosion + CONTACT: a cactus + CUSTOM: Herobrine + DROWNING: water + ENTITY_EXPLOSION: an Explosion + FALL: gravity + FIRE_TICK: fire + FIRE: a fire + LAVA: lava + LIGHTNING: Thor + MAGIC: Magical Powers + POISON: Poison + PROJECTILE: something he didn't see coming + STARVATION: hunger + SUFFOCATION: lack of air + SUICIDE: self + THORNS: thorns + VOID: the Void + CREEPER: a creeper + SKELETON: a skeleton + SPIDER: a spider + GIANT: a giant + ZOMBIE: a zombie + SLIME: a slime + GHAST: a ghast + PIG_ZOMBIE: a pig zombie + ENDERMAN: an enderman + CAVE_SPIDER: a cave spider + SILVERFISH: silverfish + BLAZE: a blaze + MAGMA_CUBE: a magma cube + ENDER_DRAGON: an ender dragon + WITHER: a wither boss + WITCH: a witch + WOLF: a wolf + IRON_GOLEM: an iron golem + SPLASH_POTION: a splash potion + duty: + 'false': You are now off duty! + 'true': You are now on duty! + error: + arena: + alreadyplaying: You are already part of &a%1%&r + arenaexists: Arena already exists! + arenanotexists: 'Arena does not exist: %1%' + arenaconfig: 'Error when loading arena config: %1%' + argumenttype: '&cInvalid argument type:&r &e%1%&r is no proper &a%2%&r' + argument: '&cArgument not recognized:&r %1% - possible arguments: &a%2%&r' + autosetup: + running: 'There is already an autosetup running! Player: %1%' + blacklist: + disallowed: You may not %1% this! Blacklisted! + unknownsubcommand: 'Unknown subcommand. Valid commands: &a%1%&r' + unknowntype: 'Unknown type. Valid types: &e%1%&r' + class: + full: The class &a%1%&r is full! + notenoughexp: You don't have enough EXP to choose &a%1%&r! + notfound: 'Class not found: &a%1%&r' + cmdblocked: '&cCommand blocked: %1%' + invalidcmd: Invalid command (%1%) + unknowncmd: Unknown command + arenadisabled: Arena disabled, please try again later! + editmode: edit mode! + error: '&cError: %1%' + fightinprogress: A fight is already in progress! + goal: + legacyunknown: 'Legacy goal &a%1%&r unknown! You will want to add goals: &a/pa + [arena] goal [goalname]' + goalnotfound: 'Goal &a%1%&r unknown. Valid goals: &a%2%&r' + install: Error while installing &a%1%&r + invalid_argument_count: '&cInvalid number of arguments&r (%1% instead of %2%)!' + invalidstattype: 'Invalid statistics type: %1%' + valuenotfound: 'Invalid value: &a%1%&r!' + invfull: Your inventory was full. You did not receive all rewards! + arenafull: arena is full! + joinrange: You are too far away to join this arena! + notjoinregion: You are not in the join region! Move there to join! + teamfull: team %1% is full! + insidevehicle: You cannot join while on a vehicle! + errorloungefree: Error! Arena is not of type free. Use '[teamname]lounge' + log: + matnotfound: 'Unrecognized material: %1%' + missingspawn: 'Spawn missing: &f%1%' + noarenas: No arenas found! + valueneg: 'Negative values: &c%1%&r' + nofight: There is no fight in progress. + nogoal: You did not add a goal! &a/pa [arena] goal [goalname] + nospawns: No spawns set! + classperms: You do not have permission for class &a%1%&r + permjoin: You don't have permission to join the arena! + noperm: '&cNo permission to %1%' + noplayerfound: No player found! + notinarena: You are not part of an arena! + notnumeric: '&cArgument not numeric:&r %1%' + notsameworld: Not in the same world as the arena (%1%)! + noteamfound: No team found! + onlyplayers: '&cThis command can only be used by players!' + playernotfound: '&cPlayer not found: &f%1%&c!' + positives: 'Positive values: &b%1%&r' + potioneffecttypenotfound: 'PotionEffectType not found: &e%1%&r' + ready: + notready0: At least one player is not ready! + notready1: You are alone in the arena! + notready2: Your team is alone in the arena! + notready3: A team is missing players! + notready4: The arena is missing players! + notready5: At least one player has not chosen a class! + noclass: You don't have a class! + error: The arena is not ready! %1% + region: + beingcreated: 'A region is already being created: %1%' + flagnotfound: 'RegionFlag &a%1%&r unknown! Valid values: %2%' + notfound: Region &a%1%&r not found! + protectionnotfound: RegionProtection &a%1%&r unknown! + typenotfound: 'RegionType &a%1%&r unknown! Valid values: %2%' + youselect: You are already selecting a region for an arena! + youselect2: Type the command again to cancel selection mode! + youselectexit: Region selection cancelled! + regionnotbeingcreated: A region is not being created! + regionnotremoved: There is no region setup. + select2: Select two points before trying to save. + setupmode: setup mode! + spawn: + unknown: 'Unknown spawn: &a%1%&r' + spawnfree: Error! Arena is of type free. Use 'spawnX' where X is a digit or letter! + statsfile: Error while reading the stats file! + teamnotfound: 'Team not found: &a%1%&r' + uninstall: Error while uninstalling &a%1%&r + unknownmodule: 'Module not found: %1%' + whitelist: + disallowed: You may not %1% this! (not whitelisted) + unknownsubcommand: 'Unknown subcommand. Valid commands: &a%1%&r' + unknowntype: 'Unknown type. Valid types: &e%1%&r' + nopermto: + madmin: administrate + create: create an arena + disable: disable + edit: edit an arena + enable: enable + nopermjoin: join an arena + reload: reload + remove: remove an arena + set: set a config node + setup: setup an arena + teleport: teleport to an arena spawn + user: use PVP Arena + cmds: + blacklist: use the blacklist command + check: use the check command + class: use the class command + create: use the create command + debug: use the debug command + disable: use the disable command + duty: use the duty command + edit: use the edit command + enable: use the enable command + gamemode: use the gamemode command + goal: use the goal command + install: use the install command + playerclass: use the playerclass command + playerjoin: use the playerjoin command + protection: use the protection command + region: use the region command + regionflag: use the regionflag command + regions: use the regions command + regiontype: use the regiontype command + reload: use the reload command + remove: use the remove command + round: use the round command + set: use the set command + setowner: use the setowner command + setup: use the setup command + spawn: use the spawn command + start: use the start command + stop: use the stop command + teams: use the teams command + teleport: use the teleport command + template: use the template command + togglemod: use the togglemod command + uninstall: use the uninstall command + update: use the update command + whitelist: use the whitelist command + arenaclass: use the arenaclass command + chat: use the chat command + join: use the join command + leave: use the leave command + spectate: use the spectate command + arenalist: use the arenalist command + help: use the help command + info: use the info command + list: use the list command + ready: use the ready command + shutup: use the shutup command + stats: use the stats command + version: use the version command + fight: + begins: Let the fight begin! + draw: This match was a draw! No winners! + killedbyremaining: '%1% has been killed by %2%! %3% lives remaining.' + killedbyremainingfrags: '%1% has been killed by %2%! %3% kills remaining.' + killedbyremainingteam: '%1% has been killed by %2%! %3% lives remaining for %4%.' + killedbyremainingteamfrags: '%1% has been killed by %2%! %3% kills remaining for + %4%.' + killedby: '%1% has been killed by %2%!' + playerleft: '%1% has left the fight!' + forcestop: You have forced the fight to stop. + gamemode: + free: Game mode &afree for all&r set for arena &a%1%&r! + team: Game mode &ateam&r set for arena &a%1%&r! + general: + break: break + place: place + use: use + goal: + added: 'Goal added: &a%1%&r' + installing: 'Install goals by command: &a/pa install [goalname]&r' + removed: 'Goal removed: &a%1%&r' + blockdestroy: + typeset: 'Blocktype set to: &e%1%' + setflag: 'Block set: %1%' + tosetflag: 'Block to set: %1%' + dom: + bossbar_claiming: 'Claiming...' + bossbar_unclaiming: 'Unclaiming...' + claiming: '&eTeam %1% is claiming a flag!' + claimed: '&eTeam %1% has claimed a flag!' + score: '&eTeam %1% scored %2% points by holding a flag!' + contesting: '&eA flag claimed by team %1% is being contested!' + unclaiming: '&eA flag claimed by Team %1% is being unclaimed!' + unclaimingby: '&eA flag claimed by Team %1% is being unclaimed by Team %2%!' + infected: + lost: '&6The infected players have been killed!' + player: '&c%1% is infected!' + you: '&cYou are infected!' + won: '&6The infected players have won the game!' + iprotect: 'The infected team is prevented from: %1%' + iprotectset: '&ePlayerProtection &f%1%&f set to: %2%' + killreward: + added: 'Kill reward added: &e%1%&f->&a%2%' + removed: 'Kill reward removed: &e%1%' + liberation: + liberated: Team %1% has been liberated! + setbutton: 'Button set: %1%' + tosetbutton: 'Button to set: %1%' + physicalflags: + holdflag: You have to hold the flag to bring it back! + sabotage: + tntignite: '%1% ignited the TNT of team %2%!' + set: 'TNT set: %1%' + toset: 'TNT to set: %1%' + youtnt: You now carry the sabotage materials!' + tank: + tankdown: The tank is down! + tankmode: TANK MODE! Everyone kill %1%, the tank! + tankwon: The tank has won! Congratulations to %1%! + tdc: + denied: '%1% denied a kill!' + remaining: '%1% kills remaining for %2%.' + scored: '%1% scored a kill!' + youdenied: You denied a kill! + youscored: You scored a kill! + pillars: + msg: + block_broken: '[%1%] %2% broke a block!' + lower: '[%1%] %2% shortened the pillar!' + block_placed: '[%1%] %2% placed a block!' + higher: '[%1%] %2% lengthened the pillar!' + claimed: '[%1%] %2% claimed the pillar!' + unclaimed: '[%1%] %2% unclaimed the pillar!' + score: '%1% scored %2% points' + rescue: + flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: + %3%' + flagsave: '%1% dropped the hostage of team %2%!' + flaggrab: '%1% grabbed the hostage of team %2%!' + flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' + setflag: 'Rescue set: %1%' + tosetflag: 'Rescue to set: %1%' + typeset: 'Hostage type set to: &e%1%' + help: + head: '&e--- &aPVP Arena Help&e %1% &e---' + admin: '&c%1% - help administrating' + setup: '&e%1% - help setting up' + custom: '&e%1% - help customizing' + game: '&a%1% - help ingame' + info: '&9%1% - help getting information' + import: + done: Successfully imported arena &e%1%&r! + info: + classes: 'Classes: &a%1%&r' + goal_active: 'Goal: &a%1%&r' + goal_inactive: 'Goal: &b%1%&r &7== INACTIVE ==' + head_headlin: 'Arena Information about: &a%1%&r | [&a%2%&r]' + head_teams: 'Teams: &a%1%&r' + mod_active: 'Module: &a%1%&r' + mod_inactive: 'Module: &b%1%&r &7== INACTIVE ==' + owner: 'Owner: &a%1%&r' + regions: 'Regions: &a%1%&r' + section: '----- &a%1%&r -----' + install: + installed: 'installed: &a%1%&r' + list: + arenas: 'Available arenas: %1%' + dead: 'Dead: %1%' + fighting: 'Fighting: %1%' + lost: 'Lost: %1%' + lounge: 'Lounge: %1%' + 'null': 'Glitched: %1%' + players: 'Players: %1%' + team: 'Team %1%: %2%' + ready: 'Ready: %1%' + warm: 'Warm: %1%' + watching: 'Watching: %1%' + log: + plugindisabled: disabled (version %1%) + pluginenabled: enabled (version %1%) + trickerdisabled: Plugin tracking disabled. See you soon? + trackingenabled: 'Plugin tracking enabled. Set tracker: false inside the main + config to disable.' + updatedisabled: Updates deactivated. Please check dev.bukkit for updates. + updateenabled: Checking for updates... + warning: '%1%' + messages: + toArena: You are now talking to the arena! + toPublic: You are now talking to the public! + toTeam: You are now talking to your team! + general: '&e[%1%&e] &f%2%' + noplayer: No player in the PVP arena. + notice: + awarded: You have been awarded %1% + nodropitem: Not so fast! No cheating! + noteleport: Please use '/pa leave' to exit the fight! + notice: 'Notice: %1%' + playerawarded: '%1% has been awarded %2%' + remove: '&cThis will permanently remove the arena &a%1%&c. Are you sure? Then + commit the command again!&f To disable this message, see ''safeadmin'' in your + config.yml' + waitingequal: Waiting for the teams to have an equal player number! + waitingforarena: Waiting for a running arena to finish! + welcomespec: Welcome to the spectator's area! + gameloot: Here is your game loot! + welcomespec2: /pa bet [name] [amount] to bet on team or player + youdeath: You entered a DEATH region. Goodbye! + youescaped: You escaped the battlefield. Goodbye! + youleft: You left the arena! + younocamp: You are in a NOCAMP region. Move! + playerhaswon: '%1% is the Champion!' + playerready: '%1%&e is ready!' + player: + prevented: + break: '&cYou may not break blocks!' + place: '&cYou may not place blocks!' + tnt: '&cYou may not use TNT!' + tntbreak: '&cYou may not break TNT!' + drop: '&cYou may not drop items!' + inventory: '&cYou may not access this!' + craft: '&cYou may not craft!' + notreadyplayers: Players not ready + players: Players + ready: + list: 'Players: %1%' + done: You have been flagged as ready! + region: + flag: + added: 'Region flag added: &a%1%&r' + removed: 'Region flag removed: &a%1%&r' + height: 'Region height set to: &a%1%&r' + pos1: First position set. + pos2: Second position set. + protection_added: 'RegionProtection added: &a%1%&r' + protection_removed: 'RegionProtection removed: &a%1%&r' + radius: 'Region radius set to: &a%1%&r' + removed: 'Region removed: %1%' + saved: Region saved. + saved_notice: '&6You created a &oCUSTOM&6 region. It has no function yet! To turn + it into a battlefield region, type &r/pvparena %1% !rt %2% BATTLE.' + select: Select two points with your wand item, left click first and then right click! + setting: Setting region enabled. + typeset: 'Region Type set: &e%1%' + youselect: You are now selecting a region for arena &a%1%&r! + regions: + flags: 'Region Flags: &a%1%&r' + head: '--- &aArena Region&r [&e%1%&r]---' + listhead: '--- &aArena Regions&r [&e%1%&r]---' + listvalue: '&a%1%&r: %2%, %3%' + protections: 'Region Protections: &a%1%&r' + shape: 'Region Shape: &a%1%&r' + type: 'Region Type: &a%1%&r' + reloaded: Config reloaded! + round: + display: 'Round #%1%: %2%' + added: 'Added goal to round: &e%1%' + removed: 'Removed goal from round: &e%1%' + set: + done: '&a%1%&r set to &e%2%&r!' + help: use /pa {arenaname} set [page] to get a node list + unknown: 'Unknown node: &e%1%&r!' + setowner: + done: '&a%1%&r is now owner of arena &a%2%&r!' + spawn: + freelounge: Lounge set + teamlounge: 'Lounge set: %1%' + notset: 'Spawn not set: &a%1%&r' + offset: Spawn &a%1%&r offset by &a%2%&r blocks. + removed: 'Spawn removed: &a%1%&r' + set: 'Spawn set: &a%1%&r' + setdone: 'Spawn setting done: &a%1%&r' + setstart: 'Spawn setting started: &a%1%&r' + unknown: 'Spawn not found: &a%1%&r' + stats: + filedone: Statistics file loaded! + head: Statistics TOP %1% (%2%) + typenotfound: 'Statistics type not found! Valid values: &e%1%&r' + stattype: + DAMAGE: full damage dealt + DAMAGETAKE: full damage taken + DEATHS: deaths + KILLS: kills + LOSSES: matches lost + MAXDAMAGE: max damage dealt + MAXDAMAGETAKE: max damage taken + 'NULL': player name + WINS: matches won + team: + haswon: Team %1% are the Champions! + ready: Team %1% is ready! + teams: + list: 'Available teams: %1%' + add: 'Team added: %1%' + set: 'Team set: %1%' + remove: 'Team removed: %1%' + template: + loaddone: 'Template loaded from: &a%1%&r' + savedone: 'Template saved to: &a%1%&r' + time: + minutes: minutes + seconds: seconds + timer: + countdowninterrupt: Countdown interrupted! Hit the ready block! + ending: The match will end in %1%! + resetting: The arena will reset in %1%! + starting: Starting in %1%! + warmingup: Warming up... %1%! + pvpactivating: PVP will be activated in %1%! + walls: Walls will be removed in %1%! + togglemod: + notice: '&cYou activated a module that requires a BATTLE region! Type: &r/pvparena + [arena] !rt [region] BATTLE' + uninstall: + done: 'uninstalled: &a%1%&r' + whitelist: + added: Added &a%1%&r to &e%2%&r whitelist! + allcleared: All whitelist cleared! + cleared: Whitelist &e%1%&r cleared! + help: 'Usage: blacklist clear | blacklist [type] [clear|add|remove] [id]' + removed: Removed &a%1%&r from &e%2%&r whitelist! + show: 'Whitelist &e%1%&r:' + mod: + aftermatch: + aftermatch: The aftermatch has begun! + startingin: AfterMatch in %1%! + spawnnotset: Spawn 'after' not set! + announcements: + ignoreon: You are now ignoring announcements! + ignoreoff: You are now receiving announcements! + arenaboards: + createarenaboard: create an ArenaBoard + arenaboarddestroyed: ArenaBoard destroyed! + boardexists: ArenaBoard already exists!' + sortingby: ArenaBoard now sorted by %1% + autovote: + arenarunning: 'Arena running: %1%' + autojoin: Arena auto join started! + playervoted: '%2% voted for arena %1%!' + youvoted: You voted for arena %1%! + duel: + accepted: '%1% &eaccepted the challenge! The game is starting.' + announce: '%1% &echallenged you! Accept the duel with &f/pa %2% accept.' + announce2: '&eCancel the duel with &r/pa %2% decline&e.' + busy: '%1% &eis already in a fight Please try again later.' + declineds: Your opponent declined the request. The duel has been cancelled. + declinedr: You declined the duel request! + requested: You &echallenged &r%1%&e! + requestedalready: You already have challenged someone! + requestexpireds: Your opponent did not accept the request in time. The duel has been cancelled. + requestexpiredr: You did not accept the request in time. The duel has been cancelled. + starting: The duel begins! + nodirectjoin: 'You may not join this arena directly! Use: &e/pa %1% duel [playername]' + fixinventorylos: + gamemode: Enter survival gamemode before joining! + invenory: Empty your inventory before joining! + latelounge: + llannounce: Arena %1% is starting! Player %2% wants to start. Join with /pa %1% + llposition: You are on queue position %1%! + llrejoin: Ready check has caught you not being able to join. Rejoin when you can! + llwait: Arena will be starting soon, please wait! + playerfinder: + near: 'Nearest player: %1% blocks!' + point: Compass pointing to nearest player! + powerups: + invalidpowerupeffect: 'Invalid PowerupEffect: %1%' + puplayer: '%1% has collected PowerUp %2%!' + puserver: PowerUp deployed! + respawnrelay: + respawning: Respawning in %1%! + skins: + dc: Hooking into DisguiseCraft! + md: Hooking into MobDisguise! + nomod: No disguise plugin found, Skins module is inactive! + showclass: Class &e%1%&r will be disguised to &a%2% + showteam: Team %1% will be disguised to %2% + specialjoin: + done: Join block set here - %1% + start: Setting join block! + stop: Aborted join block selection! + startfreeze: + announce: The game will start in %1% seconds! + tempperms: + noperms: Permissions plugin not found, defaulting to OP. + head: 'Temporary permissions of &e%1%&r:' + added: Temporary permissions &e%1%&r added to &a%2%&r + removed: Temporary permissions &e%1%&r removed from &a%2%&r + vault: + 'on': <3 eConomy + 'off': &a%2%' + removed: 'Mise à prix supprimée: &e%1%' + liberation: + liberated: L'équipe %1% a été libérée ! + setbutton: 'Bouton configuré: %1%' + scoreboardheading: 'Players in jail:' + scoreboardseparator: '----------------' + tosetbutton: 'Bouton à configurer: %1%' + physicalflags: + holdflag: Vous avez pris le drapeau, rapportez le ! + sabotage: + tntignite: '%1% a allumé la TNT de l''équipe %2% !' + set: 'TNT configurée: %1%' + toset: 'TNT a configurer: %1%' + youcannotselfdestroy: You can not ignite your own TNT!' + youtnt: Vous portez maintenant le matériel de sabotage !' + tank: + tankdown: Le tank est H.S. ! + tankmode: TANK MODE ! Tous le monde doit tuer %1%, le tank ! + tankwon: Le tank a gagné ! Félicitations à %1% ! + tdc: + denied: '%1% denied a kill!' + remaining: '%1% kills remaining for %2%.' + scored: '%1% scored a kill!' + youdenied: You denied a kill! + youscored: You scored a kill! + pillars: + msg: + block_broken: '[%1%] %2% a cassé un bloc !' + lower: '[%1%] %2% a raccourci la colonne!' + block_placed: '[%1%] %2% a posé un bloc !' + higher: '[%1%] %2% a agrandi la colonne !' + claimed: '[%1%] %2% a réclamé la colonne !' + unclaimed: '[%1%] %2% a libéré la colonne !' + score: '%1% a marqué %2% points' + rescue: + flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: + %3%' + flagsave: '%1% dropped the hostage of team %2%!' + flaggrab: '%1% grabbed the hostage of team %2%!' + flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' + setflag: 'Rescue set: %1%' + tosetflag: 'Rescue to set: %1%' + typeset: 'Hostage type set to: &e%1%' + help: + head: '&e--- &aAide de PVP Arena&e %1% &e---' + admin: '&c%1% - aide administration' + setup: '&e%1% - aide configuration' + custom: '&e%1% - aide customisation' + game: '&a%1% - aide en jeu' + info: '&9%1% - Obtenir des informations' + import: + done: L'arène &e%1%&r a été imortée avec succès ! + info: + classes: 'Classes: &a%1%&r' + goal_active: 'Objectif: &a%1%&r' + goal_inactive: 'Objectif: &b%1%&r &7== INACTIF ==' + head_headlin: 'Infos arène à propos de: &a%1%&r | [&a%2%&r]' + head_teams: 'Equipes: &a%1%&r' + mod_active: 'Module: &a%1%&r' + mod_inactive: 'Module: &b%1%&r &7== INACTIF ==' + owner: 'Propriétaire: &a%1%&r' + regions: 'Regions: &a%1%&r' + section: '----- &a%1%&r -----' + install: + installed: 'installé: &a%1%&r' + list: + arenas: 'Arènes disponibles: %1%' + dead: 'Mort: %1%' + fighting: 'Combat: %1%' + lost: 'Perdu: %1%' + lounge: 'Lounge: %1%' + 'null': 'Bugué: %1%' + players: 'Joueurs: %1%' + team: 'Equipe %1%: %2%' + ready: 'Prêt: %1%' + warm: 'Chaud: %1%' + watching: 'Observation: %1%' + log: + plugindisabled: désactivé (version %1%) + pluginenabled: activé (version %1%) + trickerdisabled: Suivi du plugin désactivé. Rendez-vous bientôt ? + trackingenabled: 'Suivi du plugin activé. Configurer le suivi: false dans la configuration + pricipale à désactiver.' + updatedisabled: Mises à jour désactivée. Veuillez vérifier dev.bukkit pour les + mises à jour. + updateenabled: Recherche de mise à jour... + warning: '%1%' + messages: + toArena: Vous parlez maintenant dans l'arène ! + toPublic: Vous parlez maintenant au public ! + toTeam: Vous parlez maintenant à votre équipe ! + general: '&e[%1%&e] &f%2%' + noplayer: Aucun joueur dans l'arène PVP. + notice: + awarded: Vous avez été décerné %1% + nodropitem: Pas si vite ! On ne triche pas ! + noteleport: Merci d'utiliser '/pa leave' pour quitter le combat ! + notice: 'Notice: %1%' + playerawarded: '%1% a été décerné %2%' + remove: '&cCeci va définitivement supprimer l''arène &a%1%&c. Etes-vous sûr ? + Si oui retapez la commande !&f Pour désactiver ce message, allez dans ''safeadmin'' + de votre fichier config.yml' + waitingequal: En attente d'un équilibre du nombre de joueurs dans les équipes + ! + waitingforarena: En attente d'un arène en cours pour terminer ! + welcomespec: Bienvenue dans la zone des spectateurs ! Tape '/pa leave' pour la + quitter. + gameloot: Voici votre butin de jeu ! + welcomespec2: /pa bet [name] [amount] pour parier sur un équipe ou un joueur. + youdeath: Vous entrez dans une zone de MORT. Au revoir ! + youescaped: Vous sortez de la zone de combat. Au revoir ! + youleft: Vous venez de quitter l'arène ! + younocamp: Vous êtes dans une zone de MOUVEMENT. Déplacez-vous! + playerhaswon: '%1% est le champion !' + playerready: '%1%&e est prêt !' + player: + prevented: + break: '&cYou may not break blocks!' + place: '&cYou may not place blocks!' + tnt: '&cYou may not use TNT!' + tntbreak: '&cYou may not break TNT!' + drop: '&cYou may not drop items!' + inventory: '&cYou may not access this!' + craft: '&cYou may not craft!' + notreadyplayers: Les joueurs ne sont pas prêts + players: Joueurs + ready: + list: 'Joueurs: %1%' + done: Tu viens d'être enregistré comme prêt ! + region: + clear: + added: 'Added to region entity clearing whitelist: &a%1%&r' + list: 'Region entity clearing whitelist: &a%1%&r' + removed: 'Removed from region entity clearing whitelist: &a%1%&r' + flag: + added: 'Flag ajouté: &a%1%&r' + removed: 'Flag suppimé: &a%1%&r' + height: 'Hauteur de région: &a%1%&r' + pos1: Premier point selectionné. + pos2: Second point selectionné. + protection_added: 'Protection ajoutée: &a%1%&r' + protection_removed: 'Protection supprimée: &a%1%&r' + radius: 'Rayon de la région: &a%1%&r' + removed: 'Region supprimée: %1%' + saved: Region enregistrée. + saved_notice: '&6You created a &oCUSTOM&6 region. It has no function yet! To turn + it into a battlefield region, type &r/pvparena %1% !rt %2% BATTLE' + select: Selectionne deux points avec le wand item, clic gauche pour le prmier + et clic droit pour le second ! + setting: Paramètrage de région activé. + typeset: 'Region Type modifié en: &e%1%' + youselect: Vous séléctionnez maintenant une région pour &a%1%&r! + regions: + flags: 'Region Flags: &a%1%&r' + head: '--- &aRégion de l''arène&r [&e%1%&r]---' + listhead: '--- &aRégions de l''arène&r [&e%1%&r]---' + listvalue: '&a%1%&r: %2%, %3%' + protections: 'Region Protections: &a%1%&r' + shape: 'Forme de la région: &a%1%&r' + type: 'Type de région: &a%1%&r' + reloaded: Config actualisée! + ymls: + reloaded: Languages reloaded! + round: + display: 'Rond #%1%: %2%' + added: 'Objectif ajouté au rond: &e%1%' + removed: 'Objectif supprimé au rond: &e%1%' + roundsdisplay: Round %1% / %2% + roundsdisplayseparator: '-----------' + set: + items_not: Please use either hand or inventory to set an item node! + done: '&a%1%&r configuré à &e%2%&r!' + help: utilise /pa {arenaname} set [page] pour obtenir la liste des configurations + unknown: 'Config inconnue: &e%1%&r!' + setowner: + done: '&a%1%&r est maintenant propritétaire de l''arène &a%2%&r!' + spawn: + freelounge: Lounge configuré + teamlounge: 'Lounge configuré: %1%' + notset: 'Spawn non configuré: &a%1%&r' + offset: Spawn &a%1%&r offset by &a%2%&r blocks. + removed: 'Spawn supprimé: &a%1%&r' + set: 'Spawn configuré: &a%1%&r' + setdone: 'Paramètrage du spawn terminé: &a%1%&r' + setstart: 'Paramètrage du spawn: &a%1%&r' + unknown: 'Spawn not found: &a%1%&r' + stats: + filedone: Fichier stats chargé ! + head: Statistics TOP %1% (%2%) + typenotfound: 'Type de statistique non trouvé! Valeurs correctes: &e%1%&r' + stattype: + DAMAGE: dommages totaux accordé + DAMAGETAKE: dommages totaux subis + DEATHS: morts + KILLS: tués + LOSSES: matchs perdus + MAXDAMAGE: domages maximums accordés + MAXDAMAGETAKE: Dommages maximums subis + 'NULL': nom du joueur + WINS: matchs gagnés + team: + haswon: L'équipe %1% gagne la partie ! + ready: L'équipe %1% est prête ! + teams: + list: 'Equipes disponibles: %1%' + add: 'Equipe ajoutée: %1%' + set: 'Equipe modifiée: %1%' + remove: 'Equipe suppriméé: %1%' + template: + loaddone: Template loaded from &a%1%&r + savedone: Template saved to &a%1%&r + time: + minutes: minutes + seconds: secondes + timer: + countdowninterrupt: Compte à rebours interrompu ! Frappe le bloc de départ ! + ending: Le match se termine dans %1% ! + resetting: L'arène sera réinitialisée dans %1% ! + starting: Début dans %1%! + warmingup: Echauffement... %1%! + pvpactivating: Le PVP sera activé dans %1%! + walls: Les murs disparaitront dans %1%! + togglemod: + notice: '&cYou activated a module that requires a BATTLE region! Type &r/pvparena + [arena] !rt [region] BATTLE' + uninstall: + done: 'supprimé: &a%1%&r' + whitelist: + added: .&a%1%&r ajouté à la whitelist &e%2%&r ! + allcleared: Toutes les whitelistes ont été effacées ! + cleared: Whitelist &e%1%&r effacée ! + help: 'Utilisation: blacklist clear | blacklist [type] [clear|add|remove] [id]' + removed: .&a%1%&r supprimé de la whiteliste &e%2%&r ! + show: 'Whitelist &e%1%&r:' + mod: + aftermatch: + aftermatch: L'aprèsmatch a commencé ! + startingin: AprèsMatch dans %1%! + spawnnotset: Spawn 'après' non configuré ! + announcements: + ignoreon: Vous ignorez maintenant les annonces ! + ignoreoff: Vous recevrez maintenant les annonces ! + arenaboards: + createarenaboard: créer un tableau des scores + arenaboarddestroyed: tableau des scores détruit ! + boardexists: Le tableau des scores existe déjà !' + sortingby: Tableau des scores maintenant trié par %1% + autovote: + arenarunning: 'Arène en cours: %1%' + autojoin: Arena auto join démarré ! + playervoted: '%2% a voté pour l''arène %1%!' + youvoted: Vous avez voté pour l'arène %1% ! + duel: + accepted: '%1% &ea accepté le challenge ! Que le jeu commence !' + announce: '%1% &evous a defié! Accepte le duel avec &f/pa %2% accept.' + announcemoney: '&eThey set up a fee of &c%1%&e!' + announce2: '&eCancel the duel with &r/pa %2% decline&e.' + cancelled: '&cThe duel has been cancelled!' + busy: '%1% &eis already in a fight Please try again later.' + declineds: Your opponent did decline. The duel has been cancelled. + declinedr: You cancelled the duel! + requested: You &echallenged &f%1%&e! + requestedalready: You already have challenged someone! + requestexpireds: Your opponent did not accept the request in time. The duel + has been cancelled. + requestexpiredr: You did not accept the request in time. The duel has been cancelled. + starting: Le duel commence ! + nodirectjoin: 'You may not join this arena directly! Use: &e/pa %1% duel [playername]' + fixinventorylos: + gamemode: Entrez en mode survie avant de rejoindre l'arène ! + invenory: Videz votre inventaire avant de rejoindre l'arène ! + latelounge: + llannounce: L'arène %1% est ouverte ! Le joueur %2% veut commencer. Rejoint + le avec /pa %1% + llposition: Vous attendez à la position numéro %1%! + llrejoin: Vous n'êtes pas en mesure de rejoindre les joueurs prêts. Rejoignez-les + quand vous pouvez ! + llwait: L'arène va ouvrir prochainement, veuillez être patient ! + playerfinder: + near: 'Joueur le plus proche: %1% blocs!' + point: La boussole pointe sur le joueur le plus proche ! + powerups: + invalidpowerupeffect: 'PowerupEffect invalide: %1%' + puplayer: '%1% a collecté le PowerUp %2%!' + puserver: PowerUp déployé! + respawnrelay: + respawning: Respawning in %1%! + skins: + dc: Connecté à DisguiseCraft ! + ld: Hooking into LibsDisguises! + nomod: Aucun plugin de déguisement trouvé, désactivation du module de skins + ! + showclass: La classe &e%1%&r wsera déguisée en &a%2% + showteam: L'équipe %1% sera déguisée en %2% + md: Connecté à MobDisguise ! + specialjoin: + done: Le join block est configuré - %1% + start: Configuration du join block ! + stop: Annulation de la selection du join block! + startfreeze: + announce: Le jeu commencera dans %1% secondes ! + tempperms: + noperms: Plugin de permission non trouvé, par défaut OP. + head: 'Permission temporaire de &e%1%&r:' + added: Permission temporaires &e%1%&r ajoutée à &a%2%&r + removed: Permission temporaire &e%1%&r supprimée à &a%2%&r + vault: + 'on': <3 eConomy + 'off': Date: Fri, 31 May 2019 09:37:54 +0200 Subject: [PATCH 023/115] move status.FIGHT check to right place --- .../pvparena/listeners/EntityListener.java | 8 ++++++ .../pvparena/listeners/PlayerListener.java | 26 ------------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/net/slipcor/pvparena/listeners/EntityListener.java b/src/net/slipcor/pvparena/listeners/EntityListener.java index f6182ce07..bae90cb13 100644 --- a/src/net/slipcor/pvparena/listeners/EntityListener.java +++ b/src/net/slipcor/pvparena/listeners/EntityListener.java @@ -281,6 +281,14 @@ public void onEntityDamageByEntity(final EntityDamageByEntityEvent event) { return; } + // cancel if defender or attacker are not fighting + if (apAttacker.getStatus() != Status.FIGHT || apDefender.getStatus() != Status.FIGHT ) { + arena.getDebugger().i("player or target is not fighting, cancel!", attacker); + arena.getDebugger().i("player or target is not fighting, cancel!", defender); + event.setCancelled(true); + return; + } + Bukkit.getScheduler().scheduleSyncDelayedTask(PVPArena.instance, new DamageResetRunnable(arena, attacker, defender), 1L); diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 46d84942d..61c7da680 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -449,32 +449,6 @@ public void onPlayerHunger(final FoodLevelChangeEvent event) { } } - /** - * Cancel damages when: - * - * - target has not (Status.FIGHT) - * - damager has not (Status.FIGHT) - * - * @param event EntityDamageByEntityEvent - */ - @EventHandler - public void onPlayerDamage(EntityDamageByEntityEvent event){ - - if (event.getEntityType() == EntityType.PLAYER && event.getDamager().getType() == EntityType.PLAYER) { - final ArenaPlayer damager = ArenaPlayer.parsePlayer(event.getDamager().getName()); - if(damager.getArena() == null) { - return; // no fighting player => OUT - } - - final ArenaPlayer target = ArenaPlayer.parsePlayer(event.getEntity().getName()); - - // cancel if damager or target not fighting - if (damager.getStatus() != Status.FIGHT || target.getStatus() != Status.FIGHT ) { - event.setCancelled(true); - } - } - } - @EventHandler(priority = EventPriority.LOW) public void onPlayerInteract(final PlayerInteractEvent event) { final Player player = event.getPlayer(); From 91cdcd79d00c0551d6b155e1e85dfa1624bfa459 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 13 Jun 2019 22:08:53 +0200 Subject: [PATCH 024/115] v1.14.0.309 - fix compatibility for 1.14 --- src/net/slipcor/pvparena/arena/ArenaPlayer.java | 6 ++---- src/net/slipcor/pvparena/listeners/PlayerListener.java | 9 ++++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index e208245e1..fcd543c77 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -865,8 +865,7 @@ public void showBloodParticles() { Player player = get(); player.getLocation() .getWorld() - .playEffect(player.getEyeLocation(), - Effect.STEP_SOUND, Material.NETHER_WART_BLOCK.getId()); + .playEffect(player.getEyeLocation(), Effect.STEP_SOUND, Material.NETHER_WART_BLOCK); } @@ -874,8 +873,7 @@ public void showBloodParticles() { public String toString() { final ArenaTeam team = getArenaTeam(); - return team == null ? name : team.getColorCodeString() + name - + ChatColor.RESET; + return team == null ? name : team.getColorCodeString() + name + ChatColor.RESET; } public void unsetSelection() { diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 61c7da680..3ac38535a 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -69,11 +69,10 @@ private boolean checkAndCommitCancel(final Arena arena, final Player player, return false; } final PlayerInteractEvent pie = (PlayerInteractEvent) event; - final Material mat = pie.getClickedBlock().getType(); - final Material check = arena == null ? Material.IRON_BLOCK : arena - .getReadyBlock(); - if (mat == Material.SIGN || mat == Material.WALL_SIGN - || mat == Material.WALL_SIGN || mat == check) { + final Block block = pie.getClickedBlock(); + final Material check = arena == null ? Material.IRON_BLOCK : arena.getReadyBlock(); + + if (block != null && (block.getState() instanceof Sign || block.getType() == check)) { DEBUG.i("signs and ready blocks allowed!", player); DEBUG.i("> false", player); return false; From a171a164ac8d7d797e86e93f25c191844393b8bd Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 13 Jun 2019 22:23:25 +0200 Subject: [PATCH 025/115] v1.14.0.312 - cleanup and new version numbers --- pom.xml | 8 ++++-- src/net/slipcor/pvparena/arena/Arena.java | 1 - .../slipcor/pvparena/arena/ArenaClass.java | 3 --- src/net/slipcor/pvparena/classes/PACheck.java | 1 - .../slipcor/pvparena/core/StringParser.java | 13 +++++----- src/net/slipcor/pvparena/goals/GoalFlags.java | 22 +++++++--------- .../slipcor/pvparena/goals/GoalInfect.java | 1 - .../pvparena/goals/GoalPhysicalFlags.java | 25 ++++++++----------- .../pvparena/goals/GoalTeamDeathConfirm.java | 1 - .../pvparena/loadables/ArenaGoalManager.java | 1 - .../pvparena/managers/InventoryManager.java | 1 - .../runnables/InventoryRefillRunnable.java | 2 -- src/plugin.yml | 4 +-- 13 files changed, 33 insertions(+), 50 deletions(-) diff --git a/pom.xml b/pom.xml index 38ce76923..650bce626 100644 --- a/pom.xml +++ b/pom.xml @@ -4,9 +4,13 @@ net.slipcor pvparena - 1.13-SNAPSHOT + 1.14.0-SNAPSHOT PVP Arena + + + + spigot-repo @@ -32,7 +36,7 @@ clean package install - pvparena + pvparena-${project.version}${buildVersion} ${basedir}/src diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index 9e5fce457..30ae7893e 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -2123,7 +2123,6 @@ public boolean tryJoin(final Player player, final ArenaTeam team) { if ("ALL".equals(clear) || clear.contains(player.getGameMode().name())) { player.getInventory().clear(); - player.updateInventory(); ArenaPlayer.backupAndClearInventory(this, player); aPlayer.dump(); } diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java index 4ecb8b161..b35cdfcb1 100644 --- a/src/net/slipcor/pvparena/arena/ArenaClass.java +++ b/src/net/slipcor/pvparena/arena/ArenaClass.java @@ -192,7 +192,6 @@ public void run() { } i++; } - player.updateInventory(); } public static void equip(final Player player, final ItemStack[][] itemArray) { @@ -218,7 +217,6 @@ public void run() { player.getInventory().addItem(item); } } - player.updateInventory(); } public void equip(final Player player) { @@ -239,7 +237,6 @@ public void equip(final Player player) { } } player.getInventory().setItemInOffHand(offHand); - player.updateInventory(); } private static void equipArmor(final ItemStack stack, final PlayerInventory inv) { diff --git a/src/net/slipcor/pvparena/classes/PACheck.java b/src/net/slipcor/pvparena/classes/PACheck.java index ae89d4c12..e3f2d5969 100644 --- a/src/net/slipcor/pvparena/classes/PACheck.java +++ b/src/net/slipcor/pvparena/classes/PACheck.java @@ -538,7 +538,6 @@ public static void handlePlayerDeath(final Arena arena, player.getKiller().getInventory().addItem(item.clone()); } } - player.getKiller().updateInventory(); } if (arena.getArenaConfig().getBoolean(CFG.USES_TELEPORTONKILL)) { SpawnManager.respawn(arena, ArenaPlayer.parsePlayer(player.getKiller().getName()), null); diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index b2e94f27f..0157dcafa 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -1,15 +1,11 @@ package net.slipcor.pvparena.core; import net.slipcor.pvparena.PVPArena; -import org.bukkit.*; +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; import org.bukkit.block.BlockFace; -import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.*; -import org.bukkit.potion.PotionData; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.potion.PotionType; import java.util.*; @@ -130,6 +126,9 @@ public static ChatColor getChatColorFromWoolEnum(final String color) { return ChatColor.valueOf(parseDyeColorToChatColor(color, true)); } + public static Material getColoredWoolFromChatColor(final String color) { + return getWoolFallbackMaterialFromString(ChatColor.valueOf(color)); + } private static String getWoolEnumFromChatColorEnum(final String color) { return parseDyeColorToChatColor(color, false); diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 4e94c0391..9f55144d1 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -328,13 +328,11 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block .getHelmet().clone()); } catch (final Exception e) { } - final ItemStack itemStack = block.getState().getData().toItemStack(1) - .clone(); - if (arena.getArenaConfig().getBoolean( - CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { - itemStack.setDurability(getFlagOverrideTeamShort(arena, aTeam)); + + if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { + final ItemStack itemStack = new ItemStack(getFlagOverrideTeamMaterial(arena, aTeam)); + player.getInventory().setHelmet(itemStack); } - player.getInventory().setHelmet(itemStack); applyEffects(player); takeFlag(team.getColor(), true, @@ -741,17 +739,15 @@ private Map getFlagMap() { return flagMap; } - private short getFlagOverrideTeamShort(final Arena arena, final String team) { + private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) { if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) { if ("touchdown".equals(team)) { - return StringParser - .getColorDataFromENUM(ChatColor.BLACK.name()); + return StringParser.getColoredWoolFromChatColor(ChatColor.BLACK.name()); } - return StringParser.getColorDataFromENUM(arena.getTeam(team) - .getColor().name()); + return StringParser.getColoredWoolFromChatColor(arena.getTeam(team).getColor().name()); } - return StringParser.getColorDataFromENUM((String) arena - .getArenaConfig().getUnsafe("flagColors." + team)); + return StringParser.getColoredWoolFromChatColor( + (String) arena.getArenaConfig().getUnsafe("flagColors." + team)); } @Override diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java index 92e8ec57f..f50a0d14b 100644 --- a/src/net/slipcor/pvparena/goals/GoalInfect.java +++ b/src/net/slipcor/pvparena/goals/GoalInfect.java @@ -35,7 +35,6 @@ import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.inventory.ItemStack; import java.util.*; diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java index 58ebaaf24..21a2c7f4c 100644 --- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java @@ -673,17 +673,15 @@ private Map getFlagMap() { return flagMap; } - private short getFlagOverrideTeamShort(final Arena arena, final String team) { + private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) { if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) { if ("touchdown".equals(team)) { - return StringParser - .getColorDataFromENUM(ChatColor.BLACK.name()); + return StringParser.getColoredWoolFromChatColor(ChatColor.BLACK.name()); } - return StringParser.getColorDataFromENUM(arena.getTeam(team) - .getColor().name()); + return StringParser.getColoredWoolFromChatColor(arena.getTeam(team).getColor().name()); } - return StringParser.getColorDataFromENUM((String) arena - .getArenaConfig().getUnsafe("flagColors." + team)); + return StringParser.getColoredWoolFromChatColor( + (String) arena.getArenaConfig().getUnsafe("flagColors." + team)); } @Override @@ -1079,17 +1077,14 @@ public void onFlagClaim(final BlockBreakEvent event) { } catch (final Exception e) { } - final ItemStack itemStack = block.getState().getData().toItemStack(1) - .clone(); - if (arena.getArenaConfig().getBoolean( - CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { - itemStack.setDurability(getFlagOverrideTeamShort(arena, aTeam)); + + if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { + final ItemStack itemStack = new ItemStack(getFlagOverrideTeamMaterial(arena, aTeam)); + player.getInventory().setHelmet(itemStack); } - player.getInventory().setHelmet(itemStack); applyEffects(player); - takeFlag(team.getColor(), true, - new PABlockLocation(block.getLocation())); + takeFlag(team.getColor(), true, new PABlockLocation(block.getLocation())); getFlagMap().put(aTeam, player.getName()); return; diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java index f244d6a05..86f9ac429 100644 --- a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java +++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java @@ -25,7 +25,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityPickupItemEvent; import org.bukkit.event.entity.PlayerDeathEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; diff --git a/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java b/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java index e60d7847c..b6508ea8b 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java +++ b/src/net/slipcor/pvparena/loadables/ArenaGoalManager.java @@ -20,7 +20,6 @@ import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerPickupItemEvent; import java.io.File; import java.util.*; diff --git a/src/net/slipcor/pvparena/managers/InventoryManager.java b/src/net/slipcor/pvparena/managers/InventoryManager.java index e15e0ae8c..33c92c4b6 100644 --- a/src/net/slipcor/pvparena/managers/InventoryManager.java +++ b/src/net/slipcor/pvparena/managers/InventoryManager.java @@ -162,6 +162,5 @@ public static void transferItems(final Player player, final Inventory blockInven } } } - player.updateInventory(); } } diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java index 6bf2dbda9..fd1d76733 100644 --- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java +++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java @@ -107,7 +107,6 @@ public void run() { for (final ItemStack item : additions) { player.getInventory().addItem(item); } - player.updateInventory(); } else if (refill) { InventoryManager.clearInventory(player); ArenaPlayer.givePlayerFightItems(arena, player); @@ -115,7 +114,6 @@ public void run() { for (final ItemStack item : additions) { player.getInventory().addItem(item); } - player.updateInventory(); } } else { arena.getDebugger().i("NOT"); diff --git a/src/plugin.yml b/src/plugin.yml index a51948a92..637ee047c 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,9 +1,9 @@ name: pvparena author: slipcor -authors: [slipcor] +authors: [slipcor, Eredrim] prefix: PVP Arena main: net.slipcor.pvparena.PVPArena -version: 1.13.9.301 +version: ${project.version}${buildVersion} api-version: 1.13 softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot] description: create, manage and enhance PvP arenas From 47b1633c15b8bb3ceef107e0f9a344fcbd4d9aac Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 18 Jun 2019 22:00:36 +0200 Subject: [PATCH 026/115] v1.14.0 - Refactor color utils and improve domination --- .../slipcor/pvparena/arena/ArenaPlayer.java | 4 +- src/net/slipcor/pvparena/arena/ArenaTeam.java | 4 +- src/net/slipcor/pvparena/core/ColorUtils.java | 115 ++++++++++++++++++ .../slipcor/pvparena/core/StringParser.java | 112 +---------------- src/net/slipcor/pvparena/core/Utils.java | 57 +-------- .../pvparena/goals/GoalBlockDestroy.java | 8 +- .../pvparena/goals/GoalDomination.java | 54 ++++---- src/net/slipcor/pvparena/goals/GoalFlags.java | 19 ++- .../pvparena/goals/GoalPhysicalFlags.java | 19 ++- .../pvparena/goals/GoalTeamDeathConfirm.java | 5 - .../runnables/CircleParticleRunnable.java | 40 ++++-- .../runnables/InventoryRefillRunnable.java | 4 +- 12 files changed, 202 insertions(+), 239 deletions(-) create mode 100644 src/net/slipcor/pvparena/core/ColorUtils.java diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index fcd543c77..03a4c7a39 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -4,10 +4,10 @@ import net.slipcor.pvparena.classes.PABlockLocation; import net.slipcor.pvparena.classes.PALocation; import net.slipcor.pvparena.classes.PAStatMap; +import net.slipcor.pvparena.core.ColorUtils; import net.slipcor.pvparena.core.Config; import net.slipcor.pvparena.core.Config.CFG; import net.slipcor.pvparena.core.Debug; -import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.events.PAPlayerClassChangeEvent; import net.slipcor.pvparena.loadables.ArenaModuleManager; import net.slipcor.pvparena.managers.ArenaManager; @@ -211,7 +211,7 @@ public static void givePlayerFightItems(final Arena arena, final Player player) arena.getDebugger().i("forcing woolhead: " + aTeam.getName() + '/' + color.name(), player); player.getInventory().setHelmet( - new ItemStack(Utils.getWoolMaterialFromChatColor(color))); + new ItemStack(ColorUtils.getWoolMaterialFromChatColor(color))); } } diff --git a/src/net/slipcor/pvparena/arena/ArenaTeam.java b/src/net/slipcor/pvparena/arena/ArenaTeam.java index d2c62ce4f..3c6a35eb6 100644 --- a/src/net/slipcor/pvparena/arena/ArenaTeam.java +++ b/src/net/slipcor/pvparena/arena/ArenaTeam.java @@ -1,8 +1,8 @@ package net.slipcor.pvparena.arena; import net.slipcor.pvparena.arena.ArenaPlayer.Status; +import net.slipcor.pvparena.core.ColorUtils; import net.slipcor.pvparena.core.Debug; -import net.slipcor.pvparena.core.StringParser; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -34,7 +34,7 @@ public class ArenaTeam { */ public ArenaTeam(final String name, final String color) { players = new HashSet<>(); - this.color = StringParser.getChatColorFromWoolEnum(color); + this.color = ColorUtils.getChatColorFromDyeColor(color); this.name = name; } diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java new file mode 100644 index 000000000..4f350b4b5 --- /dev/null +++ b/src/net/slipcor/pvparena/core/ColorUtils.java @@ -0,0 +1,115 @@ +package net.slipcor.pvparena.core; + +import org.bukkit.ChatColor; +import org.bukkit.DyeColor; +import org.bukkit.Material; + +import java.util.Arrays; +import java.util.List; + +import static net.slipcor.pvparena.core.StringParser.joinArray; + +public final class ColorUtils { + + private static final Debug DEBUG = new Debug(18); + + private ColorUtils() { + } + + public static Material getWoolMaterialFromChatColor(final String color) { + return getWoolMaterialFromChatColor(ChatColor.valueOf(color)); + } + + public static Material getWoolMaterialFromChatColor(final ChatColor color) { + return getColoredMaterialFromChatColor(color, Material.WHITE_WOOL); + } + + /** + * Get a colored Material from a chat color and any colorable material + * @param color Color from chat + * @param material Colorable material like Wool, Concrete or Stained glass + * @return + */ + public static Material getColoredMaterialFromChatColor(final ChatColor color, final Material material) { + /* + Unsupported: + ChatColor.AQUA + Material.BROWN_WOOL + */ + + DyeColor dyeColor = getDyeColorFromChatColor(color); + return getColoredMaterial(dyeColor, material); + } + + public static DyeColor getDyeColorFromChatColor(ChatColor color) { + try { + return DyeColor.valueOf(parseDyeColorToChatColor(color.name(), false)); + } catch (IllegalArgumentException e) { + DEBUG.i("ChatColor " + color.name() + " can't be cast to DyeColor => set BROWN"); + return DyeColor.BROWN; + } + } + + public static ChatColor getChatColorFromDyeColor(final String color) { + return ChatColor.valueOf(parseDyeColorToChatColor(color, true)); + } + + private static String parseDyeColorToChatColor(final String color, final boolean forward) { + /* + following colors are the sames (ignore): WHITE, YELLOW, BLACK + colors not being able to parse: chat-AQUA, wool-brown + */ + + final List wool = Arrays.asList("ORANGE", "MAGENTA", "LIGHT_BLUE", "LIME", "PINK", "GRAY", "SILVER", + "PURPLE", "BLUE", "GREEN", "RED", "CYAN"); + final List chat = Arrays.asList("GOLD", "LIGHT_PURPLE", "BLUE", "GREEN", "RED", "DARK_GRAY", "GRAY", + "DARK_PURPLE", "DARK_BLUE", "DARK_GREEN", "DARK_RED", "DARK_AQUA"); + + if (forward) { + if (wool.contains(color)) { + return chat.get(wool.indexOf(color)); + } + } else { + if (chat.contains(color)) { + return wool.get(chat.indexOf(color)); + } + } + return color; + } + + /** + * Check if a material can be colored + * @param type Material to check + * @return true if material can be colored + */ + public static boolean isColorableMaterial(Material type) { + return type.name().endsWith("_WOOL") || type.name().endsWith("_CONCRETE") || + type.name().endsWith("_STAINED_GLASS"); + } + + /** + * Get a colored material applying dye color on a material + * @param dyeColor DyeColor to get color + * @param typeMaterial Material used to get type + * @return colored material + */ + public static Material getColoredMaterial(DyeColor dyeColor, Material typeMaterial) { + String color = dyeColor.name(); + String[] typeNameArr = typeMaterial.name().split("_"); + String uncoloredMaterial = joinArray(Arrays.copyOfRange(typeNameArr, 1, typeNameArr.length), "_"); + return Material.valueOf(color + "_" + uncoloredMaterial); + } + + public static boolean isSubType(Material type, Material check) { + if (type.name().endsWith("_WOOL") && check.name().endsWith("_WOOL")) { + return true; + } + if (type.name().endsWith("_CONCRETE") && check.name().endsWith("_CONCRETE")) { + return true; + } + if (type.name().endsWith("_STAINED_GLASS") && check.name().endsWith("_STAINED_GLASS")) { + return true; + } + return false; + } +} diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index 0157dcafa..f5e1efe13 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -1,13 +1,13 @@ package net.slipcor.pvparena.core; -import net.slipcor.pvparena.PVPArena; import org.bukkit.ChatColor; -import org.bukkit.DyeColor; -import org.bukkit.Material; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** *

@@ -95,70 +95,6 @@ public static String colorVar(final String string, final boolean value) {
                 + ChatColor.WHITE;
     }
 
-    /**
-     * calculate a WOOL byte from a color enum
-     *
-     * @param color the string to parse
-     * @return the color short
-     */
-    public static byte getColorDataFromENUM(final String color) {
-
-        String wool = getWoolEnumFromChatColorEnum(color);
-        if (wool == null) {
-            wool = color;
-        }
-        /*
-		 * DyeColor supports: WHITE, ORANGE, MAGENTA, LIGHT_BLUE, YELLOW, LIME,
-		 * PINK, GRAY, SILVER, CYAN, PURPLE, BLUE, BROWN, GREEN, RED, BLACK;
-		 */
-
-        for (final DyeColor dc : DyeColor.values()) {
-            if (dc.name().equalsIgnoreCase(wool)) {
-                return (byte) (15 - dc.getDyeData());
-            }
-        }
-        PVPArena.instance.getLogger().warning("unknown color enum: " + wool);
-
-        return (byte) 0;
-    }
-
-    public static ChatColor getChatColorFromWoolEnum(final String color) {
-        return ChatColor.valueOf(parseDyeColorToChatColor(color, true));
-    }
-
-    public static Material getColoredWoolFromChatColor(final String color) {
-        return getWoolFallbackMaterialFromString(ChatColor.valueOf(color));
-    }
-
-    private static String getWoolEnumFromChatColorEnum(final String color) {
-        return parseDyeColorToChatColor(color, false);
-    }
-
-    public static Material getWoolFallbackMaterialFromString(final ChatColor color)  {
-        Map results = new HashMap<>();
-        results.put(ChatColor.BLACK, Material.BLACK_WOOL);
-        results.put(ChatColor.DARK_BLUE, Material.BLUE_WOOL);
-        results.put(ChatColor.DARK_AQUA, Material.LIGHT_BLUE_WOOL);
-        results.put(ChatColor.DARK_RED, Material.RED_WOOL);
-        results.put(ChatColor.DARK_PURPLE, Material.PURPLE_WOOL);
-        results.put(ChatColor.GOLD, Material.BROWN_WOOL);
-        results.put(ChatColor.GRAY, Material.LIGHT_GRAY_WOOL);
-        results.put(ChatColor.DARK_GRAY, Material.GRAY_WOOL);
-        results.put(ChatColor.BLUE, Material.LIGHT_BLUE_WOOL);
-        results.put(ChatColor.GREEN, Material.LIME_WOOL);
-        results.put(ChatColor.AQUA, Material.CYAN_WOOL);
-        results.put(ChatColor.RED, Material.PINK_WOOL);
-        results.put(ChatColor.LIGHT_PURPLE, Material.MAGENTA_WOOL);
-        results.put(ChatColor.YELLOW, Material.YELLOW_WOOL);
-        results.put(ChatColor.WHITE, Material.WHITE_WOOL);
-
-        if (results.containsKey(color)) {
-            return results.get(color);
-        }
-        DEBUG.i(">> Material defaulting '"+color+"' to BROWN_WOOL!! <<");
-        return Material.BROWN_WOOL;
-    }
-
     public static String joinArray(final Object[] array, final String glue) {
         final StringBuilder result = new StringBuilder("");
         for (final Object o : array) {
@@ -195,46 +131,6 @@ public static String joinSet(final Set set, final String glue) {
         return result.substring(glue.length());
     }
 
-    private static String parseDyeColorToChatColor(final String color, final boolean forward) {
-
-        /*
-          wool colors: ORANGE, MAGENTA, LIGHT_BLUE, LIME, PINK, GRAY, SILVER,
-          PURPLE, BLUE, GREEN, RED, CYAN;
-
-          chat colors: GOLD, LIGHT_PURPLE, BLUE, GREEN, RED, DARK_GRAY, GRAY,
-          DARK_PURPLE, DARK_BLUE, DARK_GREEN, DARK_RED, DARK_AQUA
-
-          both colors (ignore): WHITE, YELLOW, BLACK
-
-          colors not being able to parse:
-
-          chat-AQUA, wool-brown
-         */
-        final String[] wool = {"ORANGE", "MAGENTA", "LIGHT_BLUE",
-                "LIME", "PINK", "GRAY", "SILVER", "PURPLE", "BLUE",
-                "GREEN", "RED", "CYAN"};
-        final String[] chat = {"GOLD", "LIGHT_PURPLE", "BLUE",
-                "GREEN", "RED", "DARK_GRAY", "GRAY", "DARK_PURPLE", "DARK_BLUE",
-                "DARK_GREEN", "DARK_RED", "DARK_AQUA"};
-
-        if (forward) {
-            for (int i = 0; i < wool.length; i++) {
-                if (color.equals(wool[i])) {
-                    return chat[i];
-                }
-            }
-        } else {
-
-            for (int i = 0; i < chat.length; i++) {
-                if (color.equals(chat[i])) {
-                    return wool[i];
-                }
-            }
-        }
-
-        return color;
-    }
-
     public static String[] shiftArrayBy(final String[] args, final int offset) {
         final String[] newArgs = new String[args.length - offset];
         System.arraycopy(args, offset, newArgs, 0, args.length - offset);
diff --git a/src/net/slipcor/pvparena/core/Utils.java b/src/net/slipcor/pvparena/core/Utils.java
index 7d92f7ed8..4b83ea775 100644
--- a/src/net/slipcor/pvparena/core/Utils.java
+++ b/src/net/slipcor/pvparena/core/Utils.java
@@ -1,6 +1,6 @@
 package net.slipcor.pvparena.core;
 
-import org.bukkit.ChatColor;
+import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.inventory.ItemStack;
 
@@ -37,58 +37,7 @@ public static List> getSerializableItemStacks(ItemStack item
         return getSerializableItemStacks(new ItemStack[]{itemStack});
     }
 
-    public static Material getWoolMaterialFromChatColor(final ChatColor color) {
-        /*
-        Unsupported:
-        ChatColor.AQUA
-        Material.BROWN_WOOL
-        */
-
-        switch (color) {
-            case BLACK:
-                return Material.BLACK_WOOL;
-            case DARK_BLUE:
-                return Material.BLUE_WOOL;
-            case DARK_GREEN:
-                return Material.GREEN_WOOL;
-            case DARK_AQUA:
-                return Material.CYAN_WOOL;
-            case DARK_RED:
-                return Material.RED_WOOL;
-            case DARK_PURPLE:
-                return Material.PURPLE_WOOL;
-            case GOLD:
-                return Material.ORANGE_WOOL;
-            case GRAY:
-                return Material.LIGHT_GRAY_WOOL;
-            case DARK_GRAY:
-                return Material.GRAY_WOOL;
-            case BLUE:
-                return Material.LIGHT_BLUE_WOOL;
-            case GREEN:
-                return Material.LIME_WOOL;
-            case RED:
-                return Material.PINK_WOOL;
-            case LIGHT_PURPLE:
-                return Material.MAGENTA_WOOL;
-            case YELLOW:
-                return Material.YELLOW_WOOL;
-            case WHITE:
-            default:
-                return Material.WHITE_WOOL;
-        }
-    }
-
-    public static boolean isSubType(Material type, Material check) {
-        if (type.name().endsWith("_WOOL") && check.name().endsWith("_WOOL")) {
-            return true;
-        }
-        if (type.name().endsWith("_CONCRETE") && check.name().endsWith("_CONCRETE")) {
-            return true;
-        }
-        if (type.name().endsWith("_STAINED_GLASS") && check.name().endsWith("_STAINED_GLASS")) {
-            return true;
-        }
-        return false;
+    public static Location getCenteredLocation(Location loc) {
+        return new Location(loc.getWorld(), loc.getBlockX() + 0.5, loc.getBlockY() + 0.5, loc.getBlockZ() + 0.5);
     }
 }
diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
index 8776b2bea..a76f69eb0 100644
--- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
+++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
@@ -11,12 +11,11 @@
 import net.slipcor.pvparena.classes.PACheck;
 import net.slipcor.pvparena.commands.CommandTree;
 import net.slipcor.pvparena.commands.PAA_Region;
+import net.slipcor.pvparena.core.ColorUtils;
 import net.slipcor.pvparena.core.Config.CFG;
 import net.slipcor.pvparena.core.Debug;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
-import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -500,10 +499,11 @@ void takeBlock(final ChatColor blockColor, final PABlockLocation paBlockLocation
         if (paBlockLocation == null) {
             return;
         }
-        if (Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE)), Material.WHITE_WOOL)) {
+        Material blockDestroyType = Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE));
+        if (ColorUtils.isColorableMaterial(blockDestroyType)) {
             paBlockLocation.toLocation()
                     .getBlock()
-                    .setType(StringParser.getWoolFallbackMaterialFromString(blockColor));
+                    .setType(ColorUtils.getColoredMaterialFromChatColor(blockColor, blockDestroyType));
         } else {
             paBlockLocation.toLocation()
                     .getBlock()
diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java
index 43d8f6b2a..1aefb8602 100644
--- a/src/net/slipcor/pvparena/goals/GoalDomination.java
+++ b/src/net/slipcor/pvparena/goals/GoalDomination.java
@@ -8,12 +8,9 @@
 import net.slipcor.pvparena.arena.ArenaTeam;
 import net.slipcor.pvparena.classes.*;
 import net.slipcor.pvparena.commands.PAA_Region;
+import net.slipcor.pvparena.core.*;
 import net.slipcor.pvparena.core.Config.CFG;
-import net.slipcor.pvparena.core.Debug;
-import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
-import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -182,10 +179,11 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
      */
     private Set checkLocationPresentTeams(final Location loc, final int distance) {
         final Set result = new HashSet<>();
+        final Location flagCenter = Utils.getCenteredLocation(loc);
 
         for (final ArenaPlayer p : arena.getFighters()) {
 
-            if (p.get().getLocation().distance(loc) > distance) {
+            if (p.get().getLocation().distance(flagCenter) > distance) {
                 continue;
             }
 
@@ -225,16 +223,14 @@ void checkMove() {
         arena.getDebugger().i("   checkMove();");
         arena.getDebugger().i("------------------");
 
-        final int checkDistance = arena.getArenaConfig().getInt(
-                CFG.GOAL_DOM_CLAIMRANGE);
+        final int checkDistance = arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE);
 
         for (final PABlockLocation paLoc : SpawnManager.getBlocksStartingWith(arena, "flag")) {
             // arena.getDebugger().info("checking location: " + loc.toString());
 
             final Location loc = paLoc.toLocation();
 
-            final Set teams = checkLocationPresentTeams(paLoc.toLocation(),
-                    checkDistance);
+            final Set teams = checkLocationPresentTeams(loc, checkDistance);
 
             arena.getDebugger().i("teams: " + StringParser.joinSet(teams, ", "));
 
@@ -281,17 +277,16 @@ void checkMove() {
                             // unclaim
                             arena.getDebugger().i("      - not being unclaimed. do it!");
                             ArenaTeam team = arena.getTeam(getFlagMap().get(loc));
-                            arena.broadcast(Language.parse(arena, MSG.GOAL_DOMINATION_CONTESTING, team.getColoredName() + ChatColor.YELLOW));
+                            String contestingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_CONTESTING, team.getColoredName() + ChatColor.YELLOW);
+                            arena.broadcast(contestingMsg);
                             final DominationRunnable domRunner = new DominationRunnable(
                                     arena, false, loc,
                                     getFlagMap().get(loc), this);
                             domRunner.runID = Bukkit.getScheduler()
-                                    .scheduleSyncRepeatingTask(
-                                            PVPArena.instance, domRunner, 10 * 20L,
-                                            10 * 20L);
+                                    .scheduleSyncRepeatingTask(PVPArena.instance, domRunner, 10 * 20L, 10 * 20L);
+
                             getRunnerMap().put(loc, domRunner);
-                            barStart(loc, Language.parse(arena,
-                                    MSG.GOAL_DOMINATION_UNCLAIMING), ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), 200L);
+                            barStart(loc, contestingMsg, ChatColor.WHITE, checkDistance, 200L);
                         }
                     } else {
                         // just the owning team is there
@@ -335,7 +330,8 @@ void checkMove() {
                 arena.getDebugger().i("    - not yet being unclaimed, do it!");
                 // create an unclaim runnable
                 ArenaTeam team = arena.getTeam(getFlagMap().get(loc));
-                arena.broadcast(Language.parse(arena, MSG.GOAL_DOMINATION_UNCLAIMING, team.getColoredName() + ChatColor.YELLOW));
+                String unclaimingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_UNCLAIMING, team.getColoredName() + ChatColor.YELLOW);
+                arena.broadcast(unclaimingMsg);
                 final DominationRunnable running = new DominationRunnable(arena,
                         false, loc, getFlagMap().get(loc), this);
                 final long interval = 20L * 10;
@@ -343,8 +339,7 @@ void checkMove() {
                 running.runID = Bukkit.getScheduler().scheduleSyncRepeatingTask(
                         PVPArena.instance, running, interval, interval);
                 getRunnerMap().put(loc, running);
-                barStart(loc, Language.parse(arena,
-                        MSG.GOAL_DOMINATION_UNCLAIMING), ChatColor.WHITE, arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval);
+                barStart(loc, unclaimingMsg, ChatColor.WHITE, checkDistance, interval);
             } else {
                 // flag not taken
                 arena.getDebugger().i("- flag not taken");
@@ -384,9 +379,9 @@ void checkMove() {
                             arena.getDebugger().i("TEAM " + sName + " IS CLAIMING "
                                     + loc);
                             final ArenaTeam team = arena.getTeam(sName);
-                            arena.broadcast(Language.parse(arena,
-                                    MSG.GOAL_DOMINATION_CLAIMING,
-                                    team.getColoredName() + ChatColor.YELLOW));
+                            String claimingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_CLAIMING,
+                                    team.getColoredName() + ChatColor.YELLOW);
+                            arena.broadcast(claimingMsg);
 
                             final DominationRunnable running = new DominationRunnable(
                                     arena, true, loc, sName, this);
@@ -396,8 +391,7 @@ void checkMove() {
                                             PVPArena.instance, running,
                                             interval, interval);
                             getRunnerMap().put(loc, running);
-                            barStart(loc, Language.parse(arena,
-                                    MSG.GOAL_DOMINATION_CLAIMING), team.getColor(), arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE), interval);
+                            barStart(loc, claimingMsg, team.getColor(), checkDistance, interval);
                         }
                     } else {
                         arena.getDebugger().i("  - more than one team present. continue!");
@@ -454,7 +448,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block
                 || !PAA_Region.activeSelections.containsKey(player.getName())) {
             return res;
         }
-        if (block == null || !block.getType().name().contains("WOOL")) {
+        if (block == null || !ColorUtils.isColorableMaterial(block.getType())) {
             return res;
         }
         res.setPriority(this, PRIORITY); // success :)
@@ -701,7 +695,7 @@ public void parseStart() {
 
         announceOffset = arena.getArenaConfig().getInt(CFG.GOAL_DOM_ANNOUNCEOFFSET);
 
-        circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(arena, CFG.GOAL_DOM_CLAIMRANGE), 1L, 1L);
+        circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(arena, CFG.GOAL_DOM_CLAIMRANGE, getFlagMap()), 1L, 1L);
     }
 
     private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String team) {
@@ -757,8 +751,9 @@ public void setDefaults(final YamlConfiguration config) {
      * take/reset an arena flag
      *
      * @param paBlockLocation the location to take/reset*/
-    void takeFlag(final PABlockLocation paBlockLocation) {
-        paBlockLocation.toLocation().getBlock().setType(Material.WHITE_WOOL);
+    private void takeFlag(final PABlockLocation paBlockLocation) {
+        Block flagBlock = paBlockLocation.toLocation().getBlock();
+        flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(ChatColor.WHITE, flagBlock.getType()));
     }
 
     @Override
@@ -839,16 +834,17 @@ public void run() {
 
         private void takeFlag(final Arena arena, final Location lBlock, final String name) {
             ArenaTeam team = null;
+            Block flagBlock = lBlock.getBlock();
             for (final ArenaTeam t : arena.getTeams()) {
                 if (t.getName().equals(name)) {
                     team = t;
                 }
             }
             if (team == null) {
-                lBlock.getBlock().setType(Material.WHITE_WOOL);
+                flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(ChatColor.WHITE, flagBlock.getType()));
                 return;
             }
-            lBlock.getBlock().setType(Utils.getWoolMaterialFromChatColor(team.getColor()));
+            flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(team.getColor(), flagBlock.getType()));
         }
     }
 
diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java
index 9f55144d1..e74e40e52 100644
--- a/src/net/slipcor/pvparena/goals/GoalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalFlags.java
@@ -10,12 +10,9 @@
 import net.slipcor.pvparena.classes.PACheck;
 import net.slipcor.pvparena.commands.CommandTree;
 import net.slipcor.pvparena.commands.PAA_Region;
+import net.slipcor.pvparena.core.*;
 import net.slipcor.pvparena.core.Config.CFG;
-import net.slipcor.pvparena.core.Debug;
-import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
-import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -166,7 +163,7 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
         }
 
         Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
-        if (!Utils.isSubType(block.getType(), flagType)) {
+        if (!ColorUtils.isSubType(block.getType(), flagType)) {
             arena.getDebugger().i("block, but not flag", player);
             return res;
         }
@@ -429,7 +426,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block
         }
 
         Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
-        if (block == null || !Utils.isSubType(block.getType(), flagType)) {
+        if (block == null || !ColorUtils.isSubType(block.getType(), flagType)) {
             return res;
         }
 
@@ -742,11 +739,11 @@ private Map getFlagMap() {
     private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) {
         if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) {
             if ("touchdown".equals(team)) {
-                return StringParser.getColoredWoolFromChatColor(ChatColor.BLACK.name());
+                return ColorUtils.getWoolMaterialFromChatColor(ChatColor.BLACK);
             }
-            return StringParser.getColoredWoolFromChatColor(arena.getTeam(team).getColor().name());
+            return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor());
         }
-        return StringParser.getColoredWoolFromChatColor(
+        return ColorUtils.getWoolMaterialFromChatColor(
                 (String) arena.getArenaConfig().getUnsafe("flagColors." + team));
     }
 
@@ -998,7 +995,7 @@ void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocati
         if (paBlockLocation == null) {
             return;
         }
-        if (!Utils.isSubType(Material.getMaterial(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
+        if (!ColorUtils.isSubType(Material.getMaterial(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(
@@ -1012,7 +1009,7 @@ void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocati
                     .setType(Material.WHITE_WOOL);
         } else {
             paBlockLocation.toLocation().getBlock()
-                    .setType(StringParser.getWoolFallbackMaterialFromString(flagColor));
+                    .setType(ColorUtils.getWoolMaterialFromChatColor(flagColor));
         }
     }
 
diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
index 21a2c7f4c..216a934de 100644
--- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
@@ -10,12 +10,9 @@
 import net.slipcor.pvparena.classes.PACheck;
 import net.slipcor.pvparena.commands.CommandTree;
 import net.slipcor.pvparena.commands.PAA_Region;
+import net.slipcor.pvparena.core.*;
 import net.slipcor.pvparena.core.Config.CFG;
-import net.slipcor.pvparena.core.Debug;
-import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
-import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -162,7 +159,7 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
         arena.getDebugger().i("checking interact", player);
 
         Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
-        if (!Utils.isSubType(block.getType(), flagType)) {
+        if (!ColorUtils.isSubType(block.getType(), flagType)) {
             arena.getDebugger().i("block, but not flag", player);
             return res;
         }
@@ -366,7 +363,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block
         }
 
         Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
-        if (block == null || !Utils.isSubType(block.getType(), flagType)) {
+        if (block == null || !ColorUtils.isSubType(block.getType(), flagType)) {
             return res;
         }
 
@@ -676,11 +673,11 @@ private Map getFlagMap() {
     private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) {
         if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) {
             if ("touchdown".equals(team)) {
-                return StringParser.getColoredWoolFromChatColor(ChatColor.BLACK.name());
+                return ColorUtils.getWoolMaterialFromChatColor(ChatColor.BLACK);
             }
-            return StringParser.getColoredWoolFromChatColor(arena.getTeam(team).getColor().name());
+            return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor());
         }
-        return StringParser.getColoredWoolFromChatColor(
+        return ColorUtils.getWoolMaterialFromChatColor(
                 (String) arena.getArenaConfig().getUnsafe("flagColors." + team));
     }
 
@@ -936,7 +933,7 @@ void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocati
         if (paBlockLocation == null) {
             return;
         }
-        if (!Utils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
+        if (!ColorUtils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
             paBlockLocation.toLocation()
                     .getBlock()
                     .setType(
@@ -957,7 +954,7 @@ void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocati
                                 CFG.GOAL_FLAGS_FLAGTYPE));
 
                 if (attempt == null) {
-                    attempt = StringParser.getWoolFallbackMaterialFromString(flagColor);
+                    attempt = ColorUtils.getWoolMaterialFromChatColor(flagColor);
                 }
             }
             paBlockLocation.toLocation().getBlock().setType(attempt);
diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
index 86f9ac429..c26f5cb40 100644
--- a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
+++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
@@ -11,7 +11,6 @@
 import net.slipcor.pvparena.core.Debug;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -228,10 +227,6 @@ private void drop(final Player player, final ArenaTeam team) {
         player.getWorld().dropItem(player.getLocation(), item);
     }
 
-    private byte getDataFromTeam(final ArenaTeam team) {
-        return StringParser.getColorDataFromENUM(team.getColor().name());
-    }
-
     @Override
     public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
         if (res.getPriority() <= PRIORITY + 1000) {
diff --git a/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java b/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
index 81bd44d1d..36d66125f 100644
--- a/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
+++ b/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
@@ -2,18 +2,32 @@
 
 import net.slipcor.pvparena.arena.Arena;
 import net.slipcor.pvparena.classes.PABlock;
+import net.slipcor.pvparena.core.ColorUtils;
 import net.slipcor.pvparena.core.Config;
-import org.bukkit.Bukkit;
-import org.bukkit.Particle;
+import net.slipcor.pvparena.core.Utils;
+import org.bukkit.*;
+
+import java.util.HashMap;
+import java.util.Map;
 
 public class CircleParticleRunnable implements Runnable {
-    final Arena arena;
-    double radius = 3;
-    int i = 0;
+    private Map flagMap = new HashMap<>();
+    private final Arena arena;
+    private double radius;
+    private int i = 0;
 
-    public CircleParticleRunnable(Arena arena, Config.CFG config) {
+    public CircleParticleRunnable(Arena arena, Config.CFG config, Map flagMap) {
         this.arena = arena;
-        radius = arena.getArenaConfig().getInt(config, 3);
+        this.flagMap = flagMap;
+        this.radius = arena.getArenaConfig().getInt(config, 3);
+    }
+
+    private Color getDustColor(Location flagLocation) {
+        if(this.flagMap.containsKey(flagLocation)) {
+            ChatColor teamColor = this.arena.getTeam(flagMap.get(flagLocation)).getColor();
+            return ColorUtils.getDyeColorFromChatColor(teamColor).getColor();
+        }
+        return Color.WHITE;
     }
 
     @Override
@@ -21,16 +35,20 @@ public void run() {
 
         for (PABlock spawn : arena.getBlocks()) {
             if (spawn.getName().startsWith("flag") || spawn.getName().startsWith("beacon")) {
-                final double x = spawn.getLocation().getX() + radius * Math.cos(Math.toRadians(i));
-                final double y = spawn.getLocation().getY();
-                final double z = spawn.getLocation().getZ() + radius * Math.sin(Math.toRadians(i));
+                final Location flagCenter = Utils.getCenteredLocation(spawn.getLocation().toLocation());
+                final double x = flagCenter.getX() + radius * Math.cos(Math.toRadians(i));
+                final double y = flagCenter.getY();
+                final double z = flagCenter.getZ() + radius * Math.sin(Math.toRadians(i));
+
+                final Color dustColor = this.getDustColor(spawn.getLocation().toLocation());
 
                 Bukkit.getWorld(arena.getWorld()).spawnParticle(
                         Particle.REDSTONE,
                         x, y, z,
                         0, // count
                         1, 1, 1, // offsets (colors)
-                        1 // extra (lighting)
+                        1, // extra (lighting)
+                        new Particle.DustOptions(dustColor, 1)
                 );
             }
         }
diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
index fd1d76733..b9807084b 100644
--- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
+++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java
@@ -6,8 +6,8 @@
 import net.slipcor.pvparena.arena.ArenaPlayer;
 import net.slipcor.pvparena.arena.ArenaPlayer.Status;
 import net.slipcor.pvparena.arena.ArenaTeam;
+import net.slipcor.pvparena.core.ColorUtils;
 import net.slipcor.pvparena.core.Config.CFG;
-import net.slipcor.pvparena.core.Utils;
 import net.slipcor.pvparena.managers.InventoryManager;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
@@ -98,7 +98,7 @@ public void run() {
                     arena.getDebugger().i("forcing woolhead: " + aTeam.getName() + '/'
                             + chatColor.name(), player);
                     player.getInventory().setHelmet(
-                            new ItemStack(Utils.getWoolMaterialFromChatColor(chatColor), 1));
+                            new ItemStack(ColorUtils.getWoolMaterialFromChatColor(chatColor), 1));
                     PVPArena.instance.getAgm().refillInventory(arena, player);
                 }
             } else if (refill && "custom".equals(aPlayer.getArenaClass().getName())) {

From 2c007b94cfaaa8d5deeccb1314ce9c0143d447ce Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 18 Jun 2019 22:05:24 +0200
Subject: [PATCH 027/115] v1.14.0 - update french lang file for domination

---
 lang/lang_fr.yml | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml
index d04cfbe99..196051df1 100644
--- a/lang/lang_fr.yml
+++ b/lang/lang_fr.yml
@@ -306,9 +306,8 @@ nulang:
       claimed: '&eL''équipe %1% a capturé une position !'
       score: '&eL''équipe %1% a marqué %2% points.'
       contesting: '&eUne position capturée par l''équipe %1% est contestée !'
-      unclaiming: '&eLa position capturée par l''équipe %1% vient d''être libérée !'
-      unclaimingby: '&eLa position capturée par l''équipe %1% est en train d''être 
-        capturée par l''équipe %2% !'
+      unclaiming: '&eUne position capturée par l''équipe %1% est en train d''être libérée !'
+      unclaimingby: '&eLa position capturée par l''équipe %1% est en train d''être capturée par l''équipe %2% !'
     infected:
       lost: '&6Les joueurs infectés ont été tués !'
       player: '&c%1% est infecté !'

From bc4e3a8cb5f7062d0dcbcb98ab4bbed6eb307751 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 25 Jun 2019 01:21:47 +0200
Subject: [PATCH 028/115] v1.14.0 - fix wool head color for flag goals

---
 src/net/slipcor/pvparena/core/ColorUtils.java         | 6 +++---
 src/net/slipcor/pvparena/goals/GoalFlags.java         | 2 +-
 src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java
index 4f350b4b5..f2f41887c 100644
--- a/src/net/slipcor/pvparena/core/ColorUtils.java
+++ b/src/net/slipcor/pvparena/core/ColorUtils.java
@@ -16,8 +16,8 @@ public final class ColorUtils {
     private ColorUtils() {
     }
 
-    public static Material getWoolMaterialFromChatColor(final String color) {
-        return getWoolMaterialFromChatColor(ChatColor.valueOf(color));
+    public static Material getWoolMaterialFromDyeColor(final String color) {
+        return getColoredMaterial(DyeColor.valueOf(color), Material.WHITE_WOOL);
     }
 
     public static Material getWoolMaterialFromChatColor(final ChatColor color) {
@@ -60,7 +60,7 @@ following colors are the sames (ignore): WHITE, YELLOW, BLACK
           colors not being able to parse: chat-AQUA, wool-brown
          */
 
-        final List wool = Arrays.asList("ORANGE", "MAGENTA", "LIGHT_BLUE", "LIME", "PINK", "GRAY", "SILVER",
+        final List wool = Arrays.asList("ORANGE", "MAGENTA", "LIGHT_BLUE", "LIME", "PINK", "GRAY", "LIGHT_GRAY",
                 "PURPLE", "BLUE", "GREEN", "RED", "CYAN");
         final List chat = Arrays.asList("GOLD", "LIGHT_PURPLE", "BLUE", "GREEN", "RED", "DARK_GRAY", "GRAY",
                 "DARK_PURPLE", "DARK_BLUE", "DARK_GREEN", "DARK_RED", "DARK_AQUA");
diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java
index e74e40e52..50fc67f9c 100644
--- a/src/net/slipcor/pvparena/goals/GoalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalFlags.java
@@ -743,7 +743,7 @@ private Material getFlagOverrideTeamMaterial(final Arena arena, final String tea
             }
             return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor());
         }
-        return ColorUtils.getWoolMaterialFromChatColor(
+        return ColorUtils.getWoolMaterialFromDyeColor(
                 (String) arena.getArenaConfig().getUnsafe("flagColors." + team));
     }
 
diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
index 216a934de..9429fe405 100644
--- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
@@ -677,7 +677,7 @@ private Material getFlagOverrideTeamMaterial(final Arena arena, final String tea
             }
             return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor());
         }
-        return ColorUtils.getWoolMaterialFromChatColor(
+        return ColorUtils.getWoolMaterialFromDyeColor(
                 (String) arena.getArenaConfig().getUnsafe("flagColors." + team));
     }
 

From 11532f8e1292a8526c23d6110554729a9d53263e Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 25 Jun 2019 01:23:03 +0200
Subject: [PATCH 029/115] v1.14.0 - implement goal.dom.particlecircle
 permission

---
 src/net/slipcor/pvparena/goals/GoalDomination.java | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java
index 1aefb8602..5f9226c6b 100644
--- a/src/net/slipcor/pvparena/goals/GoalDomination.java
+++ b/src/net/slipcor/pvparena/goals/GoalDomination.java
@@ -695,7 +695,9 @@ public void parseStart() {
 
         announceOffset = arena.getArenaConfig().getInt(CFG.GOAL_DOM_ANNOUNCEOFFSET);
 
-        circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(arena, CFG.GOAL_DOM_CLAIMRANGE, getFlagMap()), 1L, 1L);
+        if(arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_PARTICLECIRCLE)) {
+            circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(arena, CFG.GOAL_DOM_CLAIMRANGE, getFlagMap()), 1L, 1L);
+        }
     }
 
     private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String team) {

From ac67b3ae36b083dee69f030d7fa2851f582d836c Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 25 Jun 2019 01:23:39 +0200
Subject: [PATCH 030/115] v1.14.0 - improve config documentation

---
 doc/configuration.md | 344 +++++++++++++++++++++++++------------------
 1 file changed, 197 insertions(+), 147 deletions(-)

diff --git a/doc/configuration.md b/doc/configuration.md
index 5fde9778c..66193d3b0 100644
--- a/doc/configuration.md
+++ b/doc/configuration.md
@@ -1,150 +1,200 @@
 # Configuration File
 
-This is a default configuation file. All parameters can be changed via in-game commands ([/pa set](commands/set.md)).
-
-    configversion: 1.0.6.198
-    chat:
-      colorNick: true               
-      defaultTeam: false
-      enabled: true
-      onlyPrivate: false
-      toGlobal: none
-    cmds:
-      defaultjoin: true
-      whitelist: []
-    damage:
-      armor: true
-      fromOutsiders: false
-      spawncamp: 1
-      weapons: true
-    general:
-      classspawn: false
-      classSwitchAfterRespawn: false
-      customReturnsGear: false
-      enabled: true
-      gm: 0
-      leavedeath: false
-      lang: none
-      owner: server
-      quickspawn: true
-      prefix: PVP Arena
-      showRemainingLives: true
-      smartspawn: false
-      time: -1
-      type: none
-      wand: 280
-    goal:   # This part depends on gamemode and goals
-      livesPerPlayer: false
-      endCountDown: 5
-      teamlives:
-        tlives: 10
+This is a default configuration file. All parameters can be changed via in-game commands ([/pa set](commands/set.md)).
+```yaml
+configversion: 1.3.3.217
+chat:
+  colorNick: true #Use team color in chat
+  defaultTeam: false #Limit chat to team only
+  enabled: true #Allows chat usage
+  onlyPrivate: false #Limit chat to the arena
+  toGlobal: none #Begin word to talk to all the arena of onlyPrivate is active. Eg: @all
+cmds:
+  defaultjoin: true #Join the arena if just typing /pa 
+  #List of allowed commands in the arena
+  whitelist:
+  - ungod
+  - login
+damage:
+  armor: true #Allow armor damage - false = unbreakable
+  bloodParticles: false #Show blood particles on fight
+  fromOutsiders: false #Allow external arena players to attack
+  spawncamp: 1 #If nocamp region flag is enabled, damage set to player
+  weapons: true #Allow weapon damage - false = unbreakable
+general:
+  classspawn: false #Create specific class spawns. Eg: blueTankSpawn
+  classSwitchAfterRespawn: false #If IngameClassSwitch is enabled, switch class only on next respawn
+  customReturnsGear: false #If player has custom inventory, reload it on respawn
+  enabled: true #Make arena accessible or not
+  gm: 0 #Arena game mode
+  leavedeath: false #Kill the player on battleground leaving
+  lang: none
+  owner: server #Set owner of the arena
+  regionclearexceptions: [] #List of regions where entities are not cleared
+  quickspawn: true #Spawn all players at the same time. If false, spawn player one by one.
+  prefix: MyArena #Name of the arena displayed in chat messages
+  showRemainingLives: true #Brodcast ramaning lives in chat
+  smartspawn: false #Spread players on spawn points in a balanced way
+  time: -1 #Arena day time in ticks, allow to make night arenas
+  type: free #Arena type : free or team
+  wand: STICK #Wand item for region selection
+goal:
+  #Goal specific configurations, see 'Enhancement' part of documentation
+  livesPerPlayer: false
+  endCountDown: 5
+  playerlives:
+    plives: 3
+  teamlives:
+    tlives: 10
+items:
+  keepAllOnRespawn: false #Keep inventory on respawn
+  excludeFromDrops: none #List of items not dropped on kill
+  keepOnRespawn: none #List of items kept on respawn (if keepAllOnRespawn is disabled)
+  minplayers: 2 #Minimum number of players to start fighting
+  random: true
+  rewards: none #List of reward items given to win team team/player
+  takeOutOfGame: none #List of items kept from player inventory out the game
+join:
+  range: 0 #Max distance from battleground to join arena. Set 0 to disable.
+  forceregionjoin: false #Limit arena join from "join" type region.
+  onlyifhasplayed: false #Allow player to join arena during game only if he played and left (with disconnection). Useful only if joinInBattle is enabled.
+block:
+  blacklist: [] #Blacklist of blocks player can't interact
+  whitelist: [] #Whitelist of blocks player can interact
+goals:
+  #List if enabled goals, see 'Enhancement' part of documentation
+- PlayerLives
+mods:
+  #List of enabled mods, see 'Enhancement' part of documentation
+- BattlefieldJoin
+- StandardLounge
+- StandardSpectate
+msg:
+  #Arena specific messages you can configure
+  lounge: Welcome to the arena lounge! Hit a class sign and then the iron block to
+    flag yourself as ready!
+  playerjoined: '%1% joined the Arena!'
+  playerjoinedteam: '%1% joined team %2%!'
+  starting: Arena is starting! Type &e/pa %1% to join!
+  youjoined: You have joined the FreeForAll Arena!
+  youjoinedteam: You have joined team %1%!
+perms:
+  alwaysJoinInBattle: false #Allow join during game in any case
+  explicitArenaNeeded: false #Player needs permission pvparena.join.arenaName to play arena
+  explicitClassNeeded: false #Player needs permission pvparena.class.className to get a class
+  fly: false #Enable/Disable fly for players
+  loungeinteract: false #If true, players can interact with other players and blocks within lounge
+  joinInBattle: false #Allow join during a game
+  joinWithScoreboard: true #Allow to join arena with scoreboard with AutoVote Mod
+  teamkill: true #Allow players to kill players of their own team
+  specTalk: true #Allow spectators to use chat
+  spectatorinteract: false #Allow spectator to interact with others
+player:
+  autoIgniteTNT: false #Ignite TNT on place
+  clearInventory: NONE #Clear player inventory on join. Set a specific game mode or ALL for any kind. 
+  collision: true #Allow player collision with ENTITIES (players, arrows, tridents, armor stands, etc)
+  dropsEXP: false #Killed players drop XP
+  dropsInventory: false #Killed players drop their inventory
+  exhaustion: 0.0 #Set player exhaustion
+  hungerforkill: 0 #Not used
+  foodLevel: 20 #Initial food level
+  health: -1 #Set initial player health. Use -1 for default server value. Must be lower or equal than maxHealth.
+  healforkill: false #Heal player who kills another one
+  hunger: true #Enable hunger, if false feed level never decreases
+  itemsonkill: none #List of items given to player who kills another one
+  mayChangeArmor: true #Allow players to edit their armor slots in game
+  maxhealth: -1 #Set maximum health for player. 1 heart = 2 pts. Use -1 for default server value.
+  preventDeath: true #Not really kill player in order to avoid "you are died" message
+  refillCustomInventory: true #Refill custom player inventory after death
+  refillInventory: true #Players keeps inventory they had before their death
+  refillforkill: false #Reset class inventory of a player who killed another one
+  removearrows: false #Remove arrows on body after death
+  saturation: 20 #Set hunger saturation
+  quickloot: false #Automatically transfer chest content to inventory
+protection:
+  enabled: true #Enable protections on regions. See "regions" part of documentation for more informations
+  punish: false #Damage players who don't respect protections
+  spawn: 0 #Radius around spawns where player fight is disallowed
+ready:
+  autoClass: none #Name of class set automatically when player joins an arena. Set "none" to disable. Set to "custom" if you use "playerClasses".
+  block: IRON_BLOCK #Block player can hit to be ready. Has the same effect than typing /pa ready.
+  checkEachPlayer: false #Check if each player is ready before start
+  checkEachTeam: true #Check if each team is ready before start
+  enforceCountdown: false #If everyone is ready, game start before the end of countdown
+  minPlayers: 2 #Minimum number of players to play the arena
+  maxPlayers: 4 #Maximum number of players to play the arena
+  maxTeam: 0 #Maximim number of player in each team
+  neededRatio: 0.5 #Ratio of ready player needed to start countdown
+time:
+  startCountDown: 10 #Start countdown in seconds
+  regionTimer: 10 #Time in ticks for region tasks. Don't change this.
+  teleportProtect: 3 #Number of seconds of invulnerability after teleport
+  resetDelay: -1 #Wait time (in ticks) to reset players when they exit arena
+  warmupCountDown: 0 #Warmup time (in seconds)
+  pvp: 0 #Time before PVP is enabled (in seconds)
+tp:
+  #Spawnpoints where players go after specific event. Use "old" to use player location before arena.
+  death: old #Spawnpoint where player goes after death (only if he can't respawn after death)
+  exit: exit #Spawnpoint where player goes after he leaves the arena
+  lose: exit #Spawnpoint where player or team goes if they lose the match
+  win: exit #Spawnpoint where player or team goes if they win the match
+  offsets: [] #Spawnpoint offsets. List of strings with following format : "spawnName:xOffset;yOffset;zOffset"
+uses:
+  classSignsDisplay: false #Display player names on class signs
+  deathMessages: true #Show death messages (from language file)
+  deathMessagesCustom: true #Not used
+  evenTeams: false #If true, requires the same number of players in each team
+  ingameClassSwitch: false #Allow to switch player class during a game
+  invisibilityfix: false #Force player to be visible
+  evilinvisibilityfix: false #Use this param if the previous one doesn't work
+  overlapCheck: true #Set to not check if the arena region collides with a running arena
+  playerclasses: false #Use players own inventory
+  scoreboard: true #Enable scoreboard
+  scoreboardrounddisplay: false #Show rounds number in scoreboard
+  suicidepunish: false #Increase other players score where someone commit suicide
+  teamrewards: false #Give reward to winning team
+  teleportonkill: false #Respawn KILLER after a kill
+  woolHead: false #Use a colored wool head as helmet
+flagColors:
+  #Flag colors with format  team: DYE_COLOR
+  #Use color among ORANGE, MAGENTA, LIGHT_BLUE, LIME, PINK, GRAY, LIGHT_GRAY, PURPLE, BLUE, GREEN, RED, CYAN, YELLOW, BLACK, WHITE
+  red: WHITE
+  blue: BLACK
+classitems:
+  #Class items. See "items" part of documentation for more information
+  warrior:
     items:
-      excludeFromDrops: none
-      keepOnRespawn: none
-      minplayers: 2
-      random: true
-      rewards: none
-      takeOutOfGame: none
-    join:
-      range: 0
-      forceregionjoin: false
-      onlyifhasplayed: false
-    block:
-      blacklist: []
-      whitelist: []
-    goals:
-    - TeamLives
-    mods:
-    - BattlefieldJoin
-    - StandardSpectate
-    - StandardLounge
-    msg:
-      lounge: Welcome to the arena lounge! Hit a class sign and then the iron block to flag yourself as ready!
-      playerjoined: '%1% joined the Arena!'
-      playerjoinedteam: '%1% joined team %2%!'
-      starting: Arena is starting! Type &e/pa %1% to join!
-      youjoined: You have joined the FreeForAll Arena!
-      youjoinedteam: You have joined team %1%!
-    perms:
-      alwaysJoinInBattle: false
-      explicitArenaNeeded: false
-      explicitClassNeeded: false
-      fly: false
-      loungeinteract: false
-      joinInBattle: false
-      joinWithScoreboard: true
-      teamkill: true
-      specTalk: true
-    player:
-      autoIgniteTNT: false
-      clearInventory: NONE
-      dropsEXP: false
-      dropsInventory: false
-      exhaustion: 0.0
-      hungerforkill: 0
-      foodLevel: 20
-      health: -1
-      healforkill: false
-      hunger: true
-      mayChangeArmor: true
-      maxhealth: -1
-      preventDeath: true
-      refillInventory: true
-      saturation: 20
-      quickloot: false
-    protection:
-      enabled: true
-      punish: false
-      spawn: 0
-    ready:
-      autoClass: Pyro   # default class when player enter to the lobby
-      block: 42         # default : iron block 
-      checkEachPlayer: false
-      checkEachTeam: true
-      enforceCountdown: false
-      minPlayers: 2
-      maxPlayers: 0
-      maxTeam: 0
-      neededRatio: 0.5
-    time:
-      startCountDown: 10
-      regionTimer: 10
-      teleportProtect: 3
-      resetDelay: -1
-      warmupCountDown: 0
-      pvp: 0
-    tp:             # teleport location when ... (old is last player's location)    
-      death: old
-      exit: old
-      lose: old
-      win: old
-    uses:
-      classSignsDisplay: false
-      deathMessages: true
-      evenTeams: false
-      ingameClassSwitch: false  # players can change class via "/pa arenaclass Pyro" for example
-      invisibilityfix: false
-      evilinvisibilityfix: false
-      playerclasses: false
-      overlapCheck: true
-      teamrewards: false
-      woolHead: false
-    flagColors:
-      red: WHITE
-      blue: BLACK
-    classitems:
-      Ranger: 261,262:64,298,299,300,301
-      Swordsman: 276,306,307,308,309
-      Tank: 272,310,311,312,313
-      Pyro: 259,46:3,298,299,300,301
-    teams:
-      red: RED
-      blue: BLUE
-    spawns:         # do not modify directly, use "/pa spawn" commands
-      bluespawn: labo,24,4,-13,-266.99993896484375,10.64997673034668
-      redspawn: labo,17,4,-13,-89.84992218017578,10.500003814697266
-      redlounge: labo,15,4,-13,272.699951171875,0.7499973177909851
-      bluelounge: labo,26,4,-13,90.74996185302734,4.049993515014648
-      spectator: labo,20,4,-7,180.2999725341797,26.549985885620117
-    arenaregion:    # do not modify directly, use "/pa region" commands
-      test: labo,16,1,-17,25,8,-9,cuboid,0,5054,BATTLE
\ No newline at end of file
+    - type: IRON_SWORD
+    - type: SPLASH_POTION
+      meta:
+        potion-type: minecraft:regeneration
+    - type: SPLASH_POTION
+      meta:
+        potion-type: minecraft:weakness
+    - type: BOW
+      meta:
+        enchants:
+          ARROW_INFINITE: 1
+    - type: ARROW
+    offhand:
+    - type: AIR
+      amount: 0
+    armor:
+    - type: IRON_BOOTS
+    - type: IRON_LEGGINGS
+    - type: IRON_CHESTPLATE
+teams:
+  #Team colors with format "team: DYE_COLOR"
+  #Use color among ORANGE, MAGENTA, LIGHT_BLUE, LIME, PINK, GRAY, LIGHT_GRAY, PURPLE, BLUE, GREEN, RED, CYAN, YELLOW, BLACK, WHITE
+  red: RED
+  blue: BLUE
+spawns:
+  #List of registered spawn. See "Creation" part of documentation for more information
+  lounge: world,863,68,-997,0,0
+  spectator: world,876,63,-997,90,0
+  exit: world,321,67,221,0,5
+  spawn1: world,873,58,-997,90,0
+  spawn2: world,863,58,-1007,0,0
+  spawn3: world,853,58,-997,-90,0
+  spawn4: world,863,58,-987,180,0
+```
\ No newline at end of file

From b7db2b9f65bccaa247e60f7791955f5f2425ed77 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 28 Jun 2019 00:49:56 +0200
Subject: [PATCH 031/115] v1.14.0 - rewrite updater

---
 src/config.yml                                |   5 +-
 src/net/slipcor/pvparena/PVPArena.java        |  20 +-
 src/net/slipcor/pvparena/core/Updater.java    | 477 ------------------
 .../pvparena/listeners/PlayerListener.java    |   7 +-
 .../pvparena/updater/AbstractUpdater.java     | 100 ++++
 .../pvparena/updater/ModulesUpdater.java      | 107 ++++
 .../pvparena/updater/PluginUpdater.java       |  70 +++
 .../pvparena/updater/UpdateChecker.java       |  35 ++
 .../slipcor/pvparena/updater/UpdateMode.java  |  19 +
 src/net/slipcor/pvparena/updater/ZipUtil.java |  45 ++
 10 files changed, 388 insertions(+), 497 deletions(-)
 delete mode 100644 src/net/slipcor/pvparena/core/Updater.java
 create mode 100644 src/net/slipcor/pvparena/updater/AbstractUpdater.java
 create mode 100644 src/net/slipcor/pvparena/updater/ModulesUpdater.java
 create mode 100644 src/net/slipcor/pvparena/updater/PluginUpdater.java
 create mode 100644 src/net/slipcor/pvparena/updater/UpdateChecker.java
 create mode 100644 src/net/slipcor/pvparena/updater/UpdateMode.java
 create mode 100644 src/net/slipcor/pvparena/updater/ZipUtil.java

diff --git a/src/config.yml b/src/config.yml
index ab8df2c28..0251e3e29 100644
--- a/src/config.yml
+++ b/src/config.yml
@@ -17,9 +17,8 @@ shortcut_shuffle: false
 allow_ungrouped: false
 consoleoffduty: false
 update:
-  mode: both
-  type: beta
-  modules: true
+  mode: announce
+  modules: announce
 materialprefixes:
 - minecraft
 - bukkit
diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java
index bf5b76003..cfed9075b 100644
--- a/src/net/slipcor/pvparena/PVPArena.java
+++ b/src/net/slipcor/pvparena/PVPArena.java
@@ -15,7 +15,7 @@
 import net.slipcor.pvparena.loadables.*;
 import net.slipcor.pvparena.managers.ArenaManager;
 import net.slipcor.pvparena.managers.StatisticsManager;
-import net.slipcor.pvparena.managers.TabManager;
+import net.slipcor.pvparena.updater.UpdateChecker;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.command.Command;
@@ -51,7 +51,7 @@ public class PVPArena extends JavaPlugin {
     private final List arenaCommands = new ArrayList<>();
     private final List globalCommands = new ArrayList<>();
 
-    private Updater updater;
+    private UpdateChecker updateChecker;
     private boolean shuttingDown;
 
     /**
@@ -89,8 +89,8 @@ public List getGlobalCommands() {
         return globalCommands;
     }
 
-    public Updater getUpdater() {
-        return updater;
+    public UpdateChecker getUpdateChecker() {
+        return updateChecker;
     }
 
     /**
@@ -436,13 +436,9 @@ public void onEnable() {
             saveConfig();
         }
 
-        if (!getConfig().contains("update.mode") && getConfig().contains("modulecheck")) {
-            getConfig().set("update.mode", getConfig().getString("update", "both"));
-            getConfig().set("update.type", getConfig().getString("updatetype", "beta"));
-            getConfig().set("update.modules", getConfig().getBoolean("modulecheck", true));
-
-            getConfig().set("modulecheck", null);
-            getConfig().set("updatetype", null);
+        if (getConfig().contains("update.type")) {
+            getConfig().set("update.modules", getConfig().getBoolean("update.modules", true) ? "download" : "announce");
+            getConfig().set("update.type", null);
 
             saveConfig();
         }
@@ -503,7 +499,7 @@ public void onEnable() {
             ArenaManager.readShortcuts(getConfig().getConfigurationSection("shortcuts"));
         }
 
-        updater = new Updater(this, getFile());
+        updateChecker = new UpdateChecker(this);
 
         if (ArenaManager.count() > 0) {
             if (PVPArena.instance.getConfig().getBoolean("tracker", true)) {
diff --git a/src/net/slipcor/pvparena/core/Updater.java b/src/net/slipcor/pvparena/core/Updater.java
deleted file mode 100644
index 9f1048824..000000000
--- a/src/net/slipcor/pvparena/core/Updater.java
+++ /dev/null
@@ -1,477 +0,0 @@
-package net.slipcor.pvparena.core;
-
-import net.slipcor.pvparena.PVPArena;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-import org.bukkit.plugin.Plugin;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-public class Updater extends Thread {
-    private final boolean files;
-
-    private final UpdateMode mode;
-    private final UpdateType type;
-
-    private final Plugin plugin;
-    private final File file;
-
-    private final int major;
-    private final int minor;
-
-    private final List instances = new ArrayList<>();
-
-    protected enum UpdateMode {
-        OFF, ANNOUNCE, DOWNLOAD, BOTH;
-
-        public static UpdateMode getBySetting(final String setting) {
-            final String lcSetting = setting.toLowerCase();
-            if (lcSetting.contains("ann")) {
-                return ANNOUNCE;
-            }
-            if (lcSetting.contains("down") || lcSetting.contains("load")) {
-                return DOWNLOAD;
-            }
-            if ("both".equals(lcSetting)) {
-                return BOTH;
-            }
-            return OFF;
-        }
-    }
-
-    protected enum UpdateType {
-        ALPHA, BETA, RELEASE;
-
-        public static UpdateType getBySetting(final String setting) {
-            if ("beta".equalsIgnoreCase(setting)) {
-                return BETA;
-            }
-            if ("alpha".equalsIgnoreCase(setting)) {
-                return ALPHA;
-            }
-            return RELEASE;
-        }
-    }
-
-    public Updater(final Plugin plugin, final File file) {
-        super();
-
-        String version = Bukkit.getServer().getBukkitVersion();
-
-        String[] chunks;
-        try {
-            chunks = version.split("-")[0].split("\\.");
-        } catch (Exception e) {
-            chunks = new String[]{"1","11"};
-        }
-        int a,b;
-        try {
-            a = Integer.parseInt(chunks[0]);
-        } catch (Exception e) {
-            a = 1;
-        }
-        major = a;
-        try {
-            b = Integer.parseInt(chunks[1]);
-        } catch (Exception e) {
-            b = 9;
-        }
-        minor = b;
-
-        this.plugin = plugin;
-        this.file = file;
-        this.files = plugin.getConfig().getBoolean("update.modules");
-
-        mode = UpdateMode.getBySetting(plugin.getConfig().getString("update.mode", "both"));
-
-        if (mode == UpdateMode.OFF) {
-            type = UpdateType.RELEASE;
-        } else {
-            instances.clear();
-            type = UpdateType.getBySetting(plugin.getConfig().getString("update.type", "beta"));
-            instances.add(new UpdateInstance("pvparena", false));
-            if (files) {
-                final File zipFolder = new File(plugin.getDataFolder(), "files");
-                zipFolder.mkdir();
-                if (type == UpdateType.RELEASE) {
-                    instances.add(new UpdateInstance("pafiles", true));
-                } else {
-                    instances.add(new UpdateInstance("pa_goals", true));
-                    instances.add(new UpdateInstance("pa_mods", true));
-                }
-            }
-            start();
-        }
-
-        if (plugin.getConfig().getBoolean("update.modules", true)) {
-            try {
-                final File destination = plugin.getDataFolder();
-                if (!destination.exists()) {
-                    destination.mkdirs();
-
-                }
-
-                final File lib = new File(destination, "install.yml");
-
-                plugin.getLogger().info("Downloading module update file...");
-                final URL url = new URL(
-                        "http://pa.slipcor.net/getYML.php?major="+major+"&minor="+minor);
-                final ReadableByteChannel rbc = Channels.newChannel(url.openStream());
-                final FileOutputStream output = new FileOutputStream(lib);
-                output.getChannel().transferFrom(rbc, 0, 1 << 24);
-                plugin.getLogger().info("Downloaded module update file");
-                output.close();
-            } catch (final Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    class UpdateInstance {
-
-
-        private byte updateDigit;
-        private String vOnline;
-        private String vThis;
-        private String pluginName;
-        private String url;
-        private final boolean zip;
-
-        private boolean msg;
-        private boolean outdated;
-
-        UpdateInstance(String checkName, boolean isZip) {
-            pluginName = checkName;
-            zip = isZip;
-        }
-
-        /**
-         * calculate the message variables based on the versions
-         */
-        private void calculateVersions() {
-            final String[] aOnline = vOnline.split("\\.");
-            final String[] aThis = vThis.split("\\.");
-            outdated = false;
-
-
-            for (int i = 0; i < aOnline.length && i < aThis.length; i++) {
-                try {
-                    final int iOnline = Integer.parseInt(aOnline[i]);
-                    final int iThis = Integer.parseInt(aThis[i]);
-                    if (iOnline == iThis) {
-                        msg = false;
-                        continue;
-                    }
-                    msg = true;
-                    outdated = iOnline > iThis;
-                    updateDigit = (byte) i;
-                    message(Bukkit.getConsoleSender(), this);
-                    return;
-                } catch (final Exception e) {
-                    calculateRadixString(aOnline[i], aThis[i], i);
-                    return;
-                }
-            }
-        }
-        /**
-         * calculate a version part based on letters
-         *
-         * @param sOnline the online letter(s)
-         * @param sThis   the local letter(s)
-         */
-        private void calculateRadixString(final String sOnline, final String sThis,
-                                          final int pos) {
-            try {
-                final int iOnline = Integer.parseInt(sOnline, 36);
-                final int iThis = Integer.parseInt(sThis, 36);
-                if (iOnline == iThis) {
-                    msg = false;
-                    return;
-                }
-                msg = true;
-                outdated = iOnline > iThis;
-                updateDigit = (byte) pos;
-                message(Bukkit.getConsoleSender(), this);
-            } catch (final Exception e) {
-                e.printStackTrace();
-            }
-        }
-
-        /**
-         * colorize a given string based on a char
-         *
-         * @param string the string to colorize
-         * @return a colorized string
-         */
-        private String colorize(final String string) {
-            final StringBuffer result;
-            if (updateDigit == 0) {
-                result = new StringBuffer(ChatColor.RED.toString());
-            } else if (updateDigit == 1) {
-                result = new StringBuffer(ChatColor.GOLD.toString());
-            } else if (updateDigit == 2) {
-                result = new StringBuffer(ChatColor.YELLOW.toString());
-            } else if (updateDigit == 3) {
-                result = new StringBuffer(ChatColor.BLUE.toString());
-            } else {
-                result = new StringBuffer(ChatColor.GREEN.toString());
-            }
-            result.append(string);
-            result.append(ChatColor.WHITE);
-            return result.toString();
-        }
-
-        public void runMe() {
-
-            try {
-
-                String version = "";
-
-                URL website = new URL("http://pa.slipcor.net/versioncheck.php?plugin="+pluginName+"&type="+type.toString().toLowerCase()+"&major="+major+"&minor="+minor);
-                URLConnection connection = website.openConnection();
-                BufferedReader in = new BufferedReader(
-                        new InputStreamReader(
-                                connection.getInputStream()));
-                String inputLine;
-
-                while ((inputLine = in.readLine()) != null) {
-                    version = inputLine;
-                    break;
-                }
-                in.close();
-                vOnline = version.replace("v", "");
-
-                url = "https://www.spigotmc.org/resources/pvp-arena.16584/";
-
-                website = new URL("http://pa.slipcor.net/versioncheck.php?plugin="+pluginName+"&link=true&type="+type.toString().toLowerCase()+"&major="+major+"&minor="+minor);
-                connection = website.openConnection();
-                in = new BufferedReader(
-                        new InputStreamReader(
-                                connection.getInputStream()));
-
-                while ((inputLine = in.readLine()) != null) {
-                    url = inputLine;
-                    break;
-                }
-                in.close();
-
-                vThis = plugin.getDescription().getVersion().replace("v", "");
-
-                calculateVersions();
-
-            } catch (final Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-
-    private void message(final CommandSender player, UpdateInstance instance) {
-        try {
-            if (!instance.msg) {
-                return;
-            }
-
-            if (instance.outdated) {
-                if (!(player instanceof Player) && mode != UpdateMode.ANNOUNCE) {
-                    // not only announce, download!
-                    final File updateFolder = Bukkit.getServer().getUpdateFolderFile();
-                    if (!updateFolder.exists()) {
-                        updateFolder.mkdirs();
-                    }
-                    final File pluginFile = new File(updateFolder, file.getName());
-                    if (pluginFile.exists() && !instance.zip) {
-                        pluginFile.delete();
-                    }
-
-                    final File zipFile = new File(updateFolder, plugin.getName() + "_files_"+instance.pluginName+".zip");
-                    if (zipFile.exists()) {
-                        zipFile.delete();
-                    }
-
-                    if (instance.zip) {
-                        downloadAndUnpack(instance.url, zipFile);
-                    } else {
-                        final URL url = new URL(instance.url);
-                        final ReadableByteChannel rbc = Channels.newChannel(url.openStream());
-                        final FileOutputStream output = new FileOutputStream(pluginFile);
-                        output.getChannel().transferFrom(rbc, 0, 1 << 24);
-                        output.close();
-                    }
-
-                }
-
-                if (mode != UpdateMode.DOWNLOAD || (!( player instanceof Player))) {
-
-                    if (instance.zip) {
-                        if (instances.size() > 2) {
-                            player.sendMessage(instance.pluginName + " " + instance.colorize('v' + instance.vThis)
-                                    + ", an outdated version! Latest: " + ChatColor.COLOR_CHAR + 'a' + 'v' + instance.vOnline);
-                        } else {
-                            player.sendMessage("PVP Arena Files " + instance.colorize('v' + instance.vThis)
-                                    + ", an outdated version! Latest: " + ChatColor.COLOR_CHAR + 'a' + 'v' + instance.vOnline);
-                        }
-                    } else {
-                        player.sendMessage("You are using " + instance.colorize('v' + instance.vThis)
-                                + ", an outdated version! Latest: " + ChatColor.COLOR_CHAR + 'a' + 'v' + instance.vOnline);
-                        if (files) {
-                            if (instances.size() > 2) {
-                                player.sendMessage("The results for the files are as follows:");
-                            }
-                        }
-                    }
-                }
-
-                if (mode == UpdateMode.ANNOUNCE) {
-                    player.sendMessage(instance.url);
-                } else {
-                    if (!instance.zip) {
-                        class RunLater implements Runnable {
-                            @Override
-                            public void run() {
-                                player.sendMessage("The plugin has been updated, please restart the server!");
-                            }
-                        }
-                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 60L);
-                    }
-                }
-            } else {
-                if (mode != UpdateMode.DOWNLOAD || (!( player instanceof Player))) {
-                    if (instance.zip) {
-                        if (instances.size() > 2) {
-                            player.sendMessage(instance.pluginName + " " + instance.colorize('v' + instance.vThis)
-                                    + ", an experimental version! Latest stable: " + ChatColor.COLOR_CHAR + 'a' + 'v'
-                                    + instance.vOnline);
-                        } else {
-                            player.sendMessage("PVP Arena Files " + instance.colorize('v' + instance.vThis)
-                                    + ", an experimental version! Latest stable: " + ChatColor.COLOR_CHAR + 'a' + 'v'
-                                    + instance.vOnline);
-                        }
-                    } else {
-                        player.sendMessage("You are using " + instance.colorize('v' + instance.vThis)
-                                + ", an experimental version! Latest stable: " + ChatColor.COLOR_CHAR + 'a' + 'v'
-                                + instance.vOnline);
-                        if (files) {
-                            if (instances.size() > 2) {
-                                player.sendMessage("The results for the files are as follows:");
-                            }
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * message a player if the version is different
-     *
-     * @param player the player to message
-     */
-    public void message(final CommandSender player) {
-        class DownloadLater implements Runnable {
-
-            @Override
-            public void run() {
-                for (final UpdateInstance instance : instances) {
-                    message(player, instance);
-                }
-            }
-        }
-        Bukkit.getScheduler().runTaskAsynchronously(plugin, new DownloadLater());
-    }
-
-    private void downloadAndUnpack(String zipURL, File zipFile) throws IOException {
-        final URL url2 = new URL(zipURL);
-        final ReadableByteChannel rbc2 = Channels.newChannel(url2.openStream());
-        final FileOutputStream output2 = new FileOutputStream(zipFile);
-        output2.getChannel().transferFrom(rbc2, 0, 1 << 24);
-        output2.close();
-        unzip(zipFile.getCanonicalPath());
-    }
-
-    @Override
-    public void run() {
-        if (mode == null || mode == UpdateMode.OFF) {
-            System.out.print(Language.parse(Language.MSG.LOG_UPDATE_DISABLED));
-            return;
-        }
-
-        System.out.print(Language.parse(Language.MSG.LOG_UPDATE_ENABLED));
-        for (UpdateInstance instance : instances) {
-            instance.runMe();
-        }
-    }
-
-    /**
-     * Part of Zip-File-Extractor, modified by Gravity for use with Updater.
-     *
-     * @param file the location of the file to extract.
-     */
-    private void unzip(final String file) {
-        try {
-            final File fSourceZip = new File(file);
-            final String zipPath = file.substring(0, file.length() - 4);
-
-            final ZipFile zipFile = new ZipFile(fSourceZip);
-
-            final Enumeration e = zipFile.entries();
-            while (e.hasMoreElements()) {
-                final ZipEntry entry = e.nextElement();
-                final File destinationFilePath = new File(zipPath, entry.getName());
-                destinationFilePath.getParentFile().mkdirs();
-                if (!entry.isDirectory()) {
-                    final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
-                    int b;
-                    final byte[] buffer = new byte[1024];
-                    final FileOutputStream fos = new FileOutputStream(destinationFilePath);
-                    final BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);
-                    while ((b = bis.read(buffer, 0, 1024)) != -1) {
-                        bos.write(buffer, 0, b);
-                    }
-                    bos.flush();
-                    bos.close();
-                    bis.close();
-                    final String name = destinationFilePath.getName();
-                    if (name.endsWith(".jar")) {
-                        destinationFilePath.renameTo(new File(plugin.getDataFolder().getParent(), plugin.getDataFolder() + File.separator + "files" + File.separator + name));
-                    }
-                }
-            }
-            zipFile.close();
-
-            // Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
-            for (final File dFile : new File(zipPath).listFiles()) {
-                if (dFile.isDirectory()) {
-                    for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
-                    {
-                        final File destFile = new File(
-                                plugin.getDataFolder().getCanonicalPath() +
-                                        File.separator + "files" +
-                                        File.separator + cFile.getName());
-
-                        destFile.delete();
-                        cFile.renameTo(destFile);
-                    }
-                }
-                dFile.delete();
-            }
-            new File(zipPath).delete();
-            fSourceZip.delete();
-        } catch (final IOException e) {
-            e.printStackTrace();
-        }
-        new File(file).delete();
-    }
-}
diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java
index 3ac38535a..3bab67edc 100644
--- a/src/net/slipcor/pvparena/listeners/PlayerListener.java
+++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java
@@ -749,12 +749,9 @@ public void onPlayerJoin(final PlayerJoinEvent event) {
             arena.playerLeave(player, CFG.TP_EXIT, true, true, false);
         }
 
-        if (!player.isOp()) {
-            return; // no OP => OUT
-        }
         DEBUG.i("OP joins the game", player);
-        if (PVPArena.instance.getUpdater() != null) {
-            PVPArena.instance.getUpdater().message(player);
+        if (player.isOp() && PVPArena.instance.getUpdateChecker() != null) {
+            PVPArena.instance.getUpdateChecker().displayMessage(player);
         }
     }
 
diff --git a/src/net/slipcor/pvparena/updater/AbstractUpdater.java b/src/net/slipcor/pvparena/updater/AbstractUpdater.java
new file mode 100644
index 000000000..3237dc070
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/AbstractUpdater.java
@@ -0,0 +1,100 @@
+package net.slipcor.pvparena.updater;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import net.slipcor.pvparena.PVPArena;
+import org.bukkit.plugin.Plugin;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import java.util.logging.Logger;
+
+public abstract class AbstractUpdater implements Runnable {
+    protected final Plugin plugin;
+    protected final UpdateMode updateMode;
+    protected List updateMsgList;
+    protected static final Logger LOG = PVPArena.instance.getLogger();
+
+    public AbstractUpdater(Plugin plugin, List updateMsgList, String configNode) {
+        this.plugin = plugin;
+        this.updateMode = UpdateMode.getBySetting(plugin.getConfig().getString(configNode, UpdateMode.ANNOUNCE.name()));
+        this.updateMsgList = updateMsgList;
+    }
+
+    public void run() {
+        try {
+            if(this.updateMode != UpdateMode.OFF) {
+                runUpdater();
+            }
+        } catch (IOException e) {
+            LOG.warning("Unable to connect to api.github.com");
+        }
+    }
+
+    protected abstract void runUpdater() throws IOException;
+
+    protected static String getOnlineVersionFromJson(JsonObject jsonObject) {
+        String tagName = jsonObject.get("tag_name").getAsString();
+        return tagName.replace("v", "");
+    }
+
+    protected static String getDownloadUrlFromJson(JsonObject jsonObject) {
+        JsonArray jsonArray = jsonObject.getAsJsonArray("assets");
+        JsonObject assetArray = jsonArray.get(0).getAsJsonObject();
+        return assetArray.get("browser_download_url").getAsString();
+    }
+
+    protected static String getFilenameFromJson(JsonObject jsonObject) {
+        JsonArray jsonArray = jsonObject.getAsJsonArray("assets");
+        JsonObject assetArray = jsonArray.get(0).getAsJsonObject();
+        return assetArray.get("name").getAsString();
+    }
+
+    protected static JsonObject getVersionJson(InputStream inputStream) throws IOException {
+        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
+        JsonElement jsonElement = new JsonParser().parse(in);
+        JsonObject jsonObject = jsonElement.getAsJsonObject();
+        in.close();
+        return jsonObject;
+    }
+
+    protected static String getAnnounceMessage(Object... args) {
+        return String.format("%s %s is now available ! Your version: %s", args);
+    }
+
+    protected static String getPluginSuccessMessage(String version) {
+        return String.format("PVP Arena has been updated to %s. Restart your server to apply update.", version);
+    }
+
+    protected static String getModulesSuccessMessage(String version) {
+        return String.format("PVP Arena Modules have been updated to %s. Run /pa update to apply new version", version);
+    }
+
+    protected static boolean isUpToDate(String currentVersion, String newVersion) {
+        String[] fullCurrentVerArr = currentVersion.split("-SNAPSHOT");
+        boolean isSnapshot = fullCurrentVerArr.length > 1;
+        String[] currentVerArr = fullCurrentVerArr[0].split("\\.");
+        String[] newVerArr = newVersion.split("\\.");
+        int currentVerVal = 0;
+        int newVerVal = 0;
+
+        final int versionLen = 3;
+        for(int i = 0; i < versionLen; i++) {
+            Long currentVerChunk = Long.valueOf(currentVerArr[i]);
+            Long newVerChunk = Long.valueOf(newVerArr[i]);
+            currentVerVal += currentVerChunk * Math.pow(10, versionLen - i);
+            newVerVal += newVerChunk * Math.pow(10, versionLen - i);
+        }
+
+        if(currentVerVal == newVerVal) {
+            //Release > snapshot if there are the same number
+            return !isSnapshot;
+        }
+        return currentVerVal > newVerVal;
+    }
+}
diff --git a/src/net/slipcor/pvparena/updater/ModulesUpdater.java b/src/net/slipcor/pvparena/updater/ModulesUpdater.java
new file mode 100644
index 000000000..49d133b2b
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/ModulesUpdater.java
@@ -0,0 +1,107 @@
+package net.slipcor.pvparena.updater;
+
+import com.google.gson.JsonObject;
+import org.bukkit.plugin.Plugin;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.util.List;
+
+public class ModulesUpdater extends AbstractUpdater {
+
+    private final static String API_URL = "https://api.github.com/repos/Eredrim/pvparena_modules/releases/latest";
+    private static final String CONFIG_NODE = "update.modules";
+
+    public ModulesUpdater(Plugin plugin, List msgList) {
+        super(plugin, msgList, CONFIG_NODE);
+    }
+
+    protected void runUpdater() throws IOException {
+        String currentVersion = this.getModulesVersion();
+        URL githubApi = new URL(API_URL);
+        URLConnection connection = githubApi.openConnection();
+        JsonObject versionJson = getVersionJson(connection.getInputStream());
+        String onlineVersion = getOnlineVersionFromJson(versionJson);
+
+        if(isUpToDate(currentVersion, onlineVersion)) {
+            LOG.info("PVP Arena modules are up to date");
+        } else {
+            String updateInfo = getAnnounceMessage("PVP Arena modules", onlineVersion, currentVersion);
+            LOG.info(updateInfo);
+            if(this.updateMode == UpdateMode.ANNOUNCE) {
+                this.updateMsgList.add(updateInfo);
+            } else if(this.updateMode == UpdateMode.DOWNLOAD ) {
+                String filename = getFilenameFromJson(versionJson);
+                LOG.info("Downloading modules update...");
+                try {
+                    this.downloadAndUnpackModules(getDownloadUrlFromJson(versionJson), filename);
+                    this.setNewLockVersion(onlineVersion);
+                    String updateSuccess = getModulesSuccessMessage(onlineVersion);
+                    LOG.info(updateSuccess);
+                    this.updateMsgList.add(updateSuccess);
+                } catch (IOException e) {
+                    LOG.warning("Error during modules update");
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private String getModulesVersion() {
+        File lockFile = new File(this.getFilesFolder(), "version.lock");
+        if(lockFile.exists()) {
+            try {
+                List lines = Files.readAllLines(lockFile.toPath(), Charset.defaultCharset());
+                return lines.get(0);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return "0.0.0";
+    }
+
+    private void setNewLockVersion(String version) {
+        File lockFile = new File(this.getFilesFolder(), "version.lock");
+        try {
+            BufferedWriter writer = new BufferedWriter(new FileWriter(lockFile));
+            writer.write(version);
+            writer.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void downloadAndUnpackModules(String downloadUrlStr, String filename) throws IOException {
+        URL downloadUrl = new URL(downloadUrlStr);
+        File zipFile = new File(this.plugin.getDataFolder(), filename);
+        if (zipFile.exists()) {
+            zipFile.delete();
+        }
+        ReadableByteChannel readableByteChannel = Channels.newChannel(downloadUrl.openStream());
+        FileOutputStream outputStream = new FileOutputStream(zipFile);
+        outputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
+        outputStream.close();
+        deleteDirectory(this.getFilesFolder());
+        ZipUtil.unzip(zipFile, this.plugin.getDataFolder());
+        zipFile.delete();
+    }
+
+    private File getFilesFolder() {
+        return new File(this.plugin.getDataFolder().getPath() + "/files");
+    }
+
+    private static void deleteDirectory(File directoryToBeDeleted) {
+        File[] allContents = directoryToBeDeleted.listFiles();
+        if (allContents != null) {
+            for (File file : allContents) {
+                deleteDirectory(file);
+            }
+        }
+        directoryToBeDeleted.delete();
+    }
+}
diff --git a/src/net/slipcor/pvparena/updater/PluginUpdater.java b/src/net/slipcor/pvparena/updater/PluginUpdater.java
new file mode 100644
index 000000000..06a826053
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/PluginUpdater.java
@@ -0,0 +1,70 @@
+package net.slipcor.pvparena.updater;
+
+import com.google.gson.JsonObject;
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
+import java.util.List;
+
+public class PluginUpdater extends AbstractUpdater {
+
+    private final static String API_URL = "https://api.github.com/repos/Eredrim/pvparena/releases/latest";
+    private static final String CONFIG_NODE = "update.mode";
+
+    public PluginUpdater(Plugin plugin, List msgList) {
+        super(plugin, msgList, CONFIG_NODE);
+    }
+
+    protected void runUpdater() throws IOException {
+        String currentVersion = plugin.getDescription().getVersion().replace("v", "");
+        URL githubApi = new URL(API_URL);
+        URLConnection connection = githubApi.openConnection();
+        JsonObject versionJson = getVersionJson(connection.getInputStream());
+        String onlineVersion = getOnlineVersionFromJson(versionJson);
+
+        if(isUpToDate(currentVersion, onlineVersion)) {
+            LOG.info("PVP Arena is up to date");
+        } else {
+            String updateInfo = getAnnounceMessage("PVP Arena", onlineVersion, currentVersion);
+            LOG.info(updateInfo);
+            if(this.updateMode == UpdateMode.ANNOUNCE) {
+                this.updateMsgList.add(updateInfo);
+            } else if(this.updateMode == UpdateMode.DOWNLOAD ) {
+                String filename = getFilenameFromJson(versionJson);
+                LOG.info("Downloading update...");
+                try {
+                    downloadPlugin(getDownloadUrlFromJson(versionJson), filename);
+                    String updateSuccess = getPluginSuccessMessage(onlineVersion);
+                    LOG.info(updateSuccess);
+                    this.updateMsgList.add(updateSuccess);
+                } catch (IOException e) {
+                    LOG.warning("Error during plugin update");
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private static void downloadPlugin(String downloadUrlStr, String filename) throws IOException {
+        URL downloadUrl = new URL(downloadUrlStr);
+        final File updateFolder = Bukkit.getServer().getUpdateFolderFile();
+        if (!updateFolder.exists()) {
+            updateFolder.mkdirs();
+        }
+        final File pluginFile = new File(updateFolder, filename);
+        if (pluginFile.exists()) {
+            pluginFile.delete();
+        }
+        ReadableByteChannel readableByteChannel = Channels.newChannel(downloadUrl.openStream());
+        FileOutputStream outputStream = new FileOutputStream(pluginFile);
+        outputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
+        outputStream.close();
+    }
+}
diff --git a/src/net/slipcor/pvparena/updater/UpdateChecker.java b/src/net/slipcor/pvparena/updater/UpdateChecker.java
new file mode 100644
index 000000000..69b4675ae
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/UpdateChecker.java
@@ -0,0 +1,35 @@
+package net.slipcor.pvparena.updater;
+
+import net.slipcor.pvparena.PVPArena;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class UpdateChecker {
+    private List updateMsgList;
+
+    public UpdateChecker(Plugin plugin) {
+        this.updateMsgList = new ArrayList<>();
+
+        PluginUpdater pluginUpdater = new PluginUpdater(plugin, this.updateMsgList);
+        ModulesUpdater modulesUpdater = new ModulesUpdater(plugin, this.updateMsgList);
+        new Thread(pluginUpdater).start();
+        new Thread(modulesUpdater).start();
+    }
+
+    public void displayMessage(final Player player) {
+        Bukkit.getScheduler().scheduleSyncDelayedTask(PVPArena.instance, new Runnable() {
+            @Override
+            public void run() {
+                for(String message : updateMsgList) {
+                    player.sendMessage(String.format("%s=- %s -=%s", ChatColor.GREEN, message, ChatColor.RESET));
+                }
+            }
+        }, 20L);
+
+    }
+}
diff --git a/src/net/slipcor/pvparena/updater/UpdateMode.java b/src/net/slipcor/pvparena/updater/UpdateMode.java
new file mode 100644
index 000000000..d0c0adc86
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/UpdateMode.java
@@ -0,0 +1,19 @@
+package net.slipcor.pvparena.updater;
+
+public enum UpdateMode {
+    OFF, ANNOUNCE, DOWNLOAD;
+
+    public static UpdateMode getBySetting(final String setting) {
+        if (ANNOUNCE.name().equalsIgnoreCase(setting)) {
+            return ANNOUNCE;
+        }
+        if (DOWNLOAD.name().equalsIgnoreCase(setting)) {
+            return DOWNLOAD;
+        }
+        //Retro-compatibility
+        if ("both".equalsIgnoreCase(setting)) {
+            return DOWNLOAD;
+        }
+        return OFF;
+    }
+}
\ No newline at end of file
diff --git a/src/net/slipcor/pvparena/updater/ZipUtil.java b/src/net/slipcor/pvparena/updater/ZipUtil.java
new file mode 100644
index 000000000..269e844bd
--- /dev/null
+++ b/src/net/slipcor/pvparena/updater/ZipUtil.java
@@ -0,0 +1,45 @@
+package net.slipcor.pvparena.updater;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class ZipUtil {
+    public static void unzip(File zipFile, File destDir) throws IOException {
+        byte[] buffer = new byte[1024];
+        ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
+        ZipEntry zipEntry = zis.getNextEntry();
+        while (zipEntry != null) {
+            File newFile = newFile(destDir, zipEntry);
+            if(zipEntry.getName().endsWith("/")) {
+                newFile.mkdirs();
+            } else {
+                FileOutputStream fos = new FileOutputStream(newFile);
+                int len;
+                while ((len = zis.read(buffer)) > 0) {
+                    fos.write(buffer, 0, len);
+                }
+                fos.close();
+            }
+            zipEntry = zis.getNextEntry();
+        }
+        zis.closeEntry();
+        zis.close();
+    }
+
+    private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
+        File destFile = new File(destinationDir, zipEntry.getName());
+
+        String destDirPath = destinationDir.getCanonicalPath();
+        String destFilePath = destFile.getCanonicalPath();
+
+        if (!destFilePath.startsWith(destDirPath + File.separator)) {
+            throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
+        }
+
+        return destFile;
+    }
+}

From df865fdcbdc0087b32df318151d54cdd4e01e878 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 4 Jul 2019 22:25:56 +0200
Subject: [PATCH 032/115] v1.14.0 - clean update, install and uninstall
 commands

---
 .../pvparena/commands/PAA_Install.java        | 170 ++++--------------
 .../pvparena/commands/PAA_Uninstall.java      |  85 +--------
 .../slipcor/pvparena/commands/PAA_Update.java |  30 +---
 3 files changed, 40 insertions(+), 245 deletions(-)

diff --git a/src/net/slipcor/pvparena/commands/PAA_Install.java b/src/net/slipcor/pvparena/commands/PAA_Install.java
index 3258ad348..3b9138fd0 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Install.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Install.java
@@ -6,12 +6,10 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModule;
 import org.bukkit.Bukkit;
 import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.configuration.file.YamlConfiguration;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -39,6 +37,8 @@ public PAA_Install() {
         super(new String[]{"pvparena.cmds.install"});
     }
 
+    private static final File FILES_DIR = new File(PVPArena.instance.getDataFolder(),"/files/");
+
     @Override
     public void commit(final CommandSender sender, final String[] args) {
         if (!hasPerms(sender)) {
@@ -52,68 +52,22 @@ public void commit(final CommandSender sender, final String[] args) {
         // pa install
         // pa install ctf
 
-        if (!PVPArena.instance.getConfig().getBoolean("update.modules", true)) {
-            Arena.pmsg(sender, ChatColor.DARK_RED+Language.parse(MSG.ERROR_MODULE_UPDATE));
-            return;
-        }
-
-        final YamlConfiguration config = new YamlConfiguration();
-        try {
-            config.load(PVPArena.instance.getDataFolder().getPath()
-                    + "/install.yml");
-        } catch (final Exception e) {
-            e.printStackTrace();
-            return;
-        }
-
         if (args.length == 0) {
-            listVersions(sender, config, null);
+            listInstalled(sender);
             return;
         }
 
-        if (config.get(args[0]) != null) {
-            listVersions(sender, config, args[0]);
-            return;
-        }
-
-        Set list = (config == null || config.getConfigurationSection("goals") == null)?new HashSet():config.getConfigurationSection("goals").getKeys(false);
-        if (list.contains(args[0].toLowerCase())) {
-            for (final String key : list) {
-                if (key.equalsIgnoreCase(args[0])) {
-                    if (download("pa_g_" + key + ".jar")) {
-                        PVPArena.instance.getAgm().reload();
-                        Arena.pmsg(sender,
-                                Language.parse(MSG.INSTALL_DONE, key));
-                        return;
-                    }
-                    Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, key));
-                    return;
-                }
-            }
-        } else if (list.size() == 0) {
-            if (download("pa_g_" + args[0].toLowerCase() + ".jar")) {
-                PVPArena.instance.getAgm().reload();
+        Set modList = getModList();
+        if (modList.contains(args[0].toLowerCase())) {
+            String modName = args[0].toLowerCase();
+            if (download("pa_m_" + modName + ".jar")) {
+                PVPArena.instance.getAmm().reload();
                 Arena.pmsg(sender,
-                        Language.parse(MSG.INSTALL_DONE, args[0].toLowerCase()));
+                        Language.parse(MSG.INSTALL_DONE, modName));
                 return;
             }
-            Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, args[0].toLowerCase()));
-        }
-
-        list = (config == null || config.getConfigurationSection("mods") == null)?new HashSet():config.getConfigurationSection("mods").getKeys(false);
-        if (list.contains(args[0].toLowerCase())) {
-            for (final String key : list) {
-                if (key.equalsIgnoreCase(args[0])) {
-                    if (download("pa_m_" + key + ".jar")) {
-                        PVPArena.instance.getAmm().reload();
-                        Arena.pmsg(sender,
-                                Language.parse(MSG.INSTALL_DONE, key));
-                        return;
-                    }
-                    Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, key));
-                }
-            }
-        } else if (list.size() == 0) {
+            Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, modName));
+        } else if (modList.size() == 0) {
             if (download("pa_m_" + args[0].toLowerCase() + ".jar")) {
                 PVPArena.instance.getAmm().reload();
                 Arena.pmsg(sender,
@@ -124,62 +78,38 @@ public void commit(final CommandSender sender, final String[] args) {
         }
     }
 
-    private void listVersions(final CommandSender sender, final YamlConfiguration cfg,
-                              final String sub) {
+    public static Set listInstalled(final CommandSender sender) {
         Arena.pmsg(sender, "--- PVP Arena Version Update information ---");
-        Arena.pmsg(sender, "[" + ChatColor.COLOR_CHAR + "7uninstalled" + ChatColor.COLOR_CHAR + "r | " + ChatColor.COLOR_CHAR + "einstalled" + ChatColor.COLOR_CHAR + "r]");
-        Arena.pmsg(sender, "[" + ChatColor.COLOR_CHAR + "coutdated" + ChatColor.COLOR_CHAR + "r | " + ChatColor.COLOR_CHAR + "alatest version" + ChatColor.COLOR_CHAR + "r]");
-        if (sub == null || "goals".equalsIgnoreCase(sub)) {
-            Arena.pmsg(sender, ChatColor.COLOR_CHAR + "c--- Arena Goals ----> /goals");
-            if (cfg.contains("goals")) {
-                final Set entries = cfg.getConfigurationSection("goals").getKeys(
-                        false);
-                for (final String key : entries) {
-                    final String latest = cfg.getString("goals." + key);
-                    final ArenaGoal goal = PVPArena.instance.getAgm().getGoalByName(key);
-                    final boolean installed = goal != null;
-                    String version = null;
-                    if (installed) {
-                        version = goal.version();
-                    }
-                    Arena.pmsg(sender, (installed ? ChatColor.COLOR_CHAR + "e" : ChatColor.COLOR_CHAR + "7")
-                            + key
-                            + ChatColor.COLOR_CHAR + "r - "
-                            + (installed ? latest.equals(version) ? ChatColor.COLOR_CHAR + "a" : ChatColor.COLOR_CHAR + "c"
-                            : "") + version + ChatColor.COLOR_CHAR + "f(" + latest + ')');
-                }
-            }
+        Arena.pmsg(sender, "[" + ChatColor.GRAY + "uninstalled" + ChatColor.RESET + " | " + ChatColor.YELLOW + "installed" + ChatColor.RESET + "]");
+        Arena.pmsg(sender, ChatColor.GREEN + "--- Installed Arena Mods ---->");
+        Set modList = new HashSet<>();
+
+        for (final String modName : getModList()) {
+            final ArenaModule mod = PVPArena.instance.getAmm().getModByName(modName);
+            Arena.pmsg(sender, (mod != null ? ChatColor.YELLOW : ChatColor.GRAY) + modName + ChatColor.RESET);
         }
-        if (sub == null || "mods".equalsIgnoreCase(sub)) {
-            Arena.pmsg(sender, ChatColor.COLOR_CHAR + "a--- Arena Mods ----> /mods");
-            if (cfg.contains("mods")) {
-                final Set entries = cfg.getConfigurationSection("mods").getKeys(
-                        false);
-                for (final String key : entries) {
-                    final String latest = cfg.getString("mods." + key);
-                    final ArenaModule mod = PVPArena.instance.getAmm().getModByName(key);
-                    final boolean installed = mod != null;
-                    String version = null;
-                    if (installed) {
-                        version = mod.version();
-                    }
-                    Arena.pmsg(sender, (installed ? ChatColor.COLOR_CHAR + "e" : ChatColor.COLOR_CHAR + "7")
-                            + key
-                            + ChatColor.COLOR_CHAR + "r - "
-                            + (installed ? latest.equals(version) ? ChatColor.COLOR_CHAR + "a" : ChatColor.COLOR_CHAR + "c"
-                            : "") + version + ChatColor.COLOR_CHAR + "f(" + latest + ')');
-                }
+        return modList;
+    }
+
+    private static Set getModList() {
+        Set modList = new HashSet<>();
+        for (final File file : FILES_DIR.listFiles()) {
+            final String fileName = file.getName();
+            if (fileName.startsWith("pa_m_") && fileName.endsWith(".jar")) {
+                String modName = fileName.substring(5, fileName.length() - 4);
+                modList.add(modName);
             }
         }
+        return modList;
     }
+
     private boolean download(final String file) {
         return download(file, false);
     }
 
     private boolean download(final String file, final boolean silent) {
 
-        final File source = new File(PVPArena.instance.getDataFolder().getPath()
-                + "/files/" + file);
+        final File source = new File(FILES_DIR, file);
 
         if (!source.exists()) {
             if (!silent) {
@@ -192,17 +122,8 @@ private boolean download(final String file, final boolean silent) {
             return false;
         }
 
-        String folder = null;
-        if (file.startsWith("pa_g")) {
-            folder = "/goals/";
-        } else if (file.startsWith("pa_m")) {
-            folder = "/mods/";
-        }
-        if (folder == null) {
-            PVPArena.instance.getLogger()
-                    .severe("unable to save file: " + file);
-            return false;
-        }
+        String folder = "/mods/";
+
         try {
             final File destination = new File(PVPArena.instance.getDataFolder()
                     .getPath() + folder + '/' + file);
@@ -251,28 +172,9 @@ public List getShort() {
     @Override
     public CommandTree getSubs(final Arena nothing) {
         final CommandTree result = new CommandTree<>(null);
-        result.define(new String[]{"mods"});
-        result.define(new String[]{"goals"});
-        for (final String string : PVPArena.instance.getAgm().getAllGoalNames()) {
-            result.define(new String[]{string});
-        }
-        final YamlConfiguration config = new YamlConfiguration();
-        try {
-            config.load(PVPArena.instance.getDataFolder().getPath()
-                    + "/install.yml");
-        } catch (final Exception e) {
-            e.printStackTrace();
-            return result;
-        }
-
-        Set list = config.getConfigurationSection("goals").getKeys(false);
-
-        for (final String key : list) {
-            result.define(new String[]{key});
-        }
 
-        list = config.getConfigurationSection("mods").getKeys(false);
-        for (final String key : list) {
+        Set modList = getModList();
+        for (final String key : modList) {
             result.define(new String[]{key});
         }
         return result;
diff --git a/src/net/slipcor/pvparena/commands/PAA_Uninstall.java b/src/net/slipcor/pvparena/commands/PAA_Uninstall.java
index d437cc362..63389963f 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Uninstall.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Uninstall.java
@@ -6,9 +6,7 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModule;
-import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
 import org.bukkit.configuration.file.FileConfiguration;
 import org.bukkit.configuration.file.YamlConfiguration;
@@ -17,7 +15,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
 
 /**
  * 
PVP Arena UNINSTALL Command class
@@ -45,11 +42,6 @@ public void commit(final CommandSender sender, final String[] args) { return; } - if (!PVPArena.instance.getConfig().getBoolean("update.modules", true)) { - Arena.pmsg(sender, ChatColor.DARK_RED+Language.parse(MSG.ERROR_MODULE_UPDATE)); - return; - } - // pa install // pa install ctf @@ -59,36 +51,12 @@ public void commit(final CommandSender sender, final String[] args) { } catch (final Exception e) { } - if (args.length == 0) { - listVersions(sender, config, null); - return; - } - - if (config.get(args[0]) != null) { - listVersions(sender, config, args[1]); + if (args.length == 0 || config.get(args[0]) != null) { + PAA_Install.listInstalled(sender); return; } final String name = args[0].toLowerCase(); - final ArenaGoal goal = PVPArena.instance.getAgm().getGoalByName(name); - if (goal != null) { - if (remove("pa_g_" + goal.getName().toLowerCase() + ".jar")) { - PVPArena.instance.getAgm().reload(); - Arena.pmsg(sender, Language.parse(MSG.UNINSTALL_DONE, goal.getName())); - return; - } - Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL, goal.getName())); - FileConfiguration cfg = PVPArena.instance.getConfig(); - List toDelete = cfg.getStringList("todelete"); - if (toDelete == null){ - toDelete = new ArrayList<>(); - } - toDelete.add("pa_g_" + goal.getName().toLowerCase() + ".jar"); - cfg.set("todelete", toDelete); - PVPArena.instance.saveConfig(); - Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL2)); - return; - } final ArenaModule mod = PVPArena.instance.getAmm().getModByName(name); if (mod != null) { if (remove("pa_m_" + mod.getName().toLowerCase() + ".jar")) { @@ -109,52 +77,6 @@ public void commit(final CommandSender sender, final String[] args) { } } - private void listVersions(final CommandSender sender, final YamlConfiguration cfg, - final String sub) { - Arena.pmsg(sender, "--- PVP Arena Version Update information ---"); - Arena.pmsg(sender, "[" + ChatColor.COLOR_CHAR + "7uninstalled" + ChatColor.COLOR_CHAR + "r | " + ChatColor.COLOR_CHAR + "einstalled" + ChatColor.COLOR_CHAR + "r]"); - Arena.pmsg(sender, "[" + ChatColor.COLOR_CHAR + "coutdated" + ChatColor.COLOR_CHAR + "r | " + ChatColor.COLOR_CHAR + "alatest version" + ChatColor.COLOR_CHAR + "r]"); - if (sub == null || "arenas".equalsIgnoreCase(sub)) { - Arena.pmsg(sender, ChatColor.COLOR_CHAR + "c--- Arena Goals ----> /goals"); - final Set entries = cfg.getConfigurationSection("goals").getKeys( - false); - for (final String key : entries) { - final String value = cfg.getString("goals." + key); - final ArenaGoal goal = PVPArena.instance.getAgm().getGoalByName(key); - final boolean installed = goal != null; - String version = null; - if (installed) { - version = goal.version(); - } - Arena.pmsg(sender, (installed ? ChatColor.COLOR_CHAR + "e" : ChatColor.COLOR_CHAR + "7") - + key - + ChatColor.COLOR_CHAR + "r - " - + (installed ? value.equals(version) ? ChatColor.COLOR_CHAR + "a" : ChatColor.COLOR_CHAR + "c" - : "") + value); - } - } - if (sub == null || "mods".equalsIgnoreCase(sub)) { - Arena.pmsg(sender, ChatColor.COLOR_CHAR + "a--- Arena Mods ----> /mods"); - final Set entries = cfg.getConfigurationSection("mods").getKeys( - false); - for (final String key : entries) { - final String value = cfg.getString("mods." + key); - final ArenaModule mod = PVPArena.instance.getAmm().getModByName(key); - final boolean installed = mod != null; - String version = null; - if (installed) { - version = mod.version(); - } - Arena.pmsg(sender, (installed ? ChatColor.COLOR_CHAR + "e" : ChatColor.COLOR_CHAR + "7") - + key - + ChatColor.COLOR_CHAR + "r - " - + (installed ? value.equals(version) ? ChatColor.COLOR_CHAR + "a" : ChatColor.COLOR_CHAR + "c" - : "") + value); - } - - } - } - @Override public String getName() { return getClass().getName(); @@ -208,9 +130,6 @@ public List getShort() { @Override public CommandTree getSubs(final Arena nothing) { final CommandTree result = new CommandTree<>(null); - for (final String string : PVPArena.instance.getAgm().getAllGoalNames()) { - result.define(new String[]{string}); - } for (final ArenaModule mod : PVPArena.instance.getAmm().getAllMods()) { result.define(new String[]{mod.getName()}); } diff --git a/src/net/slipcor/pvparena/commands/PAA_Update.java b/src/net/slipcor/pvparena/commands/PAA_Update.java index 89aecadf1..690a3ffdc 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Update.java +++ b/src/net/slipcor/pvparena/commands/PAA_Update.java @@ -4,10 +4,8 @@ import net.slipcor.pvparena.arena.Arena; import net.slipcor.pvparena.core.Help; import net.slipcor.pvparena.core.Help.HELP; -import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.loadables.ArenaModule; import net.slipcor.pvparena.ncloader.NCBLoadable; -import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import java.io.File; @@ -33,23 +31,11 @@ public PAA_Update() { @Override public void commit(final CommandSender sender, final String[] args) { - if (!PVPArena.instance.getConfig().getBoolean("update.modules", true)) { - Arena.pmsg(sender, ChatColor.DARK_RED+ Language.parse(Language.MSG.ERROR_MODULE_UPDATE)); - return; - } if (!hasPerms(sender)) { return; } - final Set modules = new HashSet<>(); - - if (args.length < 1 || "mods".equals(args[0])) { - modules.addAll(PVPArena.instance.getAmm().getAllMods()); - } else if (args.length < 1 || "goals".equals(args[0])) { - modules.addAll(PVPArena.instance.getAgm().getAllGoals()); - } else if (args.length < 1 || "regionshapes".equals(args[0])) { - modules.addAll(PVPArena.instance.getArsm().getRegions()); - } + final Set modules = new HashSet(PVPArena.instance.getAmm().getAllMods()); if (!modules.isEmpty()) { for (final NCBLoadable mod : modules) { @@ -59,10 +45,9 @@ public void commit(final CommandSender sender, final String[] args) { final File destination = new File(PVPArena.instance.getDataFolder().getPath() + "/files/"); - final File destFileG = new File(destination, "pa_g_" + mod.getName().toLowerCase() + ".jar"); final File destFileM = new File(destination, "pa_m_" + mod.getName().toLowerCase() + ".jar"); - if (!destFileG.exists() && !destFileM.exists()) { + if (!destFileM.exists()) { continue; } @@ -77,13 +62,7 @@ public void commit(final CommandSender sender, final String[] args) { } install.commit(sender, new String[]{mod.getName()}); } - return; } - - final PAA_Uninstall uninstall = new PAA_Uninstall(); - uninstall.commit(sender, args); - final PAA_Install install = new PAA_Install(); - install.commit(sender, args); } @@ -110,11 +89,6 @@ public List getShort() { @Override public CommandTree getSubs(final Arena nothing) { final CommandTree result = new CommandTree<>(null); - result.define(new String[]{"mods"}); - result.define(new String[]{"goals"}); - for (final String string : PVPArena.instance.getAgm().getAllGoalNames()) { - result.define(new String[]{string}); - } for (final ArenaModule mod : PVPArena.instance.getAmm().getAllMods()) { result.define(new String[]{mod.getName()}); } From 5b4c898a0ae1b7072b96fece027497a6debe7886 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Sat, 6 Jul 2019 18:20:35 +0200 Subject: [PATCH 033/115] v1.14.0 - add javadoc and language support to updater --- src/config.yml | 2 +- src/net/slipcor/pvparena/PVPArena.java | 4 +- .../pvparena/commands/PAA_Install.java | 17 ++--- src/net/slipcor/pvparena/core/Language.java | 4 ++ .../pvparena/updater/AbstractUpdater.java | 67 ++++++++++++++++--- .../pvparena/updater/ModulesUpdater.java | 49 ++++++++++---- .../pvparena/updater/PluginUpdater.java | 27 +++++++- .../pvparena/updater/UpdateChecker.java | 14 +++- src/net/slipcor/pvparena/updater/ZipUtil.java | 16 +++++ 9 files changed, 159 insertions(+), 41 deletions(-) diff --git a/src/config.yml b/src/config.yml index 0251e3e29..7ad58e3e9 100644 --- a/src/config.yml +++ b/src/config.yml @@ -17,7 +17,7 @@ shortcut_shuffle: false allow_ungrouped: false consoleoffduty: false update: - mode: announce + plugin: announce modules: announce materialprefixes: - minecraft diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index cfed9075b..54ba3becf 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -436,9 +436,11 @@ public void onEnable() { saveConfig(); } - if (getConfig().contains("update.type")) { + if (getConfig().contains("update.type") || getConfig().contains("update.mode")) { + getConfig().set("update.plugin", getConfig().getString("update.mode", "announce")); getConfig().set("update.modules", getConfig().getBoolean("update.modules", true) ? "download" : "announce"); getConfig().set("update.type", null); + getConfig().set("update.mode", null); saveConfig(); } diff --git a/src/net/slipcor/pvparena/commands/PAA_Install.java b/src/net/slipcor/pvparena/commands/PAA_Install.java index 3b9138fd0..046539135 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Install.java +++ b/src/net/slipcor/pvparena/commands/PAA_Install.java @@ -58,23 +58,14 @@ public void commit(final CommandSender sender, final String[] args) { } Set modList = getModList(); - if (modList.contains(args[0].toLowerCase())) { + if (modList.size() == 0 || modList.contains(args[0].toLowerCase())) { String modName = args[0].toLowerCase(); if (download("pa_m_" + modName + ".jar")) { PVPArena.instance.getAmm().reload(); - Arena.pmsg(sender, - Language.parse(MSG.INSTALL_DONE, modName)); - return; + Arena.pmsg(sender, Language.parse(MSG.INSTALL_DONE, modName)); + } else { + Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, modName)); } - Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, modName)); - } else if (modList.size() == 0) { - if (download("pa_m_" + args[0].toLowerCase() + ".jar")) { - PVPArena.instance.getAmm().reload(); - Arena.pmsg(sender, - Language.parse(MSG.INSTALL_DONE, args[0].toLowerCase())); - return; - } - Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, args[0].toLowerCase())); } } diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index a00345d1a..432c4aac0 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -463,6 +463,10 @@ public enum MSG { TOGGLEMOD_NOTICE("nulang.togglemod.notice", "&cYou activated a module that requires a BATTLE region! Type: &r/pvparena [arena] !rt [region] BATTLE"), UNINSTALL_DONE("nulang.uninstall.done", "Uninstalled: &a%1%&r"), + UPDATER_PLUGIN("updater.plugin", "PVP Arena"), + UPDATER_MODULES("updater.modules", "PVP Arena modules pack"), + UPDATER_ANNOUNCE("updater.announce", "%1% %2% is now available ! Your version: %3%"), + UPDATER_SUCCESS("updater.success", "%1% has been updated to %2%. Restart your server to apply update."), WHITELIST_ADDED("nulang.whitelist.added", "Added &a%1%&r to &e%2%&r whitelist!"), WHITELIST_ALLCLEARED("nulang.whitelist.allcleared", "All whitelists cleared!"), diff --git a/src/net/slipcor/pvparena/updater/AbstractUpdater.java b/src/net/slipcor/pvparena/updater/AbstractUpdater.java index 3237dc070..cd65e59d3 100644 --- a/src/net/slipcor/pvparena/updater/AbstractUpdater.java +++ b/src/net/slipcor/pvparena/updater/AbstractUpdater.java @@ -5,6 +5,8 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.core.Language; +import net.slipcor.pvparena.core.Language.MSG; import org.bukkit.plugin.Plugin; import java.io.BufferedReader; @@ -14,18 +16,30 @@ import java.util.List; import java.util.logging.Logger; +/** + * Abstract class with shared methods fo updaters + */ public abstract class AbstractUpdater implements Runnable { protected final Plugin plugin; protected final UpdateMode updateMode; protected List updateMsgList; protected static final Logger LOG = PVPArena.instance.getLogger(); + /** + * Constructs a AbstractUpdater instance + * @param plugin PVP Arena instance + * @param updateMsgList Reference to UpdateChecker message list + * @param configNode YML config node to get update setting + */ public AbstractUpdater(Plugin plugin, List updateMsgList, String configNode) { this.plugin = plugin; this.updateMode = UpdateMode.getBySetting(plugin.getConfig().getString(configNode, UpdateMode.ANNOUNCE.name())); this.updateMsgList = updateMsgList; } + /** + * Runs an updater if it's not disabled + */ public void run() { try { if(this.updateMode != UpdateMode.OFF) { @@ -36,25 +50,50 @@ public void run() { } } + /** + * Runs an updater implementation + * @throws IOException Exception if api.github.com is unreachable + */ protected abstract void runUpdater() throws IOException; + /** + * Returns release version from API json + * @param jsonObject API json + * @return version as string + */ protected static String getOnlineVersionFromJson(JsonObject jsonObject) { String tagName = jsonObject.get("tag_name").getAsString(); return tagName.replace("v", ""); } + /** + * Returns release download URL from API json + * @param jsonObject API json + * @return download URL as string + */ protected static String getDownloadUrlFromJson(JsonObject jsonObject) { JsonArray jsonArray = jsonObject.getAsJsonArray("assets"); JsonObject assetArray = jsonArray.get(0).getAsJsonObject(); return assetArray.get("browser_download_url").getAsString(); } + /** + * Returns release filename from API json + * @param jsonObject API json + * @return filename as string + */ protected static String getFilenameFromJson(JsonObject jsonObject) { JsonArray jsonArray = jsonObject.getAsJsonArray("assets"); JsonObject assetArray = jsonArray.get(0).getAsJsonObject(); return assetArray.get("name").getAsString(); } + /** + * Returns a JsonObject view of Api result stream + * @param inputStream InputStream returned by Api connection + * @return JsonObject + * @throws IOException Exception on json parsing + */ protected static JsonObject getVersionJson(InputStream inputStream) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); JsonElement jsonElement = new JsonParser().parse(in); @@ -63,18 +102,30 @@ protected static JsonObject getVersionJson(InputStream inputStream) throws IOExc return jsonObject; } - protected static String getAnnounceMessage(Object... args) { - return String.format("%s %s is now available ! Your version: %s", args); + /** + * Returns announce message of new available update + * @param args Args for stringFormatter + * @return Announce message + */ + protected static String getAnnounceMessage(String... args) { + return Language.parse(MSG.UPDATER_ANNOUNCE, args); } - protected static String getPluginSuccessMessage(String version) { - return String.format("PVP Arena has been updated to %s. Restart your server to apply update.", version); - } - - protected static String getModulesSuccessMessage(String version) { - return String.format("PVP Arena Modules have been updated to %s. Run /pa update to apply new version", version); + /** + * Returns update success message + * @param args Args for stringFormatter + * @return success message + */ + protected static String getSuccessMessage(String... args) { + return Language.parse(MSG.UPDATER_SUCCESS, args); } + /** + * Checks if current version is up to date + * @param currentVersion version currently installed as x.x.x format + * @param newVersion latest version available as x.x.x format + * @return true if current version is up to date, false otherwise + */ protected static boolean isUpToDate(String currentVersion, String newVersion) { String[] fullCurrentVerArr = currentVersion.split("-SNAPSHOT"); boolean isSnapshot = fullCurrentVerArr.length > 1; diff --git a/src/net/slipcor/pvparena/updater/ModulesUpdater.java b/src/net/slipcor/pvparena/updater/ModulesUpdater.java index 49d133b2b..101322b20 100644 --- a/src/net/slipcor/pvparena/updater/ModulesUpdater.java +++ b/src/net/slipcor/pvparena/updater/ModulesUpdater.java @@ -1,6 +1,7 @@ package net.slipcor.pvparena.updater; import com.google.gson.JsonObject; +import net.slipcor.pvparena.core.Language; import org.bukkit.plugin.Plugin; import java.io.*; @@ -12,15 +13,29 @@ import java.nio.file.Files; import java.util.List; +import static net.slipcor.pvparena.core.Language.*; + +/** + * Manage modules versions and updates + */ public class ModulesUpdater extends AbstractUpdater { private final static String API_URL = "https://api.github.com/repos/Eredrim/pvparena_modules/releases/latest"; private static final String CONFIG_NODE = "update.modules"; + /** + * Construct a modules updater + * @param plugin PVP Arena instance + * @param msgList Reference to UpdateChecker message list + */ public ModulesUpdater(Plugin plugin, List msgList) { super(plugin, msgList, CONFIG_NODE); } + /** + * Run modules updaters : checks version and downloads update according to config + * @throws IOException Exception if can't connect to github API + */ protected void runUpdater() throws IOException { String currentVersion = this.getModulesVersion(); URL githubApi = new URL(API_URL); @@ -31,7 +46,7 @@ protected void runUpdater() throws IOException { if(isUpToDate(currentVersion, onlineVersion)) { LOG.info("PVP Arena modules are up to date"); } else { - String updateInfo = getAnnounceMessage("PVP Arena modules", onlineVersion, currentVersion); + String updateInfo = getAnnounceMessage(MSG.UPDATER_MODULES.toString(), onlineVersion, currentVersion); LOG.info(updateInfo); if(this.updateMode == UpdateMode.ANNOUNCE) { this.updateMsgList.add(updateInfo); @@ -40,8 +55,7 @@ protected void runUpdater() throws IOException { LOG.info("Downloading modules update..."); try { this.downloadAndUnpackModules(getDownloadUrlFromJson(versionJson), filename); - this.setNewLockVersion(onlineVersion); - String updateSuccess = getModulesSuccessMessage(onlineVersion); + String updateSuccess = getSuccessMessage(MSG.UPDATER_MODULES.toString(), onlineVersion); LOG.info(updateSuccess); this.updateMsgList.add(updateSuccess); } catch (IOException e) { @@ -52,6 +66,10 @@ protected void runUpdater() throws IOException { } } + /** + * Get current modules version based on version.lock + * @return version string (x.x.x format) + */ private String getModulesVersion() { File lockFile = new File(this.getFilesFolder(), "version.lock"); if(lockFile.exists()) { @@ -65,17 +83,12 @@ private String getModulesVersion() { return "0.0.0"; } - private void setNewLockVersion(String version) { - File lockFile = new File(this.getFilesFolder(), "version.lock"); - try { - BufferedWriter writer = new BufferedWriter(new FileWriter(lockFile)); - writer.write(version); - writer.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - + /** + * Downloads new module package and unpack it + * @param downloadUrlStr Download url + * @param filename Packge file name + * @throws IOException + */ private void downloadAndUnpackModules(String downloadUrlStr, String filename) throws IOException { URL downloadUrl = new URL(downloadUrlStr); File zipFile = new File(this.plugin.getDataFolder(), filename); @@ -91,10 +104,18 @@ private void downloadAndUnpackModules(String downloadUrlStr, String filename) th zipFile.delete(); } + /** + * Returns PVP Arena "files" folder + * @return "files" folder + */ private File getFilesFolder() { return new File(this.plugin.getDataFolder().getPath() + "/files"); } + /** + * Removes recusively a directory + * @param directoryToBeDeleted directory to be deleted + */ private static void deleteDirectory(File directoryToBeDeleted) { File[] allContents = directoryToBeDeleted.listFiles(); if (allContents != null) { diff --git a/src/net/slipcor/pvparena/updater/PluginUpdater.java b/src/net/slipcor/pvparena/updater/PluginUpdater.java index 06a826053..232d6fca2 100644 --- a/src/net/slipcor/pvparena/updater/PluginUpdater.java +++ b/src/net/slipcor/pvparena/updater/PluginUpdater.java @@ -1,6 +1,7 @@ package net.slipcor.pvparena.updater; import com.google.gson.JsonObject; +import net.slipcor.pvparena.core.Language; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; @@ -13,15 +14,29 @@ import java.nio.channels.ReadableByteChannel; import java.util.List; +import static net.slipcor.pvparena.core.Language.*; + +/** + * Manage plugin versions and updates + */ public class PluginUpdater extends AbstractUpdater { private final static String API_URL = "https://api.github.com/repos/Eredrim/pvparena/releases/latest"; - private static final String CONFIG_NODE = "update.mode"; + private static final String CONFIG_NODE = "update.plugin"; + /** + * Construct a plugin updater + * @param plugin PVP Arena instance + * @param msgList Reference to UpdateChecker message list + */ public PluginUpdater(Plugin plugin, List msgList) { super(plugin, msgList, CONFIG_NODE); } + /** + * Run plugin updaters : checks version and downloads update according to config + * @throws IOException Exception if can't connect to github API + */ protected void runUpdater() throws IOException { String currentVersion = plugin.getDescription().getVersion().replace("v", ""); URL githubApi = new URL(API_URL); @@ -32,7 +47,7 @@ protected void runUpdater() throws IOException { if(isUpToDate(currentVersion, onlineVersion)) { LOG.info("PVP Arena is up to date"); } else { - String updateInfo = getAnnounceMessage("PVP Arena", onlineVersion, currentVersion); + String updateInfo = getAnnounceMessage(MSG.UPDATER_PLUGIN.toString(), onlineVersion, currentVersion); LOG.info(updateInfo); if(this.updateMode == UpdateMode.ANNOUNCE) { this.updateMsgList.add(updateInfo); @@ -41,7 +56,7 @@ protected void runUpdater() throws IOException { LOG.info("Downloading update..."); try { downloadPlugin(getDownloadUrlFromJson(versionJson), filename); - String updateSuccess = getPluginSuccessMessage(onlineVersion); + String updateSuccess = getSuccessMessage(MSG.UPDATER_PLUGIN.toString(), onlineVersion); LOG.info(updateSuccess); this.updateMsgList.add(updateSuccess); } catch (IOException e) { @@ -52,6 +67,12 @@ protected void runUpdater() throws IOException { } } + /** + * Downloads new plugin version and put it into "upadate" folder + * @param downloadUrlStr Download url + * @param filename Name of file to download + * @throws IOException Exception if download fails + */ private static void downloadPlugin(String downloadUrlStr, String filename) throws IOException { URL downloadUrl = new URL(downloadUrlStr); final File updateFolder = Bukkit.getServer().getUpdateFolderFile(); diff --git a/src/net/slipcor/pvparena/updater/UpdateChecker.java b/src/net/slipcor/pvparena/updater/UpdateChecker.java index 69b4675ae..52571bf9c 100644 --- a/src/net/slipcor/pvparena/updater/UpdateChecker.java +++ b/src/net/slipcor/pvparena/updater/UpdateChecker.java @@ -1,6 +1,7 @@ package net.slipcor.pvparena.updater; import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.core.Language; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; @@ -9,9 +10,16 @@ import java.util.ArrayList; import java.util.List; +/** + * Starts updaters and displays messages when player joins server + */ public class UpdateChecker { private List updateMsgList; + /** + * Start plugin and modules updater + * @param plugin PVP Arena instance + */ public UpdateChecker(Plugin plugin) { this.updateMsgList = new ArrayList<>(); @@ -21,12 +29,16 @@ public UpdateChecker(Plugin plugin) { new Thread(modulesUpdater).start(); } + /** + * Send update message to players (OPs) on login + * @param player player who joins server + */ public void displayMessage(final Player player) { Bukkit.getScheduler().scheduleSyncDelayedTask(PVPArena.instance, new Runnable() { @Override public void run() { for(String message : updateMsgList) { - player.sendMessage(String.format("%s=- %s -=%s", ChatColor.GREEN, message, ChatColor.RESET)); + player.sendMessage(Language.parse(Language.MSG.MESSAGES_GENERAL, "PVP Arena", message)); } } }, 20L); diff --git a/src/net/slipcor/pvparena/updater/ZipUtil.java b/src/net/slipcor/pvparena/updater/ZipUtil.java index 269e844bd..037f0c7aa 100644 --- a/src/net/slipcor/pvparena/updater/ZipUtil.java +++ b/src/net/slipcor/pvparena/updater/ZipUtil.java @@ -7,7 +7,16 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +/** + * Util class to manage zip files + */ public class ZipUtil { + /** + * Unzip a zip archive in destDir directory + * @param zipFile The file to unzip + * @param destDir Location where unzip the zip file + * @throws IOException Thrown an error is raised during unzipping + */ public static void unzip(File zipFile, File destDir) throws IOException { byte[] buffer = new byte[1024]; ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile)); @@ -30,6 +39,13 @@ public static void unzip(File zipFile, File destDir) throws IOException { zis.close(); } + /** + * Creates a new file based on a zip entry + * @param destinationDir extracting location of the entry + * @param zipEntry a zip entry + * @return new file created + * @throws IOException Thrown if the is an error during file creation + */ private static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { File destFile = new File(destinationDir, zipEntry.getName()); From 1dacccce4421871d41a178f2309e4e0d35c92106 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Sat, 6 Jul 2019 18:57:59 +0200 Subject: [PATCH 034/115] v1.14.0 - add lang files to repository --- doc/languages.md | 8 +- lang/lang_es-es.yml | 573 ++++++++++++++++++++++++++++++++++++++++++++ lang/lang_ru.yml | 526 ++++++++++++++++++++++++++++++++++++++++ readme.md | 24 +- 4 files changed, 1111 insertions(+), 20 deletions(-) create mode 100644 lang/lang_es-es.yml create mode 100644 lang/lang_ru.yml diff --git a/doc/languages.md b/doc/languages.md index ed6146298..7382ccab1 100644 --- a/doc/languages.md +++ b/doc/languages.md @@ -4,7 +4,7 @@ Download the file and set lang: en to lang: value inside the config.yml download | lang: value | language | author | date ------------- | ------------- | ------------- | ------------- | ------------- -[link](http://www.slipcor.de/public/mc/pafiles/lang_en.yml) | 'en' (default) | English | slipcor | 2013/09/11 -[link](http://www.slipcor.de/public/mc/pafiles/lang_es-es.yml) | 'es-es' | Espaol | Anubis3467 | 2014/09/11 -[link](http://www.slipcor.de/public/mc/pafiles/lang_fr.yml) | 'fr' | Franais | Fizzweapon | 2013/08/22 -[link](http://www.slipcor.de/public/mc/pafiles/lang_ru.yml) | 'ru' | Russki | llNeosGamer | 2013/04/13 \ No newline at end of file +[link](../lang/lang_en.yml) | 'en' (default) | English | slipcor | 2013/09/11 +[link](../lang/lang_es-es.yml) | 'es-es' | Español | Anubis3467 | 2014/09/11 +[link](../lang/lang_fr.yml) | 'fr' | Français | Fizzweapon | 2013/08/22 +[link](../lang/lang_ru.yml) | 'ru' | Russki | llNeosGamer | 2013/04/13 \ No newline at end of file diff --git a/lang/lang_es-es.yml b/lang/lang_es-es.yml new file mode 100644 index 000000000..178366bfa --- /dev/null +++ b/lang/lang_es-es.yml @@ -0,0 +1,573 @@ +nulang: + arena: + create: + done: ¡Arena '%1%' creada! + disable: + done: ¡Arena desabilitada! + edit: + disabled: Modo de edición para la Arena %1% desactivada + enabled: Modo de edición para la Arena %1% activada + enable: + done: ¡Arena activada! + arenalist: 'Arenas: &a%1%&r' + regionshapeunknown: 'Forma de Arena (Shape) ''%1%'' desconocida. Mira en el foro + las formas disponibles: http://goo.gl/IfLOh' + reload: + done: ¡Arena recargada! + remove: + done: 'Arena borrada: &e%1%&r' + setup: + disabled: 'Modo de configuración desactivada para la Arena: %1%' + enabled: 'Modo de configuración activada para la Arena: %1%' + startingin: Jugadores necesarios listos. Comenzando en %1%! + start: + done: ¡Arena forzada a comenzar! + stop: + done: ¡Arena forzada a acabar! + autosetup: + automanual: ¿Quieres el Asistente para &a%1%&r o &a%2%&r? + automatic: automático + manual: manual + modeselected: ¡Modo &a%1%&r seleccionado! + welcome: '¡Bienvenido al Asistente de autoconfiguración de PvP Arena! + + ¡Por favor, solo escribe las respuestas de colores en el chat. No se necesitan + comandos!' + blacklist: + added: ¡Añadido &a%1%&r a la &e%2%&r Lista Negra (blacklist)! + allcleared: ¡Toda la Lista Negra (blacklists ha sido limpiada! + cleared: ¡&e%1%&r removido de la Lista Negra (blacklist)! + help: 'Uso: Lista Negra limpiada (blacklist) | Lista Negra (blacklist) [tipo] + [clear|add|remove] [id]' + removed: ¡&a%1%&r removido de la &e%2%&r Lista Negra (blacklist)! + show: 'Blacklist &e%1%&r:' + check: + done: Verificación completada, ¡No errores encontrados! + class: + preview: Estas probando la clase %1% + removed: Removiendo la Clase %1% + saved: ¡La Clase %1% se ha guardado exitosamente! + selected: Has cambiado a la Clase &e%1%&e + deathcause: + BLOCK_EXPLOSION: una Explosión + CONTACT: un cactus + CUSTOM: Herobrine + DROWNING: Agua + ENTITY_EXPLOSION: Una Explosión + FALL: por caída + FIRE_TICK: fuego + FIRE: un fuego + LAVA: lava + LIGHTNING: Rayo + MAGIC: PODERES MAGICOS + POISON: Veneno + PROJECTILE: algo que el/ella no vió venir + STARVATION: Hambre + SUFFOCATION: falta de aire + SUICIDE: sí mismo + VOID: el vacíp + CREEPER: un Creeper + SKELETON: un Esqueleton + SPIDER: una Araña + GIANT: un Gigante + ZOMBIE: un Zombie + SLIME: un Slime + GHAST: un Ghast + PIG_ZOMBIE: un Zombie Pigman + ENDERMAN: un Enderman + CAVE_SPIDER: una Araña de Cueva + SILVERFISH: Lepisma + BLAZE: un Blaze + MAGMA_CUBE: un Magma Cube + ENDER_DRAGON: un Ender Dragon + WITHER: un Wither + WITCH: una Bruja + WOLF: un Lobo + IRON_GOLEM: un Iron Golem + SPLASH_POTION: una Poción Arrojadiza + duty: + 'false': You are now off duty! + 'true': You are now on duty! + error: + arena: + alreadyplaying: ¡Ya eres parte de &a%1%&r! + arenaexists: ¡La Arena aún existe!! + arenanotexists: La Arena %1% no existe + arenaconfig: Un Error se ha enontrado mientras se cargaba la Arena %1% + argumenttype: '&cTipo de Argumento inválido:&r &e%1%&r no es apropiado &a%2%&r' + argument: '&cArgumento no reconocido:&r %1% - Argumentos posibles: &a%2%&r' + autosetup: + running: '¡El Asistente de autoconfiguración ya esta activado! Jugador: %1%' + blacklist: + disallowed: ¡No deberás poner en la Lista Negra (blacklist) a este -> %1%! + unknownsubcommand: 'Sub-Comando Desconocido. Comandos validos: &a%1%&r' + unknowntype: 'Tipo Desconocido. Tipos validos: &e%1%&r' + class: + full: ¡La Clase &a%1%&r esta llena! + notenoughexp: ¡No tienes Nivel suficiente para escojer &a%1%&r! + notfound: 'Clase no encontrada: &a%1%&r' + cmdblocked: '&cComando bloqueado: %1%' + invalidcmd: Comando Inválido (%1%) + unknowncmd: Comando Desconocido + arenadisabled: Arena deshabilitada, por favor intenta otra vez luego :c + editmode: Modo edición ¬¬ + error: '&cError: %1%' + fightinprogress: ¡Hay una partida en progreso! + goal: + legacyunknown: '¡Objetivo (Goal) ingresada: "&a%1%&r" desconocida! Si deseas + añadir objetivos utiliza el comando: &a/pa [Arena] goal [Nombre del Objetivo + (goal)]' + goalnotfound: 'Objetivo &a%1%&r desconocido. Objetivos validos: &a%2%&r' + install: Error mientras se instalaba &a%1%&r + invalid_argument_count: '&cNúmero inválido de Argumentos&r (%1% en lugar de + %2%)!' + invalidstattype: 'Tipo de Estadística inválido: %1%' + valuenotfound: 'Valor inválido: &a%1%&r!' + invfull: ¡Tu inventario esta lleno, no recibiste tu recompensa! + arenafull: ¡La Arena esta llena :c! + joinrange: ¡Estas muy lejos de el Arena para unirse de la Arena! + notjoinregion: ¡No estas en el lugar correcto para unirse a la Arena! Ve allí para unirte. + teamfull: ¡El Equipo %1% esta lleno! + insidevehicle: ¡No puedes unirte a una Arena mientras estas en un Bote/Minecart/Caballo/Cerdo/ vehículos en general! + errorloungefree: ¡Error la Arena no esta en el modo sin equipos (free mode). Utiliza '[Nombre del equipo en Inglés Ejemplo Blue, Red, etc.]lounge' + log: + matnotfound: 'Material incorrecto: %1%' + missingspawn: 'Lugar de Reaparición(Spawn) no encontrado: &r%1%' + noarenas: ¡No tienes ninguna Arena! + valueneg: 'Valores Negativos: &c%1%&r' + nofight: No hay ninguna Partida/Batalla en progreso. + nogoal: ¡No has añadido ningún Objetivo(goal) para la Arena! Utiliza el comando &a/pa [Nombre de la Arena] goal [Nombre del Objetivo(goal)] para añadir uno + nospawns: ¡No se ha añadido ningún Lugar de Aparición(Spawn) para la Arena! + classperms: No tienes permisos para utilizar la Clase "&a%1%&r" + permjoin: You don't have permission to join the arena! + noperm: '&cNo tienes permisos para %1%' + noplayerfound: ¡No jugadores encontrados! + notinarena: ¡No eres parte de ninguna Arena! + notnumeric: '&cArgumento no numerico:&r %1%' + notsameworld: ¡No estas en el mismo Mundo de la Arena (%1%)! + noteamfound: ¡Equipos no encontrados! + onlyplayers: '&cEste comando solo puede ser utilizado por los Jugadores! &4Así + que no seas perezoso y no lo vuelvas a hacer desde el cmd ¬¬' + playernotfound: '&cJugador no encontrado: &r%1%&c!' + positives: 'Valores Positivos: &b%1%&r' + potioneffecttypenotfound: 'Efecto de poción: &e%1%&r no encontrado/reconocido' + ready: + notready0: No hay ningún jugador listos + notready1: Estas solo en la Arena :c + notready2: Tu Equipo esta solo en la Arena + notready3: A un Equipo le falta jugaores + notready4: A la Arena le falta Jugadores + notready5: Al menos un Jugadores no ha elejido ninguna clase aún + noclass: ¡No has elejido clase! + error: La Arena no esta lista/A la arena le falta %1% + region: + beingcreated: Ya hay una Región creada con el mismo nombre (%1%) + flagnotfound: '¡RegionFlag &a%1%&r desconocido! Valores válidos: %2%' + notfound: Región &a%1%&r no encontrada + protectionnotfound: ¡RegionProtection &a%1%&r desconocido! + typenotfound: 'RegionType &a%1%&r desconocido! Valores válidos: %2%' + youselect: Ya esas seleccionando una Región (Para dejar de Seleccionar escribe el Comando otra vez) + youselect2: Escribe el Comando una vez más para cancelar la selección de la Región + youselectexit: Selección de Región cancelada! + regionnotbeingcreated: ¡No estas creando una Región! + regionnotremoved: No hay ninguna configuración de región. + select2: Seleccione dos puntos antes de tratar de guardar. + setupmode: ¡Modo de Configuración! + spawn: + unknown: 'Lugar de reaparición (spawn) desconocido: &a%1%&r' + spawnfree: ¡Error! Arena esta en el tipo libre (free). Usa 'spawn1, spawn2, spawn3, etc' + statsfile: Error mientras se reconocia el archivo "stats" + teamnotfound: 'Equipo no encontrado: &a%1%&r' + uninstall: Error mientras se desinstalaba &a%1%&r + unknownmodule: 'Modulo (Module) no encontrado: %1%' + whitelist: + disallowed: No puedes %1% esto! [No estas en la Lista blanca (Whitelist)] + unknownsubcommand: 'Subcomando desconocido. Comandos Válidos: &a%1%&r' + unknowntype: 'Tipo desconocido. Tipos Válidos: &e%1%&r' + nopermto: + madmin: Administrar + create: Crear una Arena + disable: Deshabilitar + edit: Editar una Arena + enable: Habilitar + nopermjoin: Entrar a una Arena + reload: Recargar + remove: Remover una Arena + set: Establecer un Archivo de configuración + setup: Configurar una Arena + teleport: Teletransportarse a un lugar de aparición (Spawn) de alguna Arena + user: Usar PVP Arena + fight: + begins: Partida Comenzando... + draw: ¡EMPATE! ¡Ningún Ganador! + killedbyremaining: ¡%1% ha sido asesinado por %2%! Quedan %3% vidas. + killedbyremainingfrags: ¡%1% ha sido asesinado por %2%! Quedan %3% Vidas. + killedbyremainingteam: ¡%1% ha sido asesinado por %2%! Quedan %3% Vidas para %4%. + killedbyremainingteamfrags: ¡%1% ha sido asesinado por %2%! Quedan %3% Vidas para %4%. + killedby: '%1% ha sido asesinado por %2%!' + playerleft: ¡%1% se fue de la partida! + forcestop: Has forzado a que acabe la Arena. + gamemode: + free: Modo de juego &aLibre para todos (Free For All)&r establecido para la Arena &a%1%&r! + team: Modo de juego &aEquipos (Team)&r establecido para la Arena &a%1%&r! + general: + break: Romper (break) + place: Colocación (place) + use: Usar (use) + goal: + added: 'Meta (Goal) Añadida: &a%1%&r' + installing: 'Instala Metas (Goals) con el Comando: &a/pa install [Nombre de la + Meta (goalname)]&r' + removed: 'Meta removida: &a%1%&r' + blockdestroy: + typeset: 'Tipo de bloque establecido a: &e%1%' + setflag: 'Bloque establecido: %1%' + tosetflag: 'Bloque a establecer: %1%' + dom: + claiming: '&e¡Equipo %1% esta tomando una Bandera!' + claimed: '&e¡Equipo %1% ha tomado una Bandera!' + score: '&e¡Equipo %1% ha anotado %2% Puntos manteniendo una Bandera!' + unclaiming: '&e¡Una Bandera del Equipo %1% esta siendo tomada!' + unclaimingby: '&e¡Una Bandera del Equipo %1% esta siendo tomada por el Equipo + %2%!' + infected: + lost: '&6¡Los Jugadores Infectados han muerto!' + player: '&c¡%1% esta infectado!' + you: '&c¡Estas infectado D:!' + won: '&6¡Los Jugadores Infectados han ganado!' + killreward: + added: 'Recompensa de Asesinato añadida: &e%1%&r->&a%2%' + removed: 'Recompensa de Asesinato removida: &e%1%' + liberation: + liberated: ¡Equipo %1% ha sido liberado! + setbutton: 'Botón Añadido: %1%' + tosetbutton: 'Botón por añadir: %1%' + physicalflags: + holdflag: ¡Tienes que mantener la Bandera para poder llevarla devuelta! + sabotage: + tntignite: '%1% encendió la TNT del Equipo %2%!' + set: 'TNT añadida: %1%' + toset: 'TNT por añadir: %1%' + youtnt: ¡Estas llevando los materiales de Sabotage!' + tank: + tankdown: ¡El Tanque esta muerto! + tankmode: Todos a matar a %1% ¡Él/Ella es el Tanque! + tankwon: ¡El Tanque ha ganado! ¡Felicidades a %1%! + tdc: + denied: '%1% denied a kill!' + remaining: '%1% kills remaining for %2%.' + scored: '%1% scored a kill!' + youdenied: You denied a kill! + youscored: You scored a kill! + pillars: + msg: + block_broken: ¡[%1%] %2% rompió un Bloque! + lower: ¡[%1%] %2% acortó el Pilar! + block_placed: ¡[%1%] %2% puso un Bloque! + higher: ¡[%1%] %2% alargó el Pilar! + claimed: ¡[%1%] %2% ha tomado el pilar! + unclaimed: ¡[%1%] %2% esta siendo tomado! + score: '%1% hizo %2% punto/s' + rescue: + flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: + %3%' + flagsave: '%1% dropped the hostage of team %2%!' + flaggrab: '%1% grabbed the hostage of team %2%!' + flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' + setflag: 'Rescue set: %1%' + tosetflag: 'Rescue to set: %1%' + typeset: 'Hostage type set to: &e%1%' + help: + head: '&e--- &aAyuda de PVP Arena&e %1% &e---' + admin: '&c%1% - Ayuda de Administración' + setup: '&e%1% - Ayuda de Configuración' + custom: '&e%1% - Ayuda de Personalización' + game: '&a%1% - Ayuda dentro del Juego' + info: '&9%1% - Ayuda para obtener información' + import: + done: Arena satisfactoriamente importada &e%1%&r! + info: + classes: 'Clases: &a%1%&r' + goal_active: 'Meta(Goal): &a%1%&r' + goal_inactive: 'Meta(Goal): &b%1%&r &7== INACTIVA ==' + head_headlin: 'Información sobre Arena: &a%1%&r | [&a%2%&r]' + head_teams: 'Equipos: &a%1%&r' + mod_active: 'Modulos: &a%1%&r' + mod_inactive: 'Modulo: &b%1%&r &7== INACTIVE ==' + owner: 'Propietario: &a%1%&r' + regions: 'Regiones: &a%1%&r' + section: '----- &a%1%&r -----' + install: + installed: 'Instalado: &a%1%&r' + list: + arenas: 'Arenas Disponibles: %1%' + dead: 'Muerto: %1%' + fighting: 'En batalla: %1%' + lost: 'Perdido: %1%' + lounge: 'Sala de Espera (Lounge): %1%' + 'null': 'Glitched: %1%' + players: 'Jugadores: %1%' + team: 'Equipo %1%: %2%' + ready: 'Listo: %1%' + warm: 'Caliente: %1%' + watching: 'Observando: %1%' + log: + plugindisabled: Deshabilitado (version %1%) + pluginenabled: Habilitado (version %1%) + trickerdisabled: Plugin Seguimiento(Tracking) desabilitado. ¿Nos volveremos a ver? + trackingenabled: 'Plugin Segumieinto(Tracking) Habilitado. Establece el Segumiento(Tracking): + "False" dentro de la configuración principal para deshabilitarlo.' + updatedisabled: Actualizaciones deshabilitadas. Por favor mira dev.bukkit.org para Actualizaciones. + updateenabled: Comprobando Actualizaciones... + warning: '%1%' + messages: + toArena: Ahora estas hablando a la Arena! + toPublic: Ahora estas hablando publicamente! + toTeam: Ahora le estas hablando a tu Equipo! + general: '&e[%1%&e] &r%2%' + noplayer: Ningún Jugador en la Arena de PVP. + notice: + awarded: Se le ha otorgado %1% + nodropitem: ¡No tan Rápido! ¡No hagas trampas! + noteleport: Por favor usa '/pa leave' para salir de la Partida! + notice: 'Aviso: %1%' + playerawarded: '%1% se le ha otorgado %2%' + remove: '&cEsto removerá permanentemente la arena &a%1%&c. ¿Estás seguro? Entonces + usa el comando otra vez!&r Para deshabilitar este mensaje, busca ''safeadmin'' + en tu config.yml' + waitingequal: Espera por un equipo con un número igual de jugadores! + waitingforarena: Esperando por una arena en juego para terminar! + welcomespec: Bienvenio al área de espectador! + gameloot: Aquí está tu botín! + welcomespec2: /pa bet [name] [monto] para apostar a un equipo o jugador + youdeath: Has entrado a una Región de MUERTE. Adiós! + youescaped: Te saliste de la Región de Batalla. Adiós! + youleft: Saliste de la Arena + younocamp: Estas en una Región de No Campeo. ¡Muevete! + playerhaswon: '%1% es el ganador!' + playerready: '%1%&e esta listo!' + notreadyplayers: Algunos jugadores no estan listos + players: Jugadores + ready: + list: 'Jugadores: %1%' + done: Te has marcado como listo + region: + flag: + added: 'Región flag añadida: &a%1%&r' + removed: 'Región flag removida: &a%1%&r' + height: 'Altura de Región puesta a: &a%1%&r' + pos1: Primer punto puesto. + pos2: Segundo punto puesto. + protection_added: 'RegionProtection añadida: &a%1%&r' + protection_removed: 'RegionProtection removida: &a%1%&r' + radius: 'Radio de Región puesta a: &a%1%&r' + removed: 'Región removida: %1%' + saved: Región guardada. + saved_notice: '&cHas creado una Región &oCUSTOM&c. No tiene función aún, conviertela + a una Región de Batalla con el comando &r/pvparena %1% !rt %2% BATTLE' + select: Selecciona 2 puntos, Click Izquierdo y luego Click Derecho + setting: Configuración de Región activada. + typeset: 'Tipo de Región puesta: &e%1%' + youselect: Has activado la selección de Región para la Arena &a%1%&r! + regions: + flags: 'Región Flags: &a%1%&r' + head: '--- &aRegiones de Arena&r [&e%1%&r]---' + listhead: '--- &aRegiones de Arena&r [&e%1%&r]---' + listvalue: '&a%1%&r: %2%, %3%' + protections: 'Región Protections: &a%1%&r' + shape: 'Forma de Región: &a%1%&r' + type: 'Tipo de Región: &a%1%&r' + reloaded: ¡Configuración recargada! + round: + display: 'Ronda #%1%: %2%' + added: 'Meta(Goal) añadida para Ronda: &e%1%' + removed: 'Meta(Goal) removida para Ronda: &e%1%' + set: + done: '&a%1%&r puesto a &e%2%&r!' + help: use /pa {NombreDeLaArena} set [pagina] para obtener una lista de nodos + unknown: 'Nodo desconocido: &e%1%&r!' + setowner: + done: '&a%1%&r ahora es el dueño de la Arena &a%2%&r!' + spawn: + freelounge: Sala de Espera(Lounge) ajustada + teamlounge: 'Sala de Espera(Lounge) para el Equipo: %1% puesta' + notset: 'Lugar de Reaparición(Spawn) no ajustado: &a%1%&r' + removed: 'Lugar de Reaparición(Spawn) removido: &a%1%&r' + set: 'Lugar de Reaparición(Spawn) ajustado: &a%1%&r' + setdone: 'Lugar de Reaparición(Spawn) ajuste hecho: &a%1%&r' + setstart: 'Lugar de Reaparición(Spawn) ajustes comenzados: &a%1%&r' + stats: + filedone: Archivo de estdística cargado! + head: TOP de Estadísticas %1% (%2%) + typenotfound: 'Tipo de estadística no encontrado, valores válidos: &e%1%&r' + stattype: + DAMAGE: Daño completo tratado + DAMAGETAKE: Daño completo tomado + DEATHS: muertes + KILLS: matanzas + LOSSES: partidas perdidos + MAXDAMAGE: máximo de daño dado + MAXDAMAGETAKE: máximo daño tomado + 'NULL': nombre de jugador + WINS: partidas ganados + team: + haswon: Equipo %1%&r son los ganadores! + ready: Equipo %1%&r está listo! + teams: + list: 'Equipos disponibles: %1%' + add: 'Equipo agregado: %1%' + set: 'Equipo puesto: %1%' + remove: 'Equipo removido: %1%' + template: + loaddone: Plantilla cargada desde &a%1%&r + savedone: Plantilla guardada en &a%1%&r + time: + minutes: minutos + seconds: segundos + timer: + countdowninterrupt: Cuenta regresiva interrumpida! Pulse el bloque listo! + ending: El partido terminará en %1%! + resetting: La arena se restaurará en %1%! + starting: Comenzando en %1%! + warmingup: Warming up... %1%! + pvpactivating: PVP será activado en %1%! + walls: Las paredes serán removidas en %1%! + togglemod: + notice: '&cHas activado un modulo que requiere BATTLE región! Type &r/pvparena + [arena] !rt [región] BATTLE' + uninstall: + done: 'desinstalar: &a%1%&r' + whitelist: + added: Agregar &a%1%&r a &e%2%&r whitelist! + allcleared: Toda la whitelist vaciada! + cleared: Whitelist &e%1%&r vaciada! + help: 'Usage: blacklist borrada | blacklist [tipo] [vacir|agregar|remover] [id]' + removed: Removido &a%1%&r de &e%2%&r whitelist! + show: 'Whitelist &e%1%&r:' + mod: + aftermatch: + aftermatch: El aftermatch ha comenzado! + startingin: AfterMatch en %1%! + spawnnotset: Lugar de Reaparición(Spawn) 'after' no establecido! + announcements: + ignoreon: Ahora estás ignorando anuncios! + ignoreoff: Ahora estás recibiendo anuncios! + arenaboards: + createarenaboard: Crea una ArenaBoard + arenaboarddestroyed: ArenaBoard destruida! + boardexists: ArenaBoard ya existe!' + sortingby: ArenaBoard ahora clasificado por %1% + autovote: + arenarunning: 'Arena en juego: %1%' + autojoin: Arena auto join comenzó! + playervoted: '%2% Vota por arena %1%!' + youvoted: Has votado por la Arena %1%! + duel: + accepted: '%1% &eacepta el desafío! El juego está comenzando.' + announce: '%1% &eTe ha desafiado! Acepta el duelo con &r/pa %2% accept.' + requested: Has &edesafiado &r%1%&e! + starting: El duelo comienza! + fixinventorylos: + gamemode: Entre en el modo survival antes de unirse! + invenory: Vacíe su inventario antes de unirse! + latelounge: + llannounce: Arena %1% está comenzando! Jugador %2% desea comenzar. Únase con /pa %1% + llposition: Usted está en la cola %1%! + llrejoin: La verificación se ha cortado, no será capaz de unirse. Vuelva a unirse cuando pueda! + llwait: Arena comenzará pronto, por favor espere! + playerfinder: + near: 'Jugador más cercano: %1% bloques!' + point: Brújula que señala al jugador más cercano! + powerups: + invalidpowerupeffect: 'PowerupEffect Inválido: %1%' + puplayer: '%1% ha recogido PowerUp %2%!' + puserver: PowerUp desplegado! + skins: + dc: Conexión dentro de DisguiseCraft! + md: Conexión dentro de MobDisguise! + nomod: Ningún plugin de ocultamieto encontrado, Módulo de Skins está inactivo! + showclass: Clase &e%1%&r será ocultado a &a%2% + showteam: Equipo %1% será ocultado a %2% + specialjoin: + done: Bloque con el cuál los jugadores podrán unirse a la partida puesto en - %1% + start: Poniendo un Bloque de poder unirse + stop: Bloque de poner unirse selección abortada + startfreeze: + announce: La Partida comenzará en %1% segundos + tempperms: + noperms: Plugin de Permisos no encontrado, predeterminando a OP. + head: 'Permiso temporal de &e%1%&r:' + added: Permiso temporal &e%1%&r Agregado a &a%2%&r + removed: Permiso temporal &e%1%&r Removido de &a%2%&r + vault: + 'on': <3 eConomy + 'off': &a%2%' + removed: ' : &e%1%' + liberation: + liberated: %1% ! + setbutton: ' : %1%' + tosetbutton: ' : %1%' + physicalflags: + holdflag: , ! + sabotage: + tntignite: '%1% TNT %2%!' + set: 'TNT : %1%' + toset: 'TNT : %1%' + youtnt: TNT !' + tank: + tankdown: ! + tankmode: ! %1%, ! + tankwon: ! %1%! + pillars: + msg: + block_broken: '[%1%] %2% !' + lower: '[%1%] %2% !' + block_placed: '[%1%] %2% !' + higher: '[%1%] %2% !' + claimed: '[%1%] %2% !' + unclaimed: '[%1%] %2% !' + score: '%1% %2% ' + help: + head: '&e--- &aPVP Arena &e %1% &e---' + admin: '&c%1% - ' + setup: '&e%1% - ' + custom: '&e%1% - ' + game: '&a%1% - ' + info: '&9%1% - ' + import: + done: &e%1%&r! + info: + classes: ': &a%1%&r' + goal_active: ': &a%1%&r' + goal_inactive: ': &b%1%&r &7== ==' + head_headlin: ' : &a%1%&r | [&a%2%&r]' + head_teams: ': &a%1%&r' + mod_active: ': &a%1%&r' + mod_inactive: ': &b%1%&r &7== ==' + owner: ': &a%1%&r' + regions: ': &a%1%&r' + section: '----- &a%1%&r -----' + install: + installed: ': &a%1%&r' + list: + arenas: ' : %1%' + dead: '̸: %1%' + fighting: ': %1%' + lost: ': %1%' + lounge: ': %1%' + 'null': ': %1%' + players: ': %1%' + team: ' %1%: %2%' + ready: ': %1%' + warm: ': %1%' + watching: ': %1%' + log: + plugindisabled: ( %1%) + pluginenabled: ( %1%) + trickerdisabled: . ? + trackingenabled: ' . : false .' + updatedisabled: . dev.bukkit . + updateenabled: ... + warning: '%1%' + messages: + toArena: ! + toPublic: ! + toTeam: ! + noplayer: PVP arena. + notice: + awarded: %1% + nodropitem: ! ! + noteleport: '/pa leave' ! + notice: ': %1%' + playerawarded: '%1% %2%' + remove: '&c &a%1%&c. ? + !&f , ''safeadmin'' + config.yml' + waitingequal: ! + waitingforarena: , ! + welcomespec: ! + welcomespec2: /pa bet [] [] ! + youdeath: . ;)! + youescaped: . ;)! + youleft: ! + younocamp: . ! + playerhaswon: '%1% !' + playerready: '%1%&e !' + notreadyplayers: + players: + ready: + list: ': %1%' + done: ! + region: + flag: + added: ' : &a%1%&r' + removed: ' : &a%1%&r' + height: ' : &a%1%&r' + pos1: . + pos2: . + protection_added: ' : &a%1%&r' + protection_removed: ' : &a%1%&r' + radius: ' : &a%1%&r' + removed: ' : %1%' + saved: . + select: 2 , ! + setting: . + typeset: ' : &e%1%' + youselect: &a%1%&r! + regions: + flags: ' : &a%1%&r' + head: '--- &a &r [&e%1%&r]---' + listhead: '--- &a &r [&e%1%&r]---' + listvalue: '&a%1%&r: %2%, %3%' + protections: ' : &a%1%&r' + shape: ' : &a%1%&r' + type: ' : &a%1%&r' + reloaded: ! + round: + display: ' #%1%/%2%' + added: ' : &e%1%' + removed: ' : &e%1%' + set: + done: '&a%1%&r set to &e%2%&r!' + help: /pa {arenaname} set [] + unknown: ' : &e%1%&r!' + setowner: + done: '&a%1%&r &a%2%&r!' + spawn: + freelounge: + teamlounge: ' : %1%' + notset: ' : &a%1%&r' + removed: ' : &a%1%&r' + set: ' : &a%1%&r' + setdone: ' : &a%1%&r' + setstart: ' : &a%1%&r' + stats: + filedone: ! + head: %1% (%2%) + typenotfound: ' ! : &e%1%&r' + stattype: + DAMAGE: + DAMAGETAKE: + DEATHS: + KILLS: + LOSSES: + MAXDAMAGE: + MAXDAMAGETAKE: + 'NULL': + WINS: + team: + haswon: '%1% !' + ready: '%1% !' + teams: + list: ' : %1%' + add: ' : %1%' + set: ' : %1%' + remove: ' : %1%' + time: + minutes: + seconds: + timer: + countdowninterrupt: interrupted! ! + ending: %1%! + resetting: %1%! + starting: %1%! + warmingup: Warming up... %1%! + pvpactivating: %1%! + walls: %1%! + uninstall: + done: ': &a%1%&r' + whitelist: + added: &a%1%&r &e%2%&r ! + allcleared: ! + cleared: &e%1%&r ! + help: ': blacklist clear | blacklist [type] [clear|add|remove] [id]' + removed: Removed &a%1%&r from &e%2%&r whitelist! + show: 'Whitelist &e%1%&r:' + mod: + aftermatch: + aftermatch: AfterMatch ! + startingin: AfterMatch %1%! + spawnnotset: 'after' ! + announcements: + ignoreon: ! + ignoreoff: ! + arenaboards: + createarenaboard: + arenaboarddestroyed: ! + boardexists: !' + sortingby: %1% + autovote: + arenarunning: ' : %1%' + autojoin: ! + playervoted: '%2% %1%!' + youvoted: %1%! + duel: + accepted: '%1% &e ! .' + announce: '%1% &e ! &f/pa %2% accept.' + starting: ! + fixinventorylos: + gamemode: ! + invenory: ! + latelounge: + llannounce: %1% ! , %2%. /pa %1% + llposition: %1%! + llrejoin: , . , ! + llwait: , ! + playerfinder: + near: ' %1% !' + point: ! + powerups: + invalidpowerupeffect: ' : %1%' + puplayer: '%1% %2%!' + puserver: ! + skins: + dc: DisguiseCraft! + md: MobDisguise! + nomod: , ! + showclass: &e%1%&r &a%2% + showteam: %1% %2% + specialjoin: + done: - %1% + start: ! + stop: ! + startfreeze: + announce: %1% ! + tempperms: + noperms: , . + head: ' &e%1%&r:' + added: &e%1%&r &a%2%&r + removed: &e%1%&r &a%2%&r + vault: + 'on': <3 eConomy + 'off': Date: Sun, 7 Jul 2019 00:48:13 +0200 Subject: [PATCH 035/115] v1.14.0 - add bstats --- .gitignore | 1 + pom.xml | 155 +++++++++++++++---------- src/net/slipcor/pvparena/PVPArena.java | 4 + 3 files changed, 98 insertions(+), 62 deletions(-) diff --git a/.gitignore b/.gitignore index ae4d08a55..c76adf957 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ # Maven target/ +dependency-reduced-pom.xml /bin/ diff --git a/pom.xml b/pom.xml index 650bce626..bc2457082 100644 --- a/pom.xml +++ b/pom.xml @@ -1,73 +1,104 @@ - 4.0.0 - - net.slipcor - pvparena + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + net.slipcor + pvparena 1.14.0-SNAPSHOT - PVP Arena + PVP Arena + + + + - - - + + + spigot-repo + https://hub.spigotmc.org/nexus/content/groups/public/ + + + CodeMC + https://repo.codemc.org/repository/maven-public + + - - - spigot-repo - https://hub.spigotmc.org/nexus/content/groups/public/ - - + + + org.bukkit + bukkit + 1.13.2-R0.1-SNAPSHOT + jar + provided + + + org.bstats + bstats-bukkit + 1.5 + compile + + - - - org.bukkit - bukkit - 1.13.2-R0.1-SNAPSHOT - jar - provided - - + http://pa.slipcor.net + + jenkins + https://ci2.craftyn.com + - http://pa.slipcor.net - - jenkins - https://ci2.craftyn.com - - - - clean package install + + clean package install pvparena-${project.version}${buildVersion} - ${basedir}/src + ${basedir}/src - - - . - true - ${basedir}/src - - config.yml - plugin.yml - - - + + + . + true + ${basedir}/src + + config.yml + plugin.yml + + + - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.7 + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + 1.7 1.7 - UTF-8 - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.3.2 - - - + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.3.2 + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + + org.bstats + + net.slipcor.pvparena + + + + + + package + + shade + + + + + + \ No newline at end of file diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index 54ba3becf..a0dafb719 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -16,6 +16,7 @@ import net.slipcor.pvparena.managers.ArenaManager; import net.slipcor.pvparena.managers.StatisticsManager; import net.slipcor.pvparena.updater.UpdateChecker; +import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.Command; @@ -418,6 +419,9 @@ public void onEnable() { instance = this; DEBUG = new Debug(1); + //Enable bStats + Metrics metrics = new Metrics(this); + saveDefaultConfig(); if (!getConfig().contains("shortcuts")) { final List ffa = new ArrayList<>(); From 17f114399f30009811f5d4ec9a3758df4a6223ab Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 10 Jul 2019 23:21:20 +0200 Subject: [PATCH 036/115] v1.14.1 - fix plugin updater --- pom.xml | 2 +- src/net/slipcor/pvparena/PVPArena.java | 6 +-- src/net/slipcor/pvparena/core/Language.java | 10 ++--- .../pvparena/updater/AbstractUpdater.java | 21 ++++++---- .../pvparena/updater/ModulesUpdater.java | 21 +++++----- .../pvparena/updater/PluginUpdater.java | 38 +++++++++++++++---- .../pvparena/updater/UpdateChecker.java | 21 ++++++---- 7 files changed, 76 insertions(+), 43 deletions(-) diff --git a/pom.xml b/pom.xml index bc2457082..7adcb3df8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ net.slipcor pvparena - 1.14.0-SNAPSHOT + 1.14.1-SNAPSHOT PVP Arena diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index a0dafb719..f97708276 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -409,8 +409,8 @@ public void onDisable() { ArenaManager.reset(true); Tracker.stop(); Debug.destroy(); - Language.logInfo(MSG.LOG_PLUGIN_DISABLED, getDescription() - .getFullName()); + this.getUpdateChecker().runOnDisable(); + Language.logInfo(MSG.LOG_PLUGIN_DISABLED, getDescription().getFullName()); } @Override @@ -505,7 +505,7 @@ public void onEnable() { ArenaManager.readShortcuts(getConfig().getConfigurationSection("shortcuts")); } - updateChecker = new UpdateChecker(this); + updateChecker = new UpdateChecker(this.getFile()); if (ArenaManager.count() > 0) { if (PVPArena.instance.getConfig().getBoolean("tracker", true)) { diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 432c4aac0..0517c64b4 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -324,8 +324,6 @@ public enum MSG { LOG_PLUGIN_ENABLED("nulang.log.pluginenabled", "enabled (version %1%)"), LOG_TRACKER_DISABLED("nulang.log.trickerdisabled", "Plugin tracking disabled. See you soon?"), LOG_TRACKER_ENABLED("nulang.log.trackingenabled", "Plugin tracking enabled. Set 'tracker: false' inside the main config to disable."), - LOG_UPDATE_DISABLED("nulang.log.updatedisabled", "Updates deactivated. Please check dev.bukkit for updates."), - LOG_UPDATE_ENABLED("nulang.log.updateenabled", "Checking for updates..."), LOG_WARNING("nulang.log.warning", "%1%"), MESSAGES_TOARENA("nulang.messages.toArena", "You are now talking to the arena!"), @@ -463,10 +461,10 @@ public enum MSG { TOGGLEMOD_NOTICE("nulang.togglemod.notice", "&cYou activated a module that requires a BATTLE region! Type: &r/pvparena [arena] !rt [region] BATTLE"), UNINSTALL_DONE("nulang.uninstall.done", "Uninstalled: &a%1%&r"), - UPDATER_PLUGIN("updater.plugin", "PVP Arena"), - UPDATER_MODULES("updater.modules", "PVP Arena modules pack"), - UPDATER_ANNOUNCE("updater.announce", "%1% %2% is now available ! Your version: %3%"), - UPDATER_SUCCESS("updater.success", "%1% has been updated to %2%. Restart your server to apply update."), + UPDATER_PLUGIN("nulang.updater.plugin", "PVP Arena"), + UPDATER_MODULES("nulang.updater.modules", "PVP Arena modules pack"), + UPDATER_ANNOUNCE("nulang.updater.announce", "%1% %2% is now available ! Your version: %3%"), + UPDATER_SUCCESS("nulang.updater.success", "%1% has been updated to %2%. Restart your server to apply update."), WHITELIST_ADDED("nulang.whitelist.added", "Added &a%1%&r to &e%2%&r whitelist!"), WHITELIST_ALLCLEARED("nulang.whitelist.allcleared", "All whitelists cleared!"), diff --git a/src/net/slipcor/pvparena/updater/AbstractUpdater.java b/src/net/slipcor/pvparena/updater/AbstractUpdater.java index cd65e59d3..498a965fd 100644 --- a/src/net/slipcor/pvparena/updater/AbstractUpdater.java +++ b/src/net/slipcor/pvparena/updater/AbstractUpdater.java @@ -7,7 +7,7 @@ import net.slipcor.pvparena.PVPArena; import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; -import org.bukkit.plugin.Plugin; +import org.bukkit.configuration.file.FileConfiguration; import java.io.BufferedReader; import java.io.IOException; @@ -20,20 +20,19 @@ * Abstract class with shared methods fo updaters */ public abstract class AbstractUpdater implements Runnable { - protected final Plugin plugin; protected final UpdateMode updateMode; protected List updateMsgList; + protected Runnable toRunOnDisable; protected static final Logger LOG = PVPArena.instance.getLogger(); /** * Constructs a AbstractUpdater instance - * @param plugin PVP Arena instance * @param updateMsgList Reference to UpdateChecker message list * @param configNode YML config node to get update setting */ - public AbstractUpdater(Plugin plugin, List updateMsgList, String configNode) { - this.plugin = plugin; - this.updateMode = UpdateMode.getBySetting(plugin.getConfig().getString(configNode, UpdateMode.ANNOUNCE.name())); + public AbstractUpdater(List updateMsgList, String configNode) { + FileConfiguration config = PVPArena.instance.getConfig(); + this.updateMode = UpdateMode.getBySetting(config.getString(configNode, UpdateMode.ANNOUNCE.name())); this.updateMsgList = updateMsgList; } @@ -50,6 +49,12 @@ public void run() { } } + public void runOnDisable() { + if(this.toRunOnDisable != null) { + this.toRunOnDisable.run(); + } + } + /** * Runs an updater implementation * @throws IOException Exception if api.github.com is unreachable @@ -127,8 +132,8 @@ protected static String getSuccessMessage(String... args) { * @return true if current version is up to date, false otherwise */ protected static boolean isUpToDate(String currentVersion, String newVersion) { - String[] fullCurrentVerArr = currentVersion.split("-SNAPSHOT"); - boolean isSnapshot = fullCurrentVerArr.length > 1; + String[] fullCurrentVerArr = currentVersion.split("-"); + boolean isSnapshot = currentVersion.contains("SNAPSHOT"); String[] currentVerArr = fullCurrentVerArr[0].split("\\."); String[] newVerArr = newVersion.split("\\."); int currentVerVal = 0; diff --git a/src/net/slipcor/pvparena/updater/ModulesUpdater.java b/src/net/slipcor/pvparena/updater/ModulesUpdater.java index 101322b20..0a036898e 100644 --- a/src/net/slipcor/pvparena/updater/ModulesUpdater.java +++ b/src/net/slipcor/pvparena/updater/ModulesUpdater.java @@ -1,10 +1,11 @@ package net.slipcor.pvparena.updater; import com.google.gson.JsonObject; -import net.slipcor.pvparena.core.Language; -import org.bukkit.plugin.Plugin; +import net.slipcor.pvparena.PVPArena; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.net.URL; import java.net.URLConnection; import java.nio.channels.Channels; @@ -13,7 +14,7 @@ import java.nio.file.Files; import java.util.List; -import static net.slipcor.pvparena.core.Language.*; +import static net.slipcor.pvparena.core.Language.MSG; /** * Manage modules versions and updates @@ -25,11 +26,10 @@ public class ModulesUpdater extends AbstractUpdater { /** * Construct a modules updater - * @param plugin PVP Arena instance * @param msgList Reference to UpdateChecker message list */ - public ModulesUpdater(Plugin plugin, List msgList) { - super(plugin, msgList, CONFIG_NODE); + public ModulesUpdater(List msgList) { + super(msgList, CONFIG_NODE); } /** @@ -91,7 +91,8 @@ private String getModulesVersion() { */ private void downloadAndUnpackModules(String downloadUrlStr, String filename) throws IOException { URL downloadUrl = new URL(downloadUrlStr); - File zipFile = new File(this.plugin.getDataFolder(), filename); + File dataFolder = PVPArena.instance.getDataFolder(); + File zipFile = new File(dataFolder, filename); if (zipFile.exists()) { zipFile.delete(); } @@ -100,7 +101,7 @@ private void downloadAndUnpackModules(String downloadUrlStr, String filename) th outputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); outputStream.close(); deleteDirectory(this.getFilesFolder()); - ZipUtil.unzip(zipFile, this.plugin.getDataFolder()); + ZipUtil.unzip(zipFile, dataFolder); zipFile.delete(); } @@ -109,7 +110,7 @@ private void downloadAndUnpackModules(String downloadUrlStr, String filename) th * @return "files" folder */ private File getFilesFolder() { - return new File(this.plugin.getDataFolder().getPath() + "/files"); + return new File(PVPArena.instance.getDataFolder().getPath() + "/files"); } /** diff --git a/src/net/slipcor/pvparena/updater/PluginUpdater.java b/src/net/slipcor/pvparena/updater/PluginUpdater.java index 232d6fca2..d4f250ba0 100644 --- a/src/net/slipcor/pvparena/updater/PluginUpdater.java +++ b/src/net/slipcor/pvparena/updater/PluginUpdater.java @@ -1,9 +1,8 @@ package net.slipcor.pvparena.updater; import com.google.gson.JsonObject; -import net.slipcor.pvparena.core.Language; +import net.slipcor.pvparena.PVPArena; import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; import java.io.File; import java.io.FileOutputStream; @@ -14,23 +13,24 @@ import java.nio.channels.ReadableByteChannel; import java.util.List; -import static net.slipcor.pvparena.core.Language.*; +import static net.slipcor.pvparena.core.Language.MSG; /** * Manage plugin versions and updates */ public class PluginUpdater extends AbstractUpdater { - private final static String API_URL = "https://api.github.com/repos/Eredrim/pvparena/releases/latest"; + private static final String API_URL = "https://api.github.com/repos/Eredrim/pvparena/releases/latest"; private static final String CONFIG_NODE = "update.plugin"; + private File pluginJarFile; /** * Construct a plugin updater - * @param plugin PVP Arena instance * @param msgList Reference to UpdateChecker message list */ - public PluginUpdater(Plugin plugin, List msgList) { - super(plugin, msgList, CONFIG_NODE); + public PluginUpdater(List msgList, File pluginJarFile) { + super(msgList, CONFIG_NODE); + this.pluginJarFile = pluginJarFile; } /** @@ -38,7 +38,7 @@ public PluginUpdater(Plugin plugin, List msgList) { * @throws IOException Exception if can't connect to github API */ protected void runUpdater() throws IOException { - String currentVersion = plugin.getDescription().getVersion().replace("v", ""); + String currentVersion = PVPArena.instance.getDescription().getVersion().replace("v", ""); URL githubApi = new URL(API_URL); URLConnection connection = githubApi.openConnection(); JsonObject versionJson = getVersionJson(connection.getInputStream()); @@ -59,6 +59,7 @@ protected void runUpdater() throws IOException { String updateSuccess = getSuccessMessage(MSG.UPDATER_PLUGIN.toString(), onlineVersion); LOG.info(updateSuccess); this.updateMsgList.add(updateSuccess); + this.planPluginRenaming(filename); } catch (IOException e) { LOG.warning("Error during plugin update"); e.printStackTrace(); @@ -88,4 +89,25 @@ private static void downloadPlugin(String downloadUrlStr, String filename) throw outputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); outputStream.close(); } + + /** + * Creates a runnable to rename current plugin jar with new jar name in order to spigot updater + * could replace the plugin by the "update" folder one. + * @param fileName name of downloaded file (currently in "update" folder) + */ + private void planPluginRenaming(String fileName) { + final File pluginJarFile = this.pluginJarFile; + final String newFileName = fileName; + this.toRunOnDisable = new Runnable() { + @Override + public void run() { + String currentFileName = pluginJarFile.getName(); + File newJarFile = new File(pluginJarFile.getPath().replace(currentFileName, newFileName)); + if(!newJarFile.exists()) { + LOG.info("Renaming PVP Arena jar file. It will be replaced by the update on the next startup."); + pluginJarFile.renameTo(newJarFile); + } + } + }; + } } diff --git a/src/net/slipcor/pvparena/updater/UpdateChecker.java b/src/net/slipcor/pvparena/updater/UpdateChecker.java index 52571bf9c..49c15120c 100644 --- a/src/net/slipcor/pvparena/updater/UpdateChecker.java +++ b/src/net/slipcor/pvparena/updater/UpdateChecker.java @@ -3,10 +3,9 @@ import net.slipcor.pvparena.PVPArena; import net.slipcor.pvparena.core.Language; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -15,20 +14,28 @@ */ public class UpdateChecker { private List updateMsgList; + private PluginUpdater pluginUpdater; /** * Start plugin and modules updater - * @param plugin PVP Arena instance + * @param pluginJarFile plugin jar file */ - public UpdateChecker(Plugin plugin) { + public UpdateChecker(File pluginJarFile) { this.updateMsgList = new ArrayList<>(); - PluginUpdater pluginUpdater = new PluginUpdater(plugin, this.updateMsgList); - ModulesUpdater modulesUpdater = new ModulesUpdater(plugin, this.updateMsgList); - new Thread(pluginUpdater).start(); + this.pluginUpdater = new PluginUpdater(this.updateMsgList, pluginJarFile); + ModulesUpdater modulesUpdater = new ModulesUpdater(this.updateMsgList); + new Thread(this.pluginUpdater).start(); new Thread(modulesUpdater).start(); } + /** + * Run methods for plugin updater during plugin disabling + */ + public void runOnDisable() { + this.pluginUpdater.runOnDisable(); + } + /** * Send update message to players (OPs) on login * @param player player who joins server From 7a09dca54fe6d286d97659fb963cde56e5424a17 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Sun, 5 Apr 2020 21:26:41 +0200 Subject: [PATCH 037/115] v1.14.1 - fix death screen bug - issue #18 --- src/net/slipcor/pvparena/arena/Arena.java | 26 +++--- .../pvparena/modules/BattlefieldJoin.java | 86 +++++++++++-------- .../pvparena/modules/StandardLounge.java | 52 +++++++---- .../pvparena/modules/StandardSpectate.java | 57 +++++++----- 4 files changed, 136 insertions(+), 85 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index 30ae7893e..f21d58755 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -1510,10 +1510,10 @@ public boolean removeCustomScoreBoardEntry(final ArenaModule module, final int v * reset a player to his pre-join values * * @param player the player to reset - * @param string the teleport location + * @param destination the teleport location * @param soft if location should be preserved (another tp incoming) */ - private void resetPlayer(final Player player, final String string, final boolean soft, + private void resetPlayer(final Player player, final String destination, final boolean soft, final boolean force) { if (player == null) { return; @@ -1545,14 +1545,19 @@ private void resetPlayer(final Player player, final String string, final boolean ArenaPlayer.reloadInventory(this, player, true); } + this.teleportPlayerAfterReset(destination, soft, force, aPlayer); + } + + private void teleportPlayerAfterReset(final String destination, final boolean soft, final boolean force, final ArenaPlayer aPlayer) { + final Player player = aPlayer.get(); class RunLater implements Runnable { @Override public void run() { - getDebugger().i("string = " + string, player); + getDebugger().i("string = " + destination, player); aPlayer.setTelePass(true); - if ("old".equalsIgnoreCase(string)) { + if ("old".equalsIgnoreCase(destination)) { getDebugger().i("tping to old", player); if (aPlayer.getSavedLocation() != null) { getDebugger().i("location is fine", player); @@ -1565,13 +1570,13 @@ public void run() { aPlayer.setTeleporting(false); } } else { - Location offset = getOffset(string); + Location offset = getOffset(destination); if (offset == null) { offset = new Location(Bukkit.getWorlds().get(0), 0, 0, 0); } - final PALocation loc = SpawnManager.getSpawnByExactName(Arena.this, string); + final PALocation loc = SpawnManager.getSpawnByExactName(Arena.this, destination); if (loc == null) { - new Exception("RESET Spawn null: " + getName() + "->" + string).printStackTrace(); + new Exception("RESET Spawn null: " + getName() + "->" + destination).printStackTrace(); } else { player.teleport(loc.toLocation().add(offset.toVector())); aPlayer.setTelePass(false); @@ -1594,10 +1599,11 @@ public void run() { final RunLater runLater = new RunLater(); aPlayer.setTeleporting(true); - if (cfg.getInt(CFG.TIME_RESETDELAY) > -1 && !force) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, runLater, cfg.getInt(CFG.TIME_RESETDELAY)); + if (cfg.getInt(CFG.TIME_RESETDELAY) > 0 && !force) { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, runLater, cfg.getInt(CFG.TIME_RESETDELAY) * 20); } else { - runLater.run(); + // Waiting two ticks in order to avoid player death bug + Bukkit.getScheduler().runTaskLater(PVPArena.instance, runLater, 2); } } diff --git a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java index 2481fdbf6..ab3801da0 100644 --- a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java +++ b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java @@ -118,49 +118,61 @@ public void commitJoin(final Player sender, final ArenaTeam team) { } } - if (player.getState() == null) { - - final Arena arena = player.getArena(); - - - player.createState(player.get()); - ArenaPlayer.backupAndClearInventory(arena, player.get()); - player.dump(); - - - if (player.getArenaTeam() != null && player.getArenaClass() == null) { - final String autoClass = - arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? - arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) - : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player.get(), null, autoClass); - } - if (autoClass == null) { - arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); - return; - } - } - } else { - PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); - } - - class RunLater implements Runnable { + this.initArenaPlayerAndPlanStart(player); + } + /** + * Init player state and inventory after 2 ticks in order to avoid a player death bug, then plan the arena start + * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) + * @param player The arena player object + */ + private void initArenaPlayerAndPlanStart(final ArenaPlayer player) { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { @Override public void run() { - Boolean check = PACheck.handleStart(arena, sender, true); - if (check == null || !check) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, this, 10L); + if (player.getState() == null) { + + final Arena arena = player.getArena(); + + + player.createState(player.get()); + ArenaPlayer.backupAndClearInventory(arena, player.get()); + player.dump(); + + + if (player.getArenaTeam() != null && player.getArenaClass() == null) { + final String autoClass = + arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? + arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) + : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player.get(), null, autoClass); + } + if (autoClass == null) { + arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + return; + } + } + } else { + PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); } - } - } + class RunLater implements Runnable { + @Override + public void run() { + Boolean check = PACheck.handleStart(arena, player.get(), true); + if (check == null || !check) { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, this, 10L); + } + } + } - if (runner == null) { - runner = new RunLater(); - Bukkit.getScheduler().runTaskLater(PVPArena.instance, runner, 10L); - } + if (runner == null) { + runner = new RunLater(); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, runner, 10L); + } + } + }, 2); } @Override diff --git a/src/net/slipcor/pvparena/modules/StandardLounge.java b/src/net/slipcor/pvparena/modules/StandardLounge.java index c9c78870c..1958df3b7 100644 --- a/src/net/slipcor/pvparena/modules/StandardLounge.java +++ b/src/net/slipcor/pvparena/modules/StandardLounge.java @@ -13,6 +13,7 @@ import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.loadables.ArenaModule; import net.slipcor.pvparena.managers.ArenaManager; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -218,27 +219,42 @@ public void commitJoin(final Player sender, final ArenaTeam team) { )); } - if (player.getState() == null) { - - final Arena arena = player.getArena(); - - player.createState(player.get()); - ArenaPlayer.backupAndClearInventory(arena, player.get()); - player.dump(); - + this.initArenaPlayer(player); + } - if (player.getArenaTeam() != null && player.getArenaClass() == null) { - final String autoClass = arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player.get(), null, autoClass); - } - if (autoClass == null) { - arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + /** + * Init player state and inventory after 2 ticks in order to avoid a player death bug + * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) + * @param player The arena player object + */ + private void initArenaPlayer(final ArenaPlayer player) { + System.out.println("DELAYING LOUNGE"); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { + @Override + public void run() { + if (player.getState() == null) { + + final Arena arena = player.getArena(); + + player.createState(player.get()); + ArenaPlayer.backupAndClearInventory(arena, player.get()); + player.dump(); + + + if (player.getArenaTeam() != null && player.getArenaClass() == null) { + final String autoClass = arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player.get(), null, autoClass); + } + if (autoClass == null) { + arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + } + } + } else { + PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); } } - } else { - PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); - } + }, 2); } @Override diff --git a/src/net/slipcor/pvparena/modules/StandardSpectate.java b/src/net/slipcor/pvparena/modules/StandardSpectate.java index 878261303..3a6529af9 100644 --- a/src/net/slipcor/pvparena/modules/StandardSpectate.java +++ b/src/net/slipcor/pvparena/modules/StandardSpectate.java @@ -11,6 +11,7 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.loadables.ArenaModule; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -74,29 +75,45 @@ public void commitSpectate(final Player player) { arena.tpPlayerToCoordName(player, "spectator"); arena.msg(player, Language.parse(arena, MSG.NOTICE_WELCOME_SPECTATOR)); - if (aPlayer.getState() == null) { - - final Arena arena = aPlayer.getArena(); - - aPlayer.createState(player); - ArenaPlayer.backupAndClearInventory(arena, player); - aPlayer.dump(); - - - if (aPlayer.getArenaTeam() != null && aPlayer.getArenaClass() == null) { - final String autoClass = - arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? - arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) - : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + this.initArenaPlayer(aPlayer); + } - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player, null, autoClass); - } - if (autoClass == null) { - arena.msg(player, Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + /** + * Init player state and inventory after 2 ticks in order to avoid a player death bug + * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) + * @param aPlayer The arena player object + */ + private void initArenaPlayer(final ArenaPlayer aPlayer) { + System.out.println("DELAYING SPECTATE"); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { + @Override + public void run() { + Player player = aPlayer.get(); + if (aPlayer.getState() == null) { + + final Arena arena = aPlayer.getArena(); + + aPlayer.createState(player); + ArenaPlayer.backupAndClearInventory(arena, player); + aPlayer.dump(); + + + if (aPlayer.getArenaTeam() != null && aPlayer.getArenaClass() == null) { + final String autoClass = + arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? + arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) + : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player, null, autoClass); + } + if (autoClass == null) { + arena.msg(player, Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + } + } } } - } + }, 2); } @Override From 0e2f4b1b2697418518bb7e17e5cadd35d299649d Mon Sep 17 00:00:00 2001 From: Eredrim Date: Mon, 13 Apr 2020 13:16:41 +0200 Subject: [PATCH 038/115] v1.14.1 - remove residual debugging --- src/net/slipcor/pvparena/modules/StandardLounge.java | 1 - src/net/slipcor/pvparena/modules/StandardSpectate.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/net/slipcor/pvparena/modules/StandardLounge.java b/src/net/slipcor/pvparena/modules/StandardLounge.java index 1958df3b7..8ad6bccb8 100644 --- a/src/net/slipcor/pvparena/modules/StandardLounge.java +++ b/src/net/slipcor/pvparena/modules/StandardLounge.java @@ -228,7 +228,6 @@ public void commitJoin(final Player sender, final ArenaTeam team) { * @param player The arena player object */ private void initArenaPlayer(final ArenaPlayer player) { - System.out.println("DELAYING LOUNGE"); Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { @Override public void run() { diff --git a/src/net/slipcor/pvparena/modules/StandardSpectate.java b/src/net/slipcor/pvparena/modules/StandardSpectate.java index 3a6529af9..48fc90ca7 100644 --- a/src/net/slipcor/pvparena/modules/StandardSpectate.java +++ b/src/net/slipcor/pvparena/modules/StandardSpectate.java @@ -84,7 +84,6 @@ public void commitSpectate(final Player player) { * @param aPlayer The arena player object */ private void initArenaPlayer(final ArenaPlayer aPlayer) { - System.out.println("DELAYING SPECTATE"); Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { @Override public void run() { From 2c528d6fa00f04f50ca0edef4d228ffed706581e Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 23 Apr 2020 20:19:24 +0200 Subject: [PATCH 039/115] v1.14.1 - revert last fix and try to fix death screen bug differently --- src/net/slipcor/pvparena/arena/Arena.java | 45 +++++++--- .../pvparena/modules/BattlefieldJoin.java | 88 ++++++++----------- .../pvparena/modules/StandardLounge.java | 55 +++++------- .../pvparena/modules/StandardSpectate.java | 58 +++++------- 4 files changed, 112 insertions(+), 134 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index f21d58755..f250e2ebd 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -1601,6 +1601,8 @@ public void run() { aPlayer.setTeleporting(true); if (cfg.getInt(CFG.TIME_RESETDELAY) > 0 && !force) { Bukkit.getScheduler().runTaskLater(PVPArena.instance, runLater, cfg.getInt(CFG.TIME_RESETDELAY) * 20); + } else if (PVPArena.instance.isShuttingDown()) { + runLater.run(); } else { // Waiting two ticks in order to avoid player death bug Bukkit.getScheduler().runTaskLater(PVPArena.instance, runLater, 2); @@ -2013,13 +2015,17 @@ public String toString() { return name; } + public void tpPlayerToCoordName(Player player, String place) { + this.tpPlayerToCoordName(player, place, false); + } + /** * teleport a given player to the given coord string * * @param player the player to teleport * @param place the coord string */ - public void tpPlayerToCoordName(final Player player, final String place) { + public void tpPlayerToCoordName(final Player player, final String place, final boolean runAsync) { getDebugger().i("teleporting " + player + " to coord " + place, player); if (player == null) { @@ -2061,22 +2067,16 @@ public void tpPlayerToCoordName(final Player player, final String place) { aPlayer.setTeleporting(true); aPlayer.setTelePass(true); - player.teleport(loc.toLocation().add(offset.getX(),offset.getY(),offset.getZ())); - player.setNoDamageTicks(cfg.getInt(CFG.TIME_TELEPORTPROTECT) * 20); - if (place.contains("lounge")) { - getDebugger().i("setting TelePass later!"); + final Location destination = loc.toLocation().add(offset.getX(), offset.getY(), offset.getZ()); + if(runAsync) { Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { @Override public void run() { - aPlayer.setTelePass(false); - aPlayer.setTeleporting(false); + teleportPlayer(place, aPlayer, destination); } - }, cfg.getInt(CFG.TIME_TELEPORTPROTECT) * 20); - + }, 2); } else { - getDebugger().i("setting TelePass now!"); - aPlayer.setTelePass(false); - aPlayer.setTeleporting(false); + this.teleportPlayer(place, aPlayer, destination); } if (cfg.getBoolean(CFG.PLAYER_REMOVEARROWS)) { @@ -2113,6 +2113,27 @@ public void run() { } } + private void teleportPlayer(String place, final ArenaPlayer aPlayer, Location location) { + Player player = aPlayer.get(); + player.teleport(location); + player.setNoDamageTicks(cfg.getInt(CFG.TIME_TELEPORTPROTECT) * 20); + if (place.contains("lounge")) { + getDebugger().i("setting TelePass later!"); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { + @Override + public void run() { + aPlayer.setTelePass(false); + aPlayer.setTeleporting(false); + } + }, cfg.getInt(CFG.TIME_TELEPORTPROTECT) * 20); + + } else { + getDebugger().i("setting TelePass now!"); + aPlayer.setTelePass(false); + aPlayer.setTeleporting(false); + } + } + /** * last resort to put a player into an arena (when no goal/module wants to) * diff --git a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java index ab3801da0..4a9b8bf1d 100644 --- a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java +++ b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java @@ -113,66 +113,54 @@ public void commitJoin(final Player sender, final ArenaTeam team) { for (final PASpawn spawn : spawns) { if (--pos < 0) { - arena.tpPlayerToCoordName(player.get(), spawn.getName()); + arena.tpPlayerToCoordName(player.get(), spawn.getName(), true); break; } } - this.initArenaPlayerAndPlanStart(player); - } + if (player.getState() == null) { + + final Arena arena = player.getArena(); - /** - * Init player state and inventory after 2 ticks in order to avoid a player death bug, then plan the arena start - * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) - * @param player The arena player object - */ - private void initArenaPlayerAndPlanStart(final ArenaPlayer player) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { - @Override - public void run() { - if (player.getState() == null) { - - final Arena arena = player.getArena(); - - - player.createState(player.get()); - ArenaPlayer.backupAndClearInventory(arena, player.get()); - player.dump(); - - - if (player.getArenaTeam() != null && player.getArenaClass() == null) { - final String autoClass = - arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? - arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) - : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player.get(), null, autoClass); - } - if (autoClass == null) { - arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); - return; - } - } - } else { - PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); - } - class RunLater implements Runnable { - @Override - public void run() { - Boolean check = PACheck.handleStart(arena, player.get(), true); - if (check == null || !check) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, this, 10L); - } - } + player.createState(player.get()); + ArenaPlayer.backupAndClearInventory(arena, player.get()); + player.dump(); + + + if (player.getArenaTeam() != null && player.getArenaClass() == null) { + final String autoClass = + arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? + arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) + : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player.get(), null, autoClass); } + if (autoClass == null) { + arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); + return; + } + } + } else { + PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); + } + + class RunLater implements Runnable { - if (runner == null) { - runner = new RunLater(); - Bukkit.getScheduler().runTaskLater(PVPArena.instance, runner, 10L); + @Override + public void run() { + Boolean check = PACheck.handleStart(arena, sender, true); + if (check == null || !check) { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, this, 10L); } } - }, 2); + + } + + if (runner == null) { + runner = new RunLater(); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, runner, 10L); + } } @Override diff --git a/src/net/slipcor/pvparena/modules/StandardLounge.java b/src/net/slipcor/pvparena/modules/StandardLounge.java index 8ad6bccb8..2dcf98c11 100644 --- a/src/net/slipcor/pvparena/modules/StandardLounge.java +++ b/src/net/slipcor/pvparena/modules/StandardLounge.java @@ -13,7 +13,6 @@ import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.loadables.ArenaModule; import net.slipcor.pvparena.managers.ArenaManager; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -180,9 +179,9 @@ public void commitJoin(final Player sender, final ArenaTeam team) { team.add(player); if (arena.isFreeForAll()) { - arena.tpPlayerToCoordName(player.get(), "lounge"); + arena.tpPlayerToCoordName(player.get(), "lounge", true); } else { - arena.tpPlayerToCoordName(player.get(), team.getName() + "lounge"); + arena.tpPlayerToCoordName(player.get(), team.getName() + "lounge", true); } player.setStatus(Status.LOUNGE); @@ -219,41 +218,27 @@ public void commitJoin(final Player sender, final ArenaTeam team) { )); } - this.initArenaPlayer(player); - } + if (player.getState() == null) { + + final Arena arena = player.getArena(); + + player.createState(player.get()); + ArenaPlayer.backupAndClearInventory(arena, player.get()); + player.dump(); + - /** - * Init player state and inventory after 2 ticks in order to avoid a player death bug - * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) - * @param player The arena player object - */ - private void initArenaPlayer(final ArenaPlayer player) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { - @Override - public void run() { - if (player.getState() == null) { - - final Arena arena = player.getArena(); - - player.createState(player.get()); - ArenaPlayer.backupAndClearInventory(arena, player.get()); - player.dump(); - - - if (player.getArenaTeam() != null && player.getArenaClass() == null) { - final String autoClass = arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player.get(), null, autoClass); - } - if (autoClass == null) { - arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); - } - } - } else { - PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); + if (player.getArenaTeam() != null && player.getArenaClass() == null) { + final String autoClass = arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player.get(), null, autoClass); + } + if (autoClass == null) { + arena.msg(player.get(), Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); } } - }, 2); + } else { + PVPArena.instance.getLogger().warning("Player has a state while joining: " + player.getName()); + } } @Override diff --git a/src/net/slipcor/pvparena/modules/StandardSpectate.java b/src/net/slipcor/pvparena/modules/StandardSpectate.java index 48fc90ca7..f7f03ffe9 100644 --- a/src/net/slipcor/pvparena/modules/StandardSpectate.java +++ b/src/net/slipcor/pvparena/modules/StandardSpectate.java @@ -11,7 +11,6 @@ import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; import net.slipcor.pvparena.loadables.ArenaModule; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -72,47 +71,32 @@ public void commitSpectate(final Player player) { aPlayer.setArena(arena); aPlayer.setStatus(Status.WATCH); - arena.tpPlayerToCoordName(player, "spectator"); + arena.tpPlayerToCoordName(player, "spectator", true); arena.msg(player, Language.parse(arena, MSG.NOTICE_WELCOME_SPECTATOR)); - this.initArenaPlayer(aPlayer); - } + if (aPlayer.getState() == null) { + + final Arena arena = aPlayer.getArena(); + + aPlayer.createState(player); + ArenaPlayer.backupAndClearInventory(arena, player); + aPlayer.dump(); + - /** - * Init player state and inventory after 2 ticks in order to avoid a player death bug - * (bug appears if player health and position are change in the same time, happens since Spigot 1.14) - * @param aPlayer The arena player object - */ - private void initArenaPlayer(final ArenaPlayer aPlayer) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { - @Override - public void run() { - Player player = aPlayer.get(); - if (aPlayer.getState() == null) { - - final Arena arena = aPlayer.getArena(); - - aPlayer.createState(player); - ArenaPlayer.backupAndClearInventory(arena, player); - aPlayer.dump(); - - - if (aPlayer.getArenaTeam() != null && aPlayer.getArenaClass() == null) { - final String autoClass = - arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? - arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) - : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); - - if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { - arena.chooseClass(player, null, autoClass); - } - if (autoClass == null) { - arena.msg(player, Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); - } - } + if (aPlayer.getArenaTeam() != null && aPlayer.getArenaClass() == null) { + final String autoClass = + arena.getArenaConfig().getBoolean(CFG.USES_PLAYERCLASSES) ? + arena.getClass(player.getName()) != null ? player.getName() : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS) + : arena.getArenaConfig().getString(CFG.READY_AUTOCLASS); + + if (autoClass != null && !"none".equals(autoClass) && arena.getClass(autoClass) != null) { + arena.chooseClass(player, null, autoClass); + } + if (autoClass == null) { + arena.msg(player, Language.parse(arena, MSG.ERROR_CLASS_NOT_FOUND, "autoClass")); } } - }, 2); + } } @Override From e7e974c6190b22d72b03ca7689936c9c2053359e Mon Sep 17 00:00:00 2001 From: Eredrim Date: Mon, 20 Apr 2020 19:44:21 +0200 Subject: [PATCH 040/115] v1.15 - update maven dependency and pass to java 8 --- lang/lang_ru.yml | 828 +++++++++--------- pom.xml | 18 +- .../slipcor/pvparena/commands/PAA_Set.java | 15 +- src/net/slipcor/pvparena/core/ColorUtils.java | 31 +- src/net/slipcor/pvparena/core/Config.java | 39 +- .../pvparena/goals/GoalBlockDestroy.java | 5 +- .../pvparena/goals/GoalCheckPoints.java | 5 +- .../pvparena/goals/GoalDomination.java | 5 +- src/net/slipcor/pvparena/goals/GoalFlags.java | 5 +- .../slipcor/pvparena/goals/GoalInfect.java | 4 +- .../pvparena/goals/GoalLiberation.java | 4 +- .../pvparena/goals/GoalPhysicalFlags.java | 5 +- .../pvparena/goals/GoalPlayerLives.java | 4 +- src/net/slipcor/pvparena/goals/GoalTank.java | 4 +- .../slipcor/pvparena/goals/GoalTeamLives.java | 4 +- 15 files changed, 488 insertions(+), 488 deletions(-) diff --git a/lang/lang_ru.yml b/lang/lang_ru.yml index c46510f6d..1d3f3cc12 100644 --- a/lang/lang_ru.yml +++ b/lang/lang_ru.yml @@ -1,526 +1,526 @@ nulang: announce: - arena: ! /pa %1% ! + arena: Игра началась! Введите /pa %1% чтобы присоединиться! arena: create: - done: '%1%' ! + done: Арена '%1%' создана! disable: - done: ! + done: Арена выключена! edit: - disabled: ' : %1%' - enabled: ' : %1%' + disabled: 'Режим редактирование выключен: %1%' + enabled: 'Режим редактирования включён: %1%' enable: - done: ! - arenalist: ' : &a%1%&r' - regionshapeunknown: ' ''%1%'' . : http://goo.gl/IfLOh' + done: Арена включена! + arenalist: 'Список карт: &a%1%&r' + regionshapeunknown: 'Тип региона ''%1%'' неизвестен. проконсультируйтесь на: http://goo.gl/IfLOh' reload: - done: ! + done: Арена перезагружена! remove: - done: ' : &e%1%&r' - startingin: - . %1%! + done: 'Арена удалена: &e%1%&r' + startingin: Достаточное кол-во игроков готово. Начало через %1%! start: - done: ! + done: Игра принудительно начата! stop: - done: ! + done: Игра принудительно выключена! autosetup: - automanual: &a%1%&r &a%2%&r? - automatic: - manual: - modeselected: '&a%1%&r !' - welcome: ' PVP Arena! + automanual: Хотите ли вы воспользоваться мастером установки для &a%1%&r или &a%2%&r? + automatic: автоматически + manual: инструкция + modeselected: '&a%1%&r тип игры выбран!' + welcome: 'Добро пожаловать в мастер установки PVP Arena! - . !' + Пожалуйста введите ответы в чат. Никаких комманд не нужно!' blacklist: added: Added &a%1%&r to &e%2%&r blacklist! - allcleared: ! - cleared: ׸ &e%1%&r ! - help: ': blacklist clear | blacklist [type] [clear|add|remove] [id]' - removed: &a%1%&r &e%2%&r ! - show: '׸ &e%1%&r:' + allcleared: Все чёрные списки очищены! + cleared: Чёрный лист &e%1%&r очищен! + help: 'Используйте: blacklist clear | blacklist [type] [clear|add|remove] [id]' + removed: Удаление &a%1%&r из &e%2%&r чёрного списка! + show: 'Чёрный лист &e%1%&r:' check: - done: ! ! + done: Проверка завершена! Ошибок нет! class: preview: You are now previewing the class %1% - removed: ' : %1%' - saved: ' : %1%' - selected: &e%1%&e + removed: 'Класс удалён: %1%' + saved: 'Класс сохранён: %1%' + selected: Вы выбрали класс &e%1%&e deathcause: - BLOCK_EXPLOSION: - CONTACT: - CUSTOM: - DROWNING: - ENTITY_EXPLOSION: - FALL: - FIRE_TICK: - FIRE: - LAVA: - LIGHTNING: - MAGIC: - POISON: - PROJECTILE: - STARVATION: + BLOCK_EXPLOSION: взрыва + CONTACT: кактуса + CUSTOM: Херобрина + DROWNING: вода + ENTITY_EXPLOSION: взрыва + FALL: гравитации + FIRE_TICK: огня + FIRE: огня + LAVA: лавы + LIGHTNING: молнии + MAGIC: магических сил + POISON: зелья + PROJECTILE: того чего он не видел + STARVATION: голода SUFFOCATION: lack of air - SUICIDE: - VOID: - CREEPER: - SKELETON: - SPIDER: - GIANT: - ZOMBIE: - SLIME: - GHAST: - PIG_ZOMBIE: - - ENDERMAN: - CAVE_SPIDER: - SILVERFISH: - BLAZE: - MAGMA_CUBE: - ENDER_DRAGON: - - WITHER: - WITCH: - WOLF: - IRON_GOLEM: - SPLASH_POTION: + SUICIDE: себя + VOID: пустоты + CREEPER: крипера + SKELETON: скелета + SPIDER: паука + GIANT: гиганта + ZOMBIE: зомби + SLIME: слизня + GHAST: гаста + PIG_ZOMBIE: свино-зомби + ENDERMAN: эндермена + CAVE_SPIDER: пещерного паука + SILVERFISH: чешуйницы + BLAZE: блейза + MAGMA_CUBE: огненного слизня + ENDER_DRAGON: эндер-дракона + WITHER: визера + WITCH: ведьмы + WOLF: волка + IRON_GOLEM: железного голема + SPLASH_POTION: взрывного зелья error: arena: - alreadyplaying: &a%1%&r - arenaexists: ! - arenanotexists: ' : %1%' - arenaconfig: ' : %1%' - argumenttype: '&c :&r &e%1%&r &a%2%&r' - argument: '&c :&r %1% - : &a%2%&r' + alreadyplaying: Вы уже присоеденены к &a%1%&r + arenaexists: Арена с таким именем уже существует! + arenanotexists: 'Арены с таким именем не существует: %1%' + arenaconfig: 'Ошибка при загрузке конфигурации арены: %1%' + argumenttype: '&cНеверный аргумент:&r &e%1%&r нет нужного &a%2%&r' + argument: '&cАргумент неверен:&r %1% - возможные аргументы: &a%2%&r' autosetup: - running: ' ! : %1%' + running: 'Здесь уже запущен мастер установки! Игрок: %1%' blacklist: - disallowed: %1% ! ! - unknownsubcommand: ' . : &a%1%&r' - unknowntype: ' . : &e%1%&r' + disallowed: Вы не можете %1% это! В чёрном списке! + unknownsubcommand: 'Неизвестная подкоманда. Возможные команды: &a%1%&r' + unknowntype: 'Неизвестный тип. Возможные типы: &e%1%&r' class: - full: &a%1%&r ! - notenoughexp: - , &a%1%&r! - notfound: ' : &a%1%&r' - cmdblocked: '&c : %1%' - invalidcmd: (%1%) - unknowncmd: - arenadisabled: , ! - error: '&c: %1%' - fightinprogress: ! + full: Класс &a%1%&r переполнен! + notenoughexp: У вас нет достаточного кол-ва опыта, чтобы выбрать &a%1%&r! + notfound: 'Класс не найден: &a%1%&r' + cmdblocked: '&cКомманда заблокирована: %1%' + invalidcmd: Неверная команда (%1%) + unknowncmd: Неизвестная команда + arenadisabled: Игра выключена, пожалуйста попробуйте позже! + error: '&cОшибка: %1%' + fightinprogress: Игра уже идёт! goal: - legacyunknown: ' &a%1%&r ! : &a/pa - [_] goal [_]' - goalnotfound: ' &a%1%&r . : &a%2%&r' - install: &a%1%&r - invalid_argument_count: '&c - &r (%1% %2%)!' - invalidstattype: ' : %1%' - valuenotfound: ' : &a%1%&r!' - invfull: . ! - arenafull: ! - joinrange: , ! - notjoinregion: ! , ! - teamfull: %1% ! - insidevehicle: , ! - errorloungefree: ! "FreeForAll". '[_]lounge' + legacyunknown: 'Наследник цели &a%1%&r неизвестен! Возможно вы хотели добавить цель: &a/pa + [Название_арены] goal [название_цели]' + goalnotfound: 'Цель &a%1%&r неизвестна. Возможные цели: &a%2%&r' + install: Ошибка при установке &a%1%&r + invalid_argument_count: '&cНеверное кол-во аргументов&r (%1% вместо %2%)!' + invalidstattype: 'Неверный тип статистики: %1%' + valuenotfound: 'Неверное значание: &a%1%&r!' + invfull: Ваш инвентарь переполнен. Вы не получили все награды! + arenafull: Арена переполнена! + joinrange: Вы слишком далеко, чтобы присоединиться к арене! + notjoinregion: Вы не находитесь в регионе присоединения! Идите сюда, чтобы присоединиться! + teamfull: команда %1% переполнена! + insidevehicle: Вы не можете присоединиться, пока вы на транспорте! + errorloungefree: Ошибка! Тип арены не "FreeForAll". Используйте '[название_команды]lounge' log: - matnotfound: ' : %1%' - missingspawn: ' : &f%1%' - noarenas: ! - valueneg: ' : &c%1%&r' - nofight: . - nogoal: ! &a/pa [_] [ ] - classperms: &a%1%&r - permjoin: ! - noperm: '&c %1%' - noplayerfound: ! - notinarena: ! - notnumeric: '&c :&r %1%' + matnotfound: 'Неверный материал: %1%' + missingspawn: 'Точка спавна потерена: &f%1%' + noarenas: Арены не найдены! + valueneg: 'Отрицательные значения: &c%1%&r' + nofight: Ни одна из игр не запущена. + nogoal: Вы не добавили цели на арену! &a/pa [Название_арены] цель [название цели] + classperms: У вас нет прав для исользования класса &a%1%&r + permjoin: У вас нет прав для игры на этой арене! + noperm: '&cНет прав для %1%' + noplayerfound: Игрок не найден! + notinarena: Вы не находитесь на арене! + notnumeric: '&cАргумент не является числом:&r %1%' notsameworld: Not in the same world as the arena (%1%)! - noteamfound: ! - onlyplayers: '&c !' - playernotfound: '&c : &f%1%&c!' - positives: ' : &b%1%&r' - potioneffecttypenotfound: ' : &e%1%&r' + noteamfound: Команда не найдена! + onlyplayers: '&cЭто команда может быть использована только игроками!' + playernotfound: '&cИгрок не найден: &f%1%&c!' + positives: 'Положительные значения: &b%1%&r' + potioneffecttypenotfound: 'Эффект зелья не найден: &e%1%&r' ready: - notready0: ! - notready1: ! - notready2: ! - notready3: ! - notready4: ! - notready5: ! - noclass: ! - error: ! %1% + notready0: Последний игрок не готов! + notready1: Вы один на арене! + notready2: Ваша команда одна на арене! + notready3: Команда потеряла игрока! + notready4: Арена потеряла игрока! + notready5: Один игрок не выбрал класс! + noclass: Вы не выбрали класс! + error: Игра не готова! %1% region: - beingcreated: ' : %1%' - flagnotfound: ' &a%1%&r ! : %2%' - notfound: &a%1%&r ! - protectionnotfound: &a%1%&r ! - typenotfound: ' &a%1%&r ! : %2%' - youselect: ! - youselect2: , ! - youselectexit: ! - regionnotbeingcreated: ! - regionnotremoved: . - select2: 2 . + beingcreated: 'Регион уже создан: %1%' + flagnotfound: 'Флаг региона &a%1%&r неизвестен! Возможные значения: %2%' + notfound: Регион &a%1%&r не найден! + protectionnotfound: Защищённый регион &a%1%&r неизвестен! + typenotfound: 'Тип региона &a%1%&r Неизвестен! Возможные значения: %2%' + youselect: Вы уже выбрали регион для этой арены! + youselect2: Введите команду заного, чтобы выйти из режима создания регионов! + youselectexit: Режим создания регионов выключен! + regionnotbeingcreated: Регион не был создан! + regionnotremoved: Регион не был удалён. + select2: Выбирете 2 точки перед сохранением. spawn: - unknown: ' : &a%1%&r' - spawnfree: ! "FreeForAll". 'spawnX' X ! - statsfile: ! - teamnotfound: ' : &a%1%&r' - uninstall: &a%1%&r - unknownmodule: ' : %1%' + unknown: 'Неизвестная точка возрождения: &a%1%&r' + spawnfree: Ошибка! Тип арены "FreeForAll". Используйте 'spawnX' где X цифра или буква! + statsfile: Ошибка при считовании! + teamnotfound: 'Команда не найдена: &a%1%&r' + uninstall: Ошибка при удалении &a%1%&r + unknownmodule: 'Модуль не найден: %1%' whitelist: disallowed: You may not %1% this! (not whitelisted) - unknownsubcommand: ' . : &a%1%&r' - unknowntype: ' . : &e%1%&r' + unknownsubcommand: 'Неизвестная подкоманда. Возможные команды: &a%1%&r' + unknowntype: 'Неизвестный вид. Доступные виды: &e%1%&r' nopermto: - madmin: - create: - disable: - edit: - enable: - nopermjoin: - reload: - remove: - set: - setup: - teleport: - user: PVP Arena + madmin: администрировать + create: создать арену + disable: выключить + edit: редактировать арену + enable: включить + nopermjoin: присоединиться к арене + reload: перезапуск + remove: удалить арену + set: выбрать файл конфигурации + setup: настроить арену + teleport: телепортация на точку возраждения арены + user: использовать PVP Arena fight: - begins: ! - draw: ! ! - killedbyremaining: '%1% %2%! %3% .' - killedbyremainingfrags: '%1% %2%! %3% .' - killedbyremainingteam: '%1% %2%! %3% %4%.' - killedbyremainingteamfrags: '%1% %2%! %3% + begins: Пускай бой начнётся! + draw: Этот матч закончился ничьей! Победителей нет! + killedbyremaining: '%1% был убит %2%! %3% жизней осталось.' + killedbyremainingfrags: '%1% был убит %2%! %3% убийств осталось.' + killedbyremainingteam: '%1% был убит %2%! %3% жизней осталось для %4%.' + killedbyremainingteamfrags: '%1% был убит %2%! %3% убийств осталось до %4%.' - killedby: '%1% %2%!' - playerleft: '%1% !' - forcestop: . + killedby: '%1% был убит %2%!' + playerleft: '%1% вышел из боя!' + forcestop: Вы принудительно остановили игру. gamemode: - free: &afree for all&r &a%1%&r! - team: &ateam&r &a%1%&r! + free: Игровой режим &afree for all&r выставлен для арены &a%1%&r! + team: Игровой режим &ateam&r выставлен для арены &a%1%&r! general: - break: - place: - use: + break: сломать + place: поставить + use: использовать goal: - added: ' : &a%1%&r' - installing: ' : &a/pa install [goalname]&r' - removed: ' : &a%1%&r' + added: 'Цель создана: &a%1%&r' + installing: 'Установите цели командой: &a/pa install [goalname]&r' + removed: 'Цель удалена: &a%1%&r' blockdestroy: - typeset: ' : &e%1%' - setflag: ' : %1%' - tosetflag: ' : %1%' + typeset: 'Тип блока заменён на: &e%1%' + setflag: 'Блок выбран: %1%' + tosetflag: 'Блок для выбора: %1%' dom: - claiming: '&e %1% !' - claimed: '&e %1% !' - score: '&e %1% %2% !' - unclaiming: '&e %1% !' - unclaimingby: '&e %1% %2%!' + claiming: '&eКоманда %1% захватывает флаг!' + claimed: '&eКоманда %1% захватила флаг!' + score: '&eКоманда %1% получает %2% очков за удержание флага!' + unclaiming: '&eФлаг захваченый командой %1% захватывается другой командой!' + unclaimingby: '&eФлаг захваченый командой %1% перезахвачен командой %2%!' infected: - lost: '&6 !' - player: '&c%1% !' - you: '&c !' - won: '&6 !' + lost: '&6Заражённые игроки были убиты!' + player: '&c%1% заражён!' + you: '&cВы заражены!' + won: '&6Заражённые игроки победили в игре!' killreward: - added: ' : &e%1%&f->&a%2%' - removed: ' : &e%1%' + added: 'Награда за убийство добавлена: &e%1%&f->&a%2%' + removed: 'Награда за убийство удалена: &e%1%' liberation: - liberated: %1% ! - setbutton: ' : %1%' - tosetbutton: ' : %1%' + liberated: Команда %1% была освобождена! + setbutton: 'Кнопка выбрана: %1%' + tosetbutton: 'Кнопка для выбора: %1%' physicalflags: - holdflag: , ! + holdflag: Вы захватили флаг, верните его к себе на базу! sabotage: - tntignite: '%1% TNT %2%!' - set: 'TNT : %1%' - toset: 'TNT : %1%' - youtnt: TNT !' + tntignite: '%1% подожгли TNT команды %2%!' + set: 'TNT выбрана: %1%' + toset: 'TNT для выбора: %1%' + youtnt: У вас есть TNT для сабботажа!' tank: - tankdown: ! - tankmode: ! %1%, ! - tankwon: ! %1%! + tankdown: Танк убит! + tankmode: Режим танка! Все должны убить %1%, он танк! + tankwon: Танк победил! Поздравляем %1%! pillars: msg: - block_broken: '[%1%] %2% !' - lower: '[%1%] %2% !' - block_placed: '[%1%] %2% !' - higher: '[%1%] %2% !' - claimed: '[%1%] %2% !' - unclaimed: '[%1%] %2% !' - score: '%1% %2% ' + block_broken: '[%1%] %2% сломал блок!' + lower: '[%1%] %2% укоротил колонну!' + block_placed: '[%1%] %2% поставил блок!' + higher: '[%1%] %2% удлинил колону!' + claimed: '[%1%] %2% захватил колонну!' + unclaimed: '[%1%] %2% перехватил колонну!' + score: '%1% получают %2% очков' help: - head: '&e--- &aPVP Arena &e %1% &e---' - admin: '&c%1% - ' - setup: '&e%1% - ' - custom: '&e%1% - ' - game: '&a%1% - ' - info: '&9%1% - ' + head: '&e--- &aPVP Arena помощь&e %1% &e---' + admin: '&c%1% - помощь администрации' + setup: '&e%1% - помощь в создании' + custom: '&e%1% - помощь в настройке' + game: '&a%1% - помощь в игре' + info: '&9%1% - помощь в получении информации' import: - done: &e%1%&r! + done: Удачный импорт арены &e%1%&r! info: - classes: ': &a%1%&r' - goal_active: ': &a%1%&r' - goal_inactive: ': &b%1%&r &7== ==' - head_headlin: ' : &a%1%&r | [&a%2%&r]' - head_teams: ': &a%1%&r' - mod_active: ': &a%1%&r' - mod_inactive: ': &b%1%&r &7== ==' - owner: ': &a%1%&r' - regions: ': &a%1%&r' + classes: 'классы: &a%1%&r' + goal_active: 'Цель: &a%1%&r' + goal_inactive: 'Цель: &b%1%&r &7== неактивная ==' + head_headlin: 'Информация об арене: &a%1%&r | [&a%2%&r]' + head_teams: 'Команды: &a%1%&r' + mod_active: 'Модули: &a%1%&r' + mod_inactive: 'Модули: &b%1%&r &7== неактивная ==' + owner: 'Владельцы: &a%1%&r' + regions: 'Регионы: &a%1%&r' section: '----- &a%1%&r -----' install: - installed: ': &a%1%&r' + installed: 'установлены: &a%1%&r' list: - arenas: ' : %1%' - dead: '̸: %1%' - fighting: ': %1%' - lost: ': %1%' - lounge: ': %1%' - 'null': ': %1%' - players: ': %1%' - team: ' %1%: %2%' - ready: ': %1%' - warm: ': %1%' - watching: ': %1%' + arenas: 'Доступные арены: %1%' + dead: 'Мёртвые: %1%' + fighting: 'Сражающиеся: %1%' + lost: 'Потерянные: %1%' + lounge: 'Лобби: %1%' + 'null': 'Зависшие: %1%' + players: 'Игроки: %1%' + team: 'Команды %1%: %2%' + ready: 'Готовы: %1%' + warm: 'Ожидающие: %1%' + watching: 'Зрители: %1%' log: - plugindisabled: ( %1%) - pluginenabled: ( %1%) - trickerdisabled: . ? - trackingenabled: ' . : false .' - updatedisabled: . dev.bukkit . - updateenabled: ... + plugindisabled: выключен (версия %1%) + pluginenabled: включён (версия %1%) + trickerdisabled: Диагностика плагина выключена. Увидимся позже? + trackingenabled: 'Диагностика плагина включена. Выбор диагностики: false в главном файле конфигурации для выключения.' + updatedisabled: Обновление выключено. Пожалуйста проверьте dev.bukkit для обновления. + updateenabled: Проверка на наличие обновлений... warning: '%1%' messages: - toArena: ! - toPublic: ! - toTeam: ! - noplayer: PVP arena. + toArena: Теперь вы говорите внутри арены! + toPublic: Теперь вы говорите со всеми! + toTeam: Теперь вы разговариваете с вашей командой! + noplayer: Нет игроков в PVP arena. notice: - awarded: %1% - nodropitem: ! ! - noteleport: '/pa leave' ! - notice: ': %1%' - playerawarded: '%1% %2%' - remove: '&c &a%1%&c. ? - !&f , ''safeadmin'' + awarded: Вы были награждены %1% + nodropitem: Не так быстро! Не читерить! + noteleport: Пожалуйста используйте '/pa leave' для выхода из игры! + notice: 'Внимание: %1%' + playerawarded: '%1% был награждён %2%' + remove: '&cЭто навсегда удалит вашу арену &a%1%&c. Вы уверены? Тогда + введите команду ещё раз!&f Чтобы выключить это сообщение, посмотрите ''safeadmin'' в вашем config.yml' - waitingequal: ! - waitingforarena: , ! - welcomespec: ! - welcomespec2: /pa bet [] [] ! - youdeath: . ;)! - youescaped: . ;)! - youleft: ! - younocamp: . ! - playerhaswon: '%1% !' - playerready: '%1%&e !' - notreadyplayers: - players: + waitingequal: Ждём пока в командах будет минимальное число игроков! + waitingforarena: Ожидайте, пока игра завершится! + welcomespec: Добро пожаловать в зал зрителей! + welcomespec2: /pa bet [имя] [цена] сделать ставку на игрока или команду! + youdeath: Вы вошли в регион смерти. Пока ;)! + youescaped: Вы ушли с поля боя. Пока ;)! + youleft: Вы вышли из игры! + younocamp: Вы в некемперском регионе. Двигайтесь! + playerhaswon: '%1% победитель!' + playerready: '%1%&e готов!' + notreadyplayers: Игроки не готовы + players: Игроки ready: - list: ': %1%' - done: ! + list: 'Игроки: %1%' + done: Вы уже готовы! region: flag: - added: ' : &a%1%&r' - removed: ' : &a%1%&r' - height: ' : &a%1%&r' - pos1: . - pos2: . - protection_added: ' : &a%1%&r' - protection_removed: ' : &a%1%&r' - radius: ' : &a%1%&r' - removed: ' : %1%' - saved: . - select: 2 , ! - setting: . - typeset: ' : &e%1%' - youselect: &a%1%&r! + added: 'Флаг региона добавлен: &a%1%&r' + removed: 'Флаг региона удалён: &a%1%&r' + height: 'Высота региона установлена на: &a%1%&r' + pos1: Первая точка выбрана. + pos2: Вторая точка выбрана. + protection_added: 'Защита региона создана: &a%1%&r' + protection_removed: 'Защита региона удалена: &a%1%&r' + radius: 'Радиус региона: &a%1%&r' + removed: 'Регион удалён: %1%' + saved: Регион сохранён. + select: Выбирете 2 точки палочкой, сначала левой кнопкой мышки и потом правой! + setting: Найстройка региона включена. + typeset: 'Тип региона выбран: &e%1%' + youselect: Теперь вы выбираете регион для карты &a%1%&r! regions: - flags: ' : &a%1%&r' - head: '--- &a &r [&e%1%&r]---' - listhead: '--- &a &r [&e%1%&r]---' + flags: 'Флаги региона: &a%1%&r' + head: '--- &aРегион арены&r [&e%1%&r]---' + listhead: '--- &aРегионы арены&r [&e%1%&r]---' listvalue: '&a%1%&r: %2%, %3%' - protections: ' : &a%1%&r' - shape: ' : &a%1%&r' - type: ' : &a%1%&r' - reloaded: ! + protections: 'Защиты региона: &a%1%&r' + shape: 'Форма региона: &a%1%&r' + type: 'Тип региона: &a%1%&r' + reloaded: Конфигурация региона! round: - display: ' #%1%/%2%' - added: ' : &e%1%' - removed: ' : &e%1%' + display: 'Раунд #%1%/%2%' + added: 'Добавлена цель раунда: &e%1%' + removed: 'Удалена цель раунда: &e%1%' set: done: '&a%1%&r set to &e%2%&r!' - help: /pa {arenaname} set [] - unknown: ' : &e%1%&r!' + help: Используйте /pa {arenaname} set [страница] для получение инструкций + unknown: 'Неизестная страница: &e%1%&r!' setowner: - done: '&a%1%&r &a%2%&r!' + done: '&a%1%&r теперь владелец арены &a%2%&r!' spawn: - freelounge: - teamlounge: ' : %1%' - notset: ' : &a%1%&r' - removed: ' : &a%1%&r' - set: ' : &a%1%&r' - setdone: ' : &a%1%&r' - setstart: ' : &a%1%&r' + freelounge: Лобби выставлено + teamlounge: 'Лобби выставлено: %1%' + notset: 'Точка возраждения не указана: &a%1%&r' + removed: 'Точка возраждения удалена: &a%1%&r' + set: 'Точка возраждения указана: &a%1%&r' + setdone: 'Точка возраждения удачно выставлена: &a%1%&r' + setstart: 'Настройка точки возраждения начата: &a%1%&r' stats: - filedone: ! - head: %1% (%2%) - typenotfound: ' ! : &e%1%&r' + filedone: Файл статичтики загружен! + head: Статистика ТОП %1% (%2%) + typenotfound: 'Тип статистики не найден! Доступные значения: &e%1%&r' stattype: - DAMAGE: - DAMAGETAKE: - DEATHS: - KILLS: - LOSSES: - MAXDAMAGE: - MAXDAMAGETAKE: - 'NULL': - WINS: + DAMAGE: полный наносимый урон + DAMAGETAKE: полный забираемый урон + DEATHS: смерти + KILLS: убийства + LOSSES: матчей проиграно + MAXDAMAGE: максимальный урон + MAXDAMAGETAKE: максимальный нанесённый урон + 'NULL': имя игрока + WINS: матчей выиграно team: - haswon: '%1% !' - ready: '%1% !' + haswon: '%1% Чемпионы!' + ready: '%1% готовы!' teams: - list: ' : %1%' - add: ' : %1%' - set: ' : %1%' - remove: ' : %1%' + list: 'Доступные команды: %1%' + add: 'Команда создана: %1%' + set: 'Команда выбрана: %1%' + remove: 'Команда удалена: %1%' time: - minutes: - seconds: + minutes: минут + seconds: секунд timer: - countdowninterrupt: interrupted! ! - ending: %1%! - resetting: %1%! - starting: %1%! + countdowninterrupt: Таймер interrupted! Ударьте железный блок для готовности! + ending: Матч закончится через %1%! + resetting: Арена будет перезапущена через %1%! + starting: Начало через %1%! warmingup: Warming up... %1%! - pvpactivating: %1%! - walls: %1%! + pvpactivating: ПвП будет включен через %1%! + walls: Стены будут убраны через %1%! uninstall: - done: ': &a%1%&r' + done: 'Удалено: &a%1%&r' whitelist: - added: &a%1%&r &e%2%&r ! - allcleared: ! - cleared: &e%1%&r ! - help: ': blacklist clear | blacklist [type] [clear|add|remove] [id]' + added: Добавление &a%1%&r в &e%2%&r вайтлист! + allcleared: Все вайтлисты очищены! + cleared: Вайтлист &e%1%&r очищен! + help: 'Используйте: blacklist clear | blacklist [type] [clear|add|remove] [id]' removed: Removed &a%1%&r from &e%2%&r whitelist! show: 'Whitelist &e%1%&r:' mod: aftermatch: - aftermatch: AfterMatch ! - startingin: AfterMatch %1%! - spawnnotset: 'after' ! + aftermatch: AfterMatch начинается! + startingin: AfterMatch через %1%! + spawnnotset: Точка возраждения 'after' не установлена! announcements: - ignoreon: ! - ignoreoff: ! + ignoreon: Теперь вы игнорируете оповещения! + ignoreoff: Теперь вы получаете оповещения! arenaboards: - createarenaboard: - arenaboarddestroyed: ! - boardexists: !' - sortingby: %1% + createarenaboard: создать Границу Арены + arenaboarddestroyed: Граница арены уничтожена! + boardexists: Граница арены с таким именем уже существует!' + sortingby: Граница арены теперь сортируется через %1% autovote: - arenarunning: ' : %1%' - autojoin: ! - playervoted: '%2% %1%!' - youvoted: %1%! + arenarunning: 'Игра запущена: %1%' + autojoin: Авто присоединение к игре началось! + playervoted: '%2% проголосовал за %1%!' + youvoted: Вы проголосовали за %1%! duel: - accepted: '%1% &e ! .' - announce: '%1% &e ! &f/pa %2% accept.' - starting: ! + accepted: '%1% &eсогласился на дуель! Дуедь начинается.' + announce: '%1% &eвызывает вас на дуель! Принять вызов &f/pa %2% accept.' + starting: Дуель начинается! fixinventorylos: - gamemode: ! - invenory: ! + gamemode: Смена игрового режима перед присоединением! + invenory: Очистка инвентаря перед присоединением! latelounge: - llannounce: %1% ! , %2%. /pa %1% - llposition: %1%! - llrejoin: , . , ! - llwait: , ! + llannounce: Игра на карте %1% начинается! Игроков,которые хотят начат играть %2%. Присоединиться /pa %1% + llposition: Ваше место в очереди %1%! + llrejoin: Проверка готовности говорит,что вы не смогли подключится к игре. Переподсоединитесь, когда сможете! + llwait: Игра скоро начнётся, пожалуйста подождите! playerfinder: - near: ' %1% !' - point: ! + near: 'Ближайщий игрок от вас в %1% блоках!' + point: Компас указывает позицию ближайшего игрока! powerups: - invalidpowerupeffect: ' : %1%' - puplayer: '%1% %2%!' - puserver: ! + invalidpowerupeffect: 'Неверный эффект повышения: %1%' + puplayer: '%1% достиг повышения %2%!' + puserver: Понижение! skins: - dc: DisguiseCraft! - md: MobDisguise! - nomod: , ! - showclass: &e%1%&r &a%2% - showteam: %1% %2% + dc: Подключение в DisguiseCraft! + md: Подключение в MobDisguise! + nomod: Не найден плагин превращений, модуль скинов выключен! + showclass: Класс &e%1%&r будет превращён в &a%2% + showteam: Команда %1% будет превращёна в %2% specialjoin: - done: - %1% - start: ! - stop: ! + done: Блок готовности выбран тут - %1% + start: Выбор блока готовности! + stop: Отмена нажатия на блок готовности! startfreeze: - announce: %1% ! + announce: Игра начнётся через %1% секунд! tempperms: - noperms: , . - head: ' &e%1%&r:' - added: &e%1%&r &a%2%&r - removed: &e%1%&r &a%2%&r + noperms: Плагин прав не найден, по умалчанию доступно оперторам. + head: 'Временные права для &e%1%&r:' + added: Временные права &e%1%&r сделаны для &a%2%&r + removed: Временные права &e%1%&r удалены у &a%2%&r vault: 'on': <3 eConomy 'off': net.slipcor pvparena - 1.14.1-SNAPSHOT + 1.15.0-SNAPSHOT PVP Arena + https://github.com/Eredrim/pvparena + UTF-8 @@ -38,12 +40,6 @@ - http://pa.slipcor.net - - jenkins - https://ci2.craftyn.com - - clean package install pvparena-${project.version}${buildVersion} @@ -65,17 +61,17 @@ org.apache.maven.plugins maven-compiler-plugin - 2.3.2 + 3.8.1 - 1.7 - 1.7 + 8 + 8 UTF-8 org.apache.maven.plugins maven-jar-plugin - 2.3.2 + 3.2.0 org.apache.maven.plugins diff --git a/src/net/slipcor/pvparena/commands/PAA_Set.java b/src/net/slipcor/pvparena/commands/PAA_Set.java index 2d3b26541..bf4fdd49d 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Set.java +++ b/src/net/slipcor/pvparena/commands/PAA_Set.java @@ -153,17 +153,15 @@ private void set(final CommandSender player, final Arena arena, final String nod Language.parse(arena, MSG.SET_DONE, node, String.valueOf(dValue))); } else if ("tp".equals(type)) { - if (!"exit".equals(value) && !"old".equals(value) - && !"spectator".equals(value)) { + if (!"exit".equals(value) && !"old".equals(value) && !"spectator".equals(value)) { arena.msg(player, Language.parse(arena, MSG.ERROR_ARGUMENT_TYPE, value, "tp (exit|old|spectator|...)")); return; } - arena.getArenaConfig().setManually(node, String.valueOf(value)); + arena.getArenaConfig().setManually(node, value); arena.msg( player, - Language.parse(arena, MSG.SET_DONE, node, - String.valueOf(value))); + Language.parse(arena, MSG.SET_DONE, node, value)); } else if ("material".equals(type)) { if ("hand".equals(value)) { if (player instanceof Player) { @@ -181,13 +179,10 @@ private void set(final CommandSender player, final Arena arena, final String nod } try { - final Material mat = Material.valueOf(value); + final Material mat = Material.valueOf(value.toUpperCase()); if (mat != Material.AIR) { arena.getArenaConfig().setManually(node, mat.name()); - arena.msg( - player, - Language.parse(arena, MSG.SET_DONE, node, - String.valueOf(mat.name()))); + arena.msg(player, Language.parse(arena, MSG.SET_DONE, node, mat.name())); } arena.getArenaConfig().save(); diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java index f2f41887c..83a506ab0 100644 --- a/src/net/slipcor/pvparena/core/ColorUtils.java +++ b/src/net/slipcor/pvparena/core/ColorUtils.java @@ -6,6 +6,8 @@ import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static net.slipcor.pvparena.core.StringParser.joinArray; @@ -83,8 +85,7 @@ following colors are the sames (ignore): WHITE, YELLOW, BLACK * @return true if material can be colored */ public static boolean isColorableMaterial(Material type) { - return type.name().endsWith("_WOOL") || type.name().endsWith("_CONCRETE") || - type.name().endsWith("_STAINED_GLASS"); + return getColorableSuffixes().contains(getMaterialSuffix(type)); } /** @@ -101,15 +102,21 @@ public static Material getColoredMaterial(DyeColor dyeColor, Material typeMateri } public static boolean isSubType(Material type, Material check) { - if (type.name().endsWith("_WOOL") && check.name().endsWith("_WOOL")) { - return true; - } - if (type.name().endsWith("_CONCRETE") && check.name().endsWith("_CONCRETE")) { - return true; - } - if (type.name().endsWith("_STAINED_GLASS") && check.name().endsWith("_STAINED_GLASS")) { - return true; - } - return false; + return isColorableMaterial(type) && getMaterialSuffix(type).equals(getMaterialSuffix(check)); + } + + private static String getMaterialSuffix(Material material) { + return material.name().contains("_") ? material.name().split("_", 2)[1] : ""; + } + + /** + * Get the list of all colorable blocks + */ + private static List getColorableSuffixes() { + return Stream.of(Material.values()) + .filter(m -> m.name().startsWith("MAGENTA_")) + .filter(Material::isBlock) + .map(ColorUtils::getMaterialSuffix) + .collect(Collectors.toList()); } } diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index 117453acb..75b992920 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -77,17 +77,17 @@ public enum CFG { GENERAL_SMARTSPAWN("general.smartspawn", false, null), GENERAL_TIME("general.time", -1, null), GENERAL_TYPE("general.type", "none", null), - GENERAL_WAND("general.wand", Material.STICK.toString(), null), + GENERAL_WAND("general.wand", Material.STICK, null), GOAL_ADDLIVESPERPLAYER("goal.livesPerPlayer", false, null), - ITEMS_EXCLUDEFROMDROPS("items.excludeFromDrops", new ItemStack[0], true, null), - ITEMS_KEEPONRESPAWN("items.keepOnRespawn", new ItemStack[0], true, null), + ITEMS_EXCLUDEFROMDROPS("items.excludeFromDrops", new ItemStack[0], null), + ITEMS_KEEPONRESPAWN("items.keepOnRespawn", new ItemStack[0], null), ITEMS_KEEPALLONRESPAWN("items.keepAllOnRespawn", false, null), ITEMS_MINPLAYERS("items.minplayers", 2, null), ITEMS_RANDOM("items.random", true, null), - ITEMS_REWARDS("items.rewards", new ItemStack[0], true, null), - ITEMS_TAKEOUTOFGAME("items.takeOutOfGame", new ItemStack[0], true, null), + ITEMS_REWARDS("items.rewards", new ItemStack[0], null), + ITEMS_TAKEOUTOFGAME("items.takeOutOfGame", new ItemStack[0], null), JOIN_RANGE("join.range", 0, null), JOIN_FORCE("join.forceregionjoin", false, null), @@ -128,7 +128,7 @@ public enum CFG { PLAYER_HEALTH("player.health", -1, null), PLAYER_HEALFORKILL("player.healforkill", false, null), PLAYER_HUNGER("player.hunger", true, null), - PLAYER_ITEMSONKILL("player.itemsonkill", new ItemStack[0], true, null), + PLAYER_ITEMSONKILL("player.itemsonkill", new ItemStack[0], null), PLAYER_MAYCHANGEARMOR("player.mayChangeArmor", true, null), PLAYER_MAXHEALTH("player.maxhealth", -1, null), PLAYER_PREVENTDEATH("player.preventDeath", true, null), @@ -144,7 +144,7 @@ public enum CFG { PROTECT_SPAWN("protection.spawn", 0, null), READY_AUTOCLASS("ready.autoClass", "none", null), - READY_BLOCK("ready.block", Material.IRON_BLOCK.toString(), null), + READY_BLOCK("ready.block", Material.IRON_BLOCK, null), READY_CHECKEACHPLAYER("ready.checkEachPlayer", false, null), READY_CHECKEACHTEAM("ready.checkEachTeam", true, null), READY_ENFORCECOUNTDOWN("ready.enforceCountdown", false, null), @@ -194,7 +194,7 @@ public enum CFG { GOAL_BEACONS_TICKINTERVAL("goal.beacons.tickinterval", 60, "Beacons"), GOAL_BEACONS_TICKREWARD("goal.beacons.tickreward", 1, "Beacons"), - GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", Material.IRON_BLOCK.toString(), "BlockDestroy"), + GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", Material.IRON_BLOCK, "BlockDestroy"), GOAL_BLOCKDESTROY_LIVES("goal.blockdestroy.bdlives", 1, "BlockDestroy"), GOAL_CHECKPOINTS_CLAIMRANGE("goal.checkpoints.cpclaimrange", 5, "CheckPoints"), @@ -210,7 +210,7 @@ public enum CFG { GOAL_DOM_TICKINTERVAL("goal.dom.tickinterval", 60, "Domination"), GOAL_DOM_TICKREWARD("goal.dom.tickreward", 1, "Domination"), - GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", Material.WHITE_WOOL.toString(), "Flags"), + GOAL_FLAGS_FLAGTYPE("goal.flags.flagType", Material.WHITE_WOOL, "Flags"), GOAL_FLAGS_LIVES("goal.flags.flives", 3, "Flags"), GOAL_FLAGS_MUSTBESAFE("goal.flags.mustBeSafe", true, "Flags"), GOAL_FLAGS_WOOLFLAGHEAD("goal.flags.woolFlagHead", true, "Flags"), @@ -231,7 +231,7 @@ public enum CFG { GOAL_PLIVES_LIVES("goal.playerlives.plives", 3, "PlayerLives"), GOAL_TANK_LIVES("goal.tank.tlives", 1, "Tank"), GOAL_TDC_LIVES("goal.teamdc.tdclives", 10, "TeamDeathConfirm"), - GOAL_TDC_ITEM("goal.teamdc.tdcitem", Material.WHITE_WOOL.toString(), "TeamDeathConfirm"), + GOAL_TDC_ITEM("goal.teamdc.tdcitem", Material.WHITE_WOOL, "TeamDeathConfirm"), GOAL_TDM_LIVES("goal.teamdm.tdlives", 10, "TeamDeathMatch"), GOAL_TDM_SUICIDESCORE("goal.teamdm.suicideScore", false, "TeamDeathMatch"), GOAL_TLIVES_LIVES("goal.teamlives.tlives", 10, "TeamLives"), @@ -329,13 +329,13 @@ public enum CFG { new ItemStack(Material.PINK_WOOL, 1), new ItemStack(Material.PURPLE_WOOL, 1), new ItemStack(Material.YELLOW_WOOL, 1), - new ItemStack(Material.WHITE_WOOL, 1)}, true, "BlockDissolve"), + new ItemStack(Material.WHITE_WOOL, 1)}, "BlockDissolve"), MODULES_BLOCKDISSOLVE_STARTSECONDS("modules.blockdissolve.startseconds", 10, "BlockDissolve"), MODULES_BLOCKDISSOLVE_TICKS("modules.blockdissolve.ticks", 40, "BlockDissolve"), MODULES_CHESTFILLER_CHESTLOCATION("modules.chestfiller.chestlocation", "none", "ChestFiller"), MODULES_CHESTFILLER_CLEAR("modules.chestfiller.clear", false, "ChestFiller"), - MODULES_CHESTFILLER_ITEMS("modules.chestfiller.cfitems", new ItemStack[]{new ItemStack(Material.STONE)}, true, "ChestFiller"), + MODULES_CHESTFILLER_ITEMS("modules.chestfiller.cfitems", new ItemStack[]{new ItemStack(Material.STONE)}, "ChestFiller"), MODULES_CHESTFILLER_MAXITEMS("modules.chestfiller.cfmaxitems", 5, "ChestFiller"), MODULES_CHESTFILLER_MINITEMS("modules.chestfiller.cfminitems", 0, "ChestFiller"), @@ -348,7 +348,7 @@ public enum CFG { MODULES_FIXINVENTORYLOSS_INVENTORY("modules.fixinventoryloss.inventory", false, "FixInventoryLoss"), MODULES_ITEMS_INTERVAL("modules.items.interval", 0, "Items"), - MODULES_ITEMS_ITEMS("modules.items.items", new ItemStack[0], true, "Items"), + MODULES_ITEMS_ITEMS("modules.items.items", new ItemStack[0], "Items"), MODULES_RESPAWNRELAY_INTERVAL("modules.respawnrelay.respawnseconds", 10, "RespawnRelay"), MODULES_RESPAWNRELAY_CHOOSESPAWN("modules.respawnrelay.choosespawn", false, "RespawnRelay"), @@ -411,7 +411,7 @@ public enum CFG { MODULES_VAULT_REWARD_TRIGGER("modules.vault.reward.trigger", 0.0d, "Vault"), MODULES_VAULT_REWARD_WIN("modules.vault.reward.playerWin", 0.0d, "Vault"), - MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", Material.SAND.toString(), "Walls"), + MODULES_WALLS_MATERIAL("modules.walls.wallmaterial", Material.SAND, "Walls"), MODULES_WALLS_SCOREBOARDCOUNTDOWN("modules.walls.scoreboardcountdown", false, "Walls"), MODULES_WALLS_SECONDS("modules.walls.wallseconds", 300, "Walls"), @@ -463,10 +463,17 @@ public static CFG getByNode(final String node) { module = source; } - CFG(final String node, final ItemStack[] value, final boolean multiple, final String source) { + CFG(final String node, final ItemStack[] value, final String source) { this.node = node; this.value = getSerializableItemStacks(value); - type = multiple ? "items" : "material"; + type = "items"; + module = source; + } + + CFG(final String node, final Material value, final String source) { + this.node = node; + this.value = value.name(); + type = "material"; module = source; } diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java index a76f69eb0..596513ec7 100644 --- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java +++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java @@ -374,9 +374,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam() - .getName()) ? getLifeMap().get(aPlayer - .getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalCheckPoints.java b/src/net/slipcor/pvparena/goals/GoalCheckPoints.java index 4bb7a4bcd..2ff7d5334 100644 --- a/src/net/slipcor/pvparena/goals/GoalCheckPoints.java +++ b/src/net/slipcor/pvparena/goals/GoalCheckPoints.java @@ -301,9 +301,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam() - .getName()) ? getLifeMap().get(aPlayer - .getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java index 5f9226c6b..12f3eda32 100644 --- a/src/net/slipcor/pvparena/goals/GoalDomination.java +++ b/src/net/slipcor/pvparena/goals/GoalDomination.java @@ -618,9 +618,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam() - .getName()) ? getLifeMap().get(aPlayer - .getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 50fc67f9c..47cd119b4 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -752,9 +752,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam() - .getName()) ? getLifeMap().get(aPlayer - .getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java index f50a0d14b..03b6b2058 100644 --- a/src/net/slipcor/pvparena/goals/GoalInfect.java +++ b/src/net/slipcor/pvparena/goals/GoalInfect.java @@ -602,8 +602,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getName()) ? getLifeMap().get(aPlayer - .getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalLiberation.java b/src/net/slipcor/pvparena/goals/GoalLiberation.java index a90ffc637..af4608dc7 100644 --- a/src/net/slipcor/pvparena/goals/GoalLiberation.java +++ b/src/net/slipcor/pvparena/goals/GoalLiberation.java @@ -535,8 +535,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getName()) ? getLifeMap().get(aPlayer - .getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java index 9429fe405..091255b11 100644 --- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java @@ -686,9 +686,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam() - .getName()) ? getLifeMap().get(aPlayer - .getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java index ea5717f57..04b9d1512 100644 --- a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java +++ b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java @@ -276,8 +276,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (arena.isFreeForAll()) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getName()) ? getLifeMap().get(aPlayer - .getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getName(), 0)) + ); } else { if (getLifeMap().containsKey(aPlayer.getArenaTeam().getName())) { diff --git a/src/net/slipcor/pvparena/goals/GoalTank.java b/src/net/slipcor/pvparena/goals/GoalTank.java index 9117f1176..ec2b41483 100644 --- a/src/net/slipcor/pvparena/goals/GoalTank.java +++ b/src/net/slipcor/pvparena/goals/GoalTank.java @@ -277,8 +277,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getName()) ? getLifeMap().get(aPlayer - .getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getName(), 0)) + ); } return res; } diff --git a/src/net/slipcor/pvparena/goals/GoalTeamLives.java b/src/net/slipcor/pvparena/goals/GoalTeamLives.java index 331749d37..5ead522dd 100644 --- a/src/net/slipcor/pvparena/goals/GoalTeamLives.java +++ b/src/net/slipcor/pvparena/goals/GoalTeamLives.java @@ -250,8 +250,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().containsKey(aPlayer.getArenaTeam().getName()) ? getLifeMap() - .get(aPlayer.getArenaTeam().getName()) : 0)); + String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + ); } return res; } From 2f41352b952d6cb5363024aa26ae3024404b7fa2 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Mon, 27 Apr 2020 20:30:53 +0200 Subject: [PATCH 041/115] v1.15 - code cleanup --- src/net/slipcor/pvparena/arena/Arena.java | 18 +++--------------- .../slipcor/pvparena/arena/ArenaPlayer.java | 4 ++++ .../slipcor/pvparena/arena/PlayerState.java | 17 ++++++----------- src/net/slipcor/pvparena/core/Debug.java | 2 +- .../pvparena/goals/GoalPlayerLives.java | 6 ++---- .../pvparena/listeners/PlayerListener.java | 9 +++------ .../runnables/InventoryRefillRunnable.java | 4 ++-- 7 files changed, 21 insertions(+), 39 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index f250e2ebd..5dc69a780 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -1535,13 +1535,7 @@ private void resetPlayer(final Player player, final String destination, final bo //noinspection deprecation ArenaModuleManager.resetPlayer(this, player, soft, force); - String sClass = ""; - if (aPlayer.getArenaClass() != null) { - sClass = aPlayer.getArenaClass().getName(); - } - - if (!soft && (!"custom".equalsIgnoreCase(sClass) || - cfg.getBoolean(CFG.GENERAL_CUSTOMRETURNSGEAR))) { + if (!soft && (!aPlayer.hasCustomClass() || cfg.getBoolean(CFG.GENERAL_CUSTOMRETURNSGEAR))) { ArenaPlayer.reloadInventory(this, player, true); } @@ -1712,8 +1706,7 @@ public void unKillPlayer(final Player player, final DamageCause cause, final Ent PlayerState.playersetHealth(player, iHealth); player.setFoodLevel(cfg.getInt(CFG.PLAYER_FOODLEVEL, 20)); player.setSaturation(cfg.getInt(CFG.PLAYER_SATURATION, 20)); - player.setExhaustion((float) cfg.getDouble( - CFG.PLAYER_EXHAUSTION, 0.0)); + player.setExhaustion((float) cfg.getDouble(CFG.PLAYER_EXHAUSTION, 0.0)); player.setVelocity(new Vector()); player.setFallDistance(0); @@ -2069,12 +2062,7 @@ public void tpPlayerToCoordName(final Player player, final String place, final b aPlayer.setTelePass(true); final Location destination = loc.toLocation().add(offset.getX(), offset.getY(), offset.getZ()); if(runAsync) { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { - @Override - public void run() { - teleportPlayer(place, aPlayer, destination); - } - }, 2); + Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> teleportPlayer(place, aPlayer, destination), 2); } else { this.teleportPlayer(place, aPlayer, destination); } diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java index 03a4c7a39..037fe7053 100644 --- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java +++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java @@ -615,6 +615,10 @@ public boolean isPublicChatting() { return publicChatting; } + public boolean hasCustomClass() { + return this.getArenaClass() != null && "custom".equalsIgnoreCase(this.getArenaClass().getName()); + } + public void readDump() { debug.i("reading dump: " + name, name); debugPrint(); diff --git a/src/net/slipcor/pvparena/arena/PlayerState.java b/src/net/slipcor/pvparena/arena/PlayerState.java index d9c49a5f5..f9e92494e 100644 --- a/src/net/slipcor/pvparena/arena/PlayerState.java +++ b/src/net/slipcor/pvparena/arena/PlayerState.java @@ -105,7 +105,7 @@ public static void fullReset(final Arena arena, final Player player) { } if (arena.getArenaConfig().getInt(CFG.PLAYER_MAXHEALTH) > 0) { - player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(arena.getArenaConfig().getInt(CFG.PLAYER_MAXHEALTH)); + player.getAttribute(Attribute.GENERIC_MAX_HEALTH).setBaseValue(arena.getArenaConfig().getInt(CFG.PLAYER_MAXHEALTH)); } if (iHealth > player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue()) { @@ -115,12 +115,9 @@ public static void fullReset(final Arena arena, final Player player) { } player.setFireTicks(0); try { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() { - @Override - public void run() { - if (player.getFireTicks() > 0) { - player.setFireTicks(0); - } + Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> { + if (player.getFireTicks() > 0) { + player.setFireTicks(0); } }, 5L); } catch (Exception e) { @@ -129,8 +126,7 @@ public void run() { player.setVelocity(new Vector()); player.setFoodLevel(arena.getArenaConfig().getInt(CFG.PLAYER_FOODLEVEL)); player.setSaturation(arena.getArenaConfig().getInt(CFG.PLAYER_SATURATION)); - player.setExhaustion((float) arena.getArenaConfig().getDouble( - CFG.PLAYER_EXHAUSTION)); + player.setExhaustion((float) arena.getArenaConfig().getDouble(CFG.PLAYER_EXHAUSTION)); player.setLevel(0); player.setExp(0); if (arena.getArenaConfig().getInt(CFG.GENERAL_GAMEMODE) > -1) { @@ -250,8 +246,7 @@ public static void playersetHealth(final Player player, final double value) { final double current = player.getHealth(); final double regain = value - current; - final EntityRegainHealthEvent event = new EntityRegainHealthEvent(player, regain, - RegainReason.CUSTOM); + final EntityRegainHealthEvent event = new EntityRegainHealthEvent(player, regain, RegainReason.CUSTOM); Bukkit.getPluginManager().callEvent(event); } diff --git a/src/net/slipcor/pvparena/core/Debug.java b/src/net/slipcor/pvparena/core/Debug.java index 9924601ef..e9136a088 100644 --- a/src/net/slipcor/pvparena/core/Debug.java +++ b/src/net/slipcor/pvparena/core/Debug.java @@ -13,8 +13,8 @@ import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.*; -import java.util.logging.*; import java.util.logging.Formatter; +import java.util.logging.*; /** diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java index 04b9d1512..42fd79e6d 100644 --- a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java +++ b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java @@ -248,8 +248,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, } final List returned; - if (arena.getArenaConfig().getBoolean( - CFG.PLAYER_DROPSINVENTORY)) { + if (arena.getArenaConfig().getBoolean(CFG.PLAYER_DROPSINVENTORY)) { returned = InventoryManager.drop(player); event.getDrops().clear(); } else { @@ -257,8 +256,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, returned.addAll(event.getDrops()); } - PACheck.handleRespawn(arena, - ArenaPlayer.parsePlayer(player.getName()), returned); + PACheck.handleRespawn(arena, ArenaPlayer.parsePlayer(player.getName()), returned); } } diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index 3bab67edc..ac7392c12 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -381,7 +381,7 @@ public static void finallyKillPlayer(final Arena arena, final Player player, final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); final ArenaTeam team = aPlayer.getArenaTeam(); - final String playerName = team == null ? player.getName() : team.colorizePlayer(player); + final String playerName = (team == null) ? player.getName() : team.colorizePlayer(player); if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { arena.broadcast(Language.parse(arena, MSG.FIGHT_KILLED_BY, @@ -397,14 +397,11 @@ public static void finallyKillPlayer(final Arena arena, final Player player, } } - if (ArenaPlayer.parsePlayer(player.getName()).getArenaClass() == null - || !"custom".equalsIgnoreCase(ArenaPlayer.parsePlayer(player.getName()).getArenaClass() - .getName())) { + if (!aPlayer.hasCustomClass()) { InventoryManager.clearInventory(player); } - arena.removePlayer(player, - arena.getArenaConfig().getString(CFG.TP_DEATH), true, false); + arena.removePlayer(player, arena.getArenaConfig().getString(CFG.TP_DEATH), true, false); aPlayer.setStatus(Status.LOST); aPlayer.addDeath(); diff --git a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java index b9807084b..bcf331cf4 100644 --- a/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java +++ b/src/net/slipcor/pvparena/runnables/InventoryRefillRunnable.java @@ -78,7 +78,7 @@ public void run() { final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); arena.getDebugger().i("refilling " + player.getName()); if (aPlayer.getStatus() == Status.FIGHT) { - if ("custom".equals(aPlayer.getArenaClass().getName()) && !arena.getArenaConfig().getBoolean(CFG.PLAYER_REFILLCUSTOMINVENTORY) || !arena.getArenaConfig().getBoolean(CFG.PLAYER_REFILLINVENTORY)) { + if (aPlayer.hasCustomClass() && !arena.getArenaConfig().getBoolean(CFG.PLAYER_REFILLCUSTOMINVENTORY) || !arena.getArenaConfig().getBoolean(CFG.PLAYER_REFILLINVENTORY)) { if (refill) { final ItemStack[] items = new ItemStack[additions.size()]; int pos = 0; @@ -101,7 +101,7 @@ public void run() { new ItemStack(ColorUtils.getWoolMaterialFromChatColor(chatColor), 1)); PVPArena.instance.getAgm().refillInventory(arena, player); } - } else if (refill && "custom".equals(aPlayer.getArenaClass().getName())) { + } else if (refill && aPlayer.hasCustomClass()) { ArenaPlayer.reloadInventory(arena, player, false); for (final ItemStack item : additions) { From e95c9e9602c1265ca3459a716dd974ea8bf79e84 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 29 Apr 2020 16:37:30 +0200 Subject: [PATCH 042/115] v1.15 - fixes death screen when player lose its last life --- src/net/slipcor/pvparena/listeners/PlayerListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java index ac7392c12..1bec57349 100644 --- a/src/net/slipcor/pvparena/listeners/PlayerListener.java +++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java @@ -397,6 +397,9 @@ public static void finallyKillPlayer(final Arena arena, final Player player, } } + // Trick to avoid death screen + Bukkit.getScheduler().scheduleSyncDelayedTask(PVPArena.instance, player::closeInventory, 1); + if (!aPlayer.hasCustomClass()) { InventoryManager.clearInventory(player); } From 7575cd2913b8850800030435115c9d1b710a030a Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 30 Apr 2020 18:30:08 +0200 Subject: [PATCH 043/115] v1.15 - add translation and rewrite docs for squads mod --- doc/mods/squads.md | 22 +++++++++++++++------ lang/lang_en.yml | 15 ++++++++++++++ lang/lang_fr.yml | 15 ++++++++++++++ src/net/slipcor/pvparena/core/Language.java | 11 +++++++++++ 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/doc/mods/squads.md b/doc/mods/squads.md index 8f9f1a996..5cc8c97f1 100644 --- a/doc/mods/squads.md +++ b/doc/mods/squads.md @@ -2,7 +2,9 @@ ## Description -This mod adds squads to the game, basically only showing players belonging together apart from teams and classes. +This mod allow players to make squads. Instead of respawning anywhere / at the team spawn, you spawn at a random squad member. + +Squads are an addition to teams or even a replacement (in case of a FFA arena). ## Installation @@ -11,19 +13,27 @@ Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files f - `/pa install [modname]`, activate per arena via - `/pa [arenaname] !tm [modname]` -## Setup +## Usage -\- +Place signs, similar to the Class Signs: + +``` +[Squad name] +[ignored] +free +free +``` + +You can add another (one) sign below for display of more player names -## Config settings ( config.yml !!! NOT per arena! ) +## Config settings ( in your arena config file ) - modules.squads.ingameSquadSwitch \- allow switching squads ingame ## Commands - `/pa [arena] !sq` \- show the arena squads -- `/pa [arena] !sq add [name]` \- add squad [name] -- `/pa [arena] !sq add [name] [limit]` \- add squad with player limit +- `/pa [arena] !sq add [name] [limit]` \- add squad with player limit (set to 0 to remove limit) - `/pa [arena] !sq remove [name]` \- remove squad [name] - `/pa [arena] !sq set [name] [limit]` \- set player limit for squad diff --git a/lang/lang_en.yml b/lang/lang_en.yml index 6a0236968..b7cd3d217 100644 --- a/lang/lang_en.yml +++ b/lang/lang_en.yml @@ -563,6 +563,21 @@ nulang: done: Join block set here - %1% start: Setting join block! stop: Aborted join block selection! + squads: + nosquad: 'No squads loaded! Add some: /pa [arena] !sq add [name]' + listhead: Squads for arena &b%1% + listitem: 'Squad %1% (max: %2%) %3%' + added: Squad %1% has been added + set: Squad %1% has been set + removed: Squad %1% has been removed + notexist: Squad %1% doesn't exist + error: Error while editing squads, syntax is not correct! + full: This squad is full! + help: |- + /pa !sq | show the arena squads + /pa !sq add [name] [limit] | add squad with player limit (set to 0 for no limit) + /pa !sq set [name] [limit] | set player limit for squad + /pa !sq remove [name] | remove squad [name] startfreeze: announce: The game will start in %1% seconds! tempperms: diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml index 196051df1..a913bd22a 100644 --- a/lang/lang_fr.yml +++ b/lang/lang_fr.yml @@ -616,6 +616,21 @@ nulang: done: Le join block est configuré - %1% start: Configuration du join block ! stop: Annulation de la selection du join block! + squads: + nosquad: 'Aucune escouade n''est chargée. Ajoutez-en avec la commande /pa [arena] !sq add [name]' + listhead: Liste des escoudes de l'arène &b%1% + listitem: 'Escouade %1% (max: %2%) %3%' + added: L'escouade %1% a été ajoutée + set: L'escouade %1% a été modifiée + removed: L'escouade %1% a été supprimée + notexist: L'escouade %1% n'existe pas + error: Erreur lors de l'édition des escouades, la syntaxe de la command est incorrecte ! + full: L'escouade est pleine ! + help: |- + /pa !sq | affiche la liste des escouades de l'arène + /pa !sq add [name] [limit] | ajoute une escoude avec une limite (mettre 0 pour ne pas avoir de limite) + /pa !sq set [name] [limit] | modifier la limite de joueurs d'une escouade + /pa !sq remove [name] | supprimer une escouade startfreeze: announce: Le jeu commencera dans %1% secondes ! tempperms: diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 0517c64b4..e76b9ef6b 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -668,6 +668,17 @@ public enum MSG { MODULE_SPECIALJOIN_START("nulang.mod.specialjoin.start", "Setting join block!"), MODULE_SPECIALJOIN_STOP("nulang.mod.specialjoin.stop", "Aborted join block selection!"), + MODULE_SQUADS_NOSQUAD("nulang.mod.squads.nosquad", "No squads loaded! Add some: /pa [arena] !sq add [name]"), + MODULE_SQUADS_LISTHEAD("nulang.mod.squads.listhead", "Squads for arena &b%1%"), + MODULE_SQUADS_LISTITEM("nulang.mod.squads.listitem", "Squad %1% (max: %2%) %3%"), + MODULE_SQUADS_ADDED("nulang.mod.squads.added", "Squad %1% has been added"), + MODULE_SQUADS_SET("nulang.mod.squads.set", "Squad %1% has been set"), + MODULE_SQUADS_REMOVED("nulang.mod.squads.removed", "Squad %1% has been removed"), + MODULE_SQUADS_NOTEXIST("nulang.mod.squads.notexist", "Squad %1% doesn't exist!"), + MODULE_SQUADS_ERROR("nulang.mod.squads.error", "Error while editing squads, syntax is not correct!"), + MODULE_SQUADS_FULL("nulang.mod.squads.full", "This squad is full!"), + MODULE_SQUADS_HELP("nulang.mod.squads.help", "/pa !sq | show the arena squads\n/pa !sq add [name] [limit] | add squad with player limit (set to 0 for no limit)\n/pa !sq set [name] [limit] | set player limit for squad\n/pa !sq remove [name] | remove squad [name]"), + MODULE_STARTFREEZE_ANNOUNCE("nulang.mod.startfreeze.announce", "The game will start in %1% seconds!"), MODULE_TEMPPERMS_NOPERMS("nulang.mod.tempperms.noperms", "Permissions plugin not found, defaulting to OP."), From 5f1fc8b33a5f59c0bd7c4ef1494eb7ceddf64af5 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 30 Apr 2020 19:35:11 +0200 Subject: [PATCH 044/115] v1.15 - fix "no pvp" warn for infected arenas --- src/net/slipcor/pvparena/core/Config.java | 5 +++++ src/net/slipcor/pvparena/managers/ConfigurationManager.java | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index 75b992920..dff88f91f 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -792,6 +792,10 @@ public Set getKeys(final String path) { return section.getKeys(false); } + public List getStringList(final CFG cfg) { + return this.getStringList(cfg.getNode(), null); + } + public List getStringList(final String path, final List def) { if (cfg.get(path) == null) { return def == null ? new LinkedList() : def; @@ -800,6 +804,7 @@ public List getStringList(final String path, final List def) { return cfg.getStringList(path); } + // ///////////////////////////////////////////////////////////////////////// // // // MUTATORS // diff --git a/src/net/slipcor/pvparena/managers/ConfigurationManager.java b/src/net/slipcor/pvparena/managers/ConfigurationManager.java index 58e8124e5..966cd23c5 100644 --- a/src/net/slipcor/pvparena/managers/ConfigurationManager.java +++ b/src/net/slipcor/pvparena/managers/ConfigurationManager.java @@ -282,8 +282,8 @@ public static boolean configParse(final Arena arena, final Config cfg) { .getValues(true); if (arena.isFreeForAll()) { - if (!arena.getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL)) { - PVPArena.instance.getLogger().warning("Arena " + arena.getName() + " is running in NO-PVP mode! Make sure people can die! Ignore this if you're running infect!"); + if (!arena.getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL) && !arena.getArenaConfig().getStringList(CFG.LISTS_GOALS).contains("Infect")) { + PVPArena.instance.getLogger().warning("Arena " + arena.getName() + " is running in NO-PVP mode! Make sure people can die!"); } } else { for (final Map.Entry stringObjectEntry : tempMap.entrySet()) { From aa5d88fbef87c7f876b57abaf3bff7fc7d2bfe48 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Fri, 8 May 2020 21:14:13 +0200 Subject: [PATCH 045/115] v1.15 - Improve flags, physical flags and domination goals to handle all colorable items --- doc/commands/region.md | 6 +- doc/goals/domination.md | 51 +- doc/goals/flags.md | 42 +- doc/goals/physicalflags.md | 67 +- doc/regions.md | 26 +- src/net/slipcor/pvparena/classes/PABlock.java | 10 +- .../pvparena/classes/PABlockLocation.java | 86 +-- src/net/slipcor/pvparena/core/ColorUtils.java | 26 + src/net/slipcor/pvparena/core/Config.java | 12 +- .../slipcor/pvparena/core/StringParser.java | 3 +- .../pvparena/goals/GoalDomination.java | 464 ++++++------ src/net/slipcor/pvparena/goals/GoalFlags.java | 579 +++++++-------- .../pvparena/goals/GoalPhysicalFlags.java | 660 ++++++++---------- .../pvparena/loadables/ArenaRegion.java | 7 +- .../runnables/CircleParticleRunnable.java | 19 +- 15 files changed, 1043 insertions(+), 1015 deletions(-) diff --git a/doc/commands/region.md b/doc/commands/region.md index 3ad4f9e35..2dfe4f8e5 100644 --- a/doc/commands/region.md +++ b/doc/commands/region.md @@ -27,8 +27,4 @@ Valid regionshapes include: - CUBOID (default) - SPHERIC -- CYLINDRIC - -## ToDo - -Add more region shapes :D \ No newline at end of file +- CYLINDRIC \ No newline at end of file diff --git a/doc/goals/domination.md b/doc/goals/domination.md index 4ec9a5176..1d334c517 100644 --- a/doc/goals/domination.md +++ b/doc/goals/domination.md @@ -4,33 +4,56 @@ Domination is designed to use teams. As always, it defaults to red and blue. -It activates Flags (to set) that can be claimed by players. In order to do that, they have to stand near that flag, -alone or at least only one team. Flags can be unclaimed if a different team or multiple teams are too close to a claimed flag. +The game is simple : -Each claimed flag gives points every few seconds (tickinterval) that add up to a score, the first team to have enough points wins. +There are one or several flags that can be claimed by players. +When players are in the range of a flag, a load bar appears and they will claim the flag after few seconds. +Obviously, if a player on another team come also within the flag range, loading stops. + +When a flag is claimed, it take team color. Player of other team can get it back by the same process. +In this case, flag will be released in a first time (it takes white color) and only then it will take color of +second team. + +Each claimed flag gives points every few seconds (tickinterval) that add up to a score, the first team to have enough +points wins. ## Setup Flags have to be added.In order to do that, use `/pa [arenaname] flag`. This toggles edit mode. -Don't forget to exit it again after setting the flags. Set them by clicking the flag type (WOOL by default). +Don't forget to type command again in order to exit edit mode after setting the flags. +Set them by clicking the flag type (WOOL by default). + +Given that flag must be able to change color, you can use the following blocks as flagtype +(color prefix doesn't matter): +* WHITE_BANNER +* WHITE_CARPET +* WHITE_CONCRETE +* WHITE_CONCRETE_POWDER +* WHITE_GLAZED_TERRACOTTA +* WHITE_SHULKER_BOX +* WHITE_STAINED_GLASS +* WHITE_STAINED_GLASS_PANE +* WHITE_TERRACOTTA +* WHITE_WALL_BANNER + +It suggest you to try glass block with a beacon bottom the flag. When flag will be claimed, glass blocks will change its +color, altering beacon light ray in the same time :wink: ## Config Settings - spamoffset => after how many updates should the arena announce? (default: 3) - claimrange => how near need players to be? (default: 3) -- dlives => domination lives ( max points ) -- onlywhenmore => only score when more than half of the points are claimed -- tickinterval => the amount of ticks to wait before doing an update (default: 60 = 3 seconds) -- tickreward => the amount of points to give for each score (default: 1) +- dlives => domination lives (max points). (default: 10) +- onlywhenmore => only score when more than half of the points are claimed. (default: false) +- particlecircle => creates a circle of particles around each flag to mark capture radius. (default: true) +- tickinterval => the amount of ticks to wait before doing an update. (default: 60 = 3 seconds) +- tickreward => the amount of points to give for each score. (default: 1) ## Warnings -This game mode has to check for player's position. Based on the player count this can lag your server. But, how else should I determine a claimed flag? :p - -## Supported Game Modes - -Supports both game modes, but we suggest you use the team game mode! +This game mode has to check for player's position. Based on the player count this can lag your server. +But, how else should I determine a claimed flag? :p -## YouTube video +## YouTube video (legacy) [click me](http://www.youtube.com/watch?v=Xi7yNURxAjw) diff --git a/doc/goals/flags.md b/doc/goals/flags.md index 866e26bc9..260c46ef8 100644 --- a/doc/goals/flags.md +++ b/doc/goals/flags.md @@ -2,28 +2,48 @@ ## Description -This activates Flags (to set), per team. Team A captures the flag of team B and brings it home. To do this, simply hit the flag / your flag. +This activates Flags (to set), per team. Team A captures the flag of team B and brings it home. +To do this, simply hit/click on flags. ## Setup -Flags have to be added.In order to do that, use `/pa [arenaname] [teamname]flag` \- this enables setting. +Firstly, check if flag type is that you want (wool by default) or change it by editing +your arena configuration ou using `/pa set` command. +You can use any solid block as flag. Flags automatically take team color if flag type is one +of the following material (color prefix doesn't matter): -Do this by clicking the flag type (WOOL by default). Don't click with your wand, just click with your hand or anything else. +* WHITE_BANNER +* WHITE_CARPET +* WHITE_CONCRETE +* WHITE_CONCRETE_POWDER +* WHITE_GLAZED_TERRACOTTA +* WHITE_SHULKER_BOX +* WHITE_STAINED_GLASS +* WHITE_STAINED_GLASS_PANE +* WHITE_TERRACOTTA +* WHITE_WALL_BANNER -You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. Players claim this flag and bring it home. Only one team can bring this flag home, obviously :) +  + +Flags have to be added afterwards. In order to do that, use `/pa [arenaname] [teamname]flag` \- this enables setting. +Just left click on your flag block. Clicked block must have same type as defined in your config. However nothing will +happen. + +You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. +Players claim this flag and bring it home. Only one team can bring this flag home, obviously :) ## Config Settings - flives \- the count of flags being brought home that lead to winning -- flagType \- the material checked for flags (default: WOOL) +- flagType \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType +is a colorable item. - mustBeSafe \- do claimed flags prevent bringing home other flags? \- (default: true) - woolFlagHead \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) -- effect \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - slowness, level 2 ; see bukkit docs - -## Supported Game Modes - -Only supports team game mode! +- effect \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - +slowness, level 2) ; see bukkit docs +- alterOnCatch \- change flag aspect when a player catch it. If flag is colorable (list below), color is passed to white + otherwise block is replaced by bedrock. (default: true) -## YouTube video +## YouTube video (legacy) [click me](http://www.youtube.com/watch?v=SuL78bce-f0) diff --git a/doc/goals/physicalflags.md b/doc/goals/physicalflags.md index 9f817621d..2d4df4731 100644 --- a/doc/goals/physicalflags.md +++ b/doc/goals/physicalflags.md @@ -1,23 +1,44 @@ -# PhysicalFlags - ## Description - -This activates Flags (to set), per team. Team A captures the flag of team B and brings it home. To do this, simply break the flag block and click your flag when holding the flag block! - ## Setup - -Flags have to be added.In order to do that, use `/pa [arenaname] [teamname]flag` - this enables setting. - -Do this by clicking the flag type (WOOL by default). Don't click with your wand, -just click with your hand or anything else. - -You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. Players claim this flag and bring it home. - -Only one team can bring this flag home, obviously :) - ## Config Settings - -- flives - the count of flags being brought home that lead to winning -- flagType - the material checked for flags (default: WOOL) -- mustBeSafe - do claimed flags prevent bringing home other flags? - (default: true) - -## Supported Game Modes - -Only supports team game mode! +# PhysicalFlags + +## Description + +This activates Flags (to set), per team. Team A have to break team B flag and brings it at home. +Point is score when team A place team B flag on its own flag. + +## Setup + +Firstly, check if flag type is that you want (wool by default) or change it by editing +your arena configuration ou using `/pa set` command. +You can use any solid block as flag. Flags automatically take team color if flag type is one +of the following material (color prefix doesn't matter): + +* WHITE_BANNER +* WHITE_CARPET +* WHITE_CONCRETE +* WHITE_CONCRETE_POWDER +* WHITE_GLAZED_TERRACOTTA +* WHITE_SHULKER_BOX +* WHITE_STAINED_GLASS +* WHITE_STAINED_GLASS_PANE +* WHITE_TERRACOTTA +* WHITE_WALL_BANNER + +  + +Flags have to be added afterwards. In order to do that, use `/pa [arenaname] [teamname]flag` \- this enables setting. +Just left click on your flag block. Clicked block must have same type as defined in your config. However nothing will +happen. + +You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. +Players claim this flag and bring it home. Only one team can bring this flag home, obviously :) + +## Config Settings + +- flives \- the count of flags being brought home that lead to winning +- flagType \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType +is a colorable item. +- mustBeSafe \- do claimed flags prevent bringing home other flags? \- (default: true) +- woolFlagHead \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) +- effect \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - +slowness, level 2) ; see bukkit docs + diff --git a/doc/regions.md b/doc/regions.md index 879baf747..cb4ba5625 100644 --- a/doc/regions.md +++ b/doc/regions.md @@ -36,6 +36,8 @@ The following Region Types exist: - EXIT => the region where players should be after exiting the arena, no functionality atm - JOIN => the region where players should be when joining, see Configuration page, enforcement is disabled by default - SPAWN => a spawn region where players are randomly placed in when spawning or respawning +- BL_INV => blacklist inventory access +- WL_INV => whitelist inventory access ## Region Flags @@ -53,15 +55,17 @@ Those are valid Region Flags: The BATTLE Region parses region protection flags (other regions can assigned protections, too, but atm they don't really use them). Set them via `/pa !p [regionname] [protection]` - you can add on, off, yes, no, true, false to specify a setting, or just as just told to toggle the state. Note that there is an "ALL" protection node that triggers/sets all protection nodes Valid protections are: -- BREAK - Block breaking -- FIRE - Fire (spreading) -- MOBS - Mob spawning -- NATURE - Environment changes (leaves, shrooms, water, lava) -- PAINTING - Painting placement/destruction -- PISTON - Piston triggering -- PLACE - Block placement -- REDSTONE - Redstone current change -- TNT - TNT usage -- TNTBREAK - TNT block break -- TELEPORT - Players Teleportation +- BREAK - prevent player block breaking +- FIRE - prevent fire spreading/burning +- MOBS - prevent mob spawning +- NATURE - prevent water flow/growth +- PAINTING - prevent painting/itemframe breakage +- PISTON - prevent piston usage +- PLACE - prevent player block placing +- TNT - prevent tnt interaction +- TNTBREAK - prevent tnt block damage (explosion still hurts) +- DROP - prevent player item dropping +- INVENTORY - prevent inventory interaction +- PICKUP - prevent player item pickup +- TELEPORT - prevent player teleportation diff --git a/src/net/slipcor/pvparena/classes/PABlock.java b/src/net/slipcor/pvparena/classes/PABlock.java index 3878c176d..e41259fe7 100644 --- a/src/net/slipcor/pvparena/classes/PABlock.java +++ b/src/net/slipcor/pvparena/classes/PABlock.java @@ -5,24 +5,24 @@ public class PABlock { private final String name; public PABlock(final PABlockLocation loc, final String string) { - location = loc; - name = string; + this.location = loc; + this.name = string; } @Override public boolean equals(final Object o) { if (o instanceof PABlock) { final PABlock other = (PABlock) o; - return name.equals(other.name) && location.equals(other.location); + return this.name.equals(other.name) && this.location.equals(other.location); } return false; } public PABlockLocation getLocation() { - return location; + return this.location; } public String getName() { - return name; + return this.name; } } diff --git a/src/net/slipcor/pvparena/classes/PABlockLocation.java b/src/net/slipcor/pvparena/classes/PABlockLocation.java index 3cf916ea8..75b40a592 100644 --- a/src/net/slipcor/pvparena/classes/PABlockLocation.java +++ b/src/net/slipcor/pvparena/classes/PABlockLocation.java @@ -30,30 +30,30 @@ public PABlockLocation(final String world, final int x, final int y, final int z public PABlockLocation(final String value) { String[] split = value.split(":"); - world = split[0]; + this.world = split[0]; String[] ints = split[1].split(","); - x = Integer.parseInt(ints[0]); - y = Integer.parseInt(ints[1]); - z = Integer.parseInt(ints[2]); + this.x = Integer.parseInt(ints[0]); + this.y = Integer.parseInt(ints[1]); + this.z = Integer.parseInt(ints[2]); } public PABlockLocation(final Location bukkitLocation) { - world = bukkitLocation.getWorld().getName(); - x = bukkitLocation.getBlockX(); - y = bukkitLocation.getBlockY(); - z = bukkitLocation.getBlockZ(); + this.world = bukkitLocation.getWorld().getName(); + this.x = bukkitLocation.getBlockX(); + this.y = bukkitLocation.getBlockY(); + this.z = bukkitLocation.getBlockZ(); } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + (world == null ? 0 : world.hashCode()); - result = prime * result + x; - result = prime * result + y; - result = prime * result + z; + result = prime * result + (this.world == null ? 0 : this.world.hashCode()); + result = prime * result + this.x; + result = prime * result + this.y; + result = prime * result + this.z; return result; } @@ -65,24 +65,24 @@ public boolean equals(final Object obj) { if (obj == null) { return false; } - if (getClass() != obj.getClass()) { + if (this.getClass() != obj.getClass()) { return false; } final PABlockLocation other = (PABlockLocation) obj; - if (world == null) { + if (this.world == null) { if (other.world != null) { return false; } - } else if (!world.equals(other.world)) { + } else if (!this.world.equals(other.world)) { return false; } - if (x != other.x) { + if (this.x != other.x) { return false; } - if (y != other.y) { + if (this.y != other.y) { return false; } - return z == other.z; + return this.z == other.z; } public double getDistance(final PABlockLocation otherLocation) { @@ -90,14 +90,14 @@ public double getDistance(final PABlockLocation otherLocation) { throw new IllegalArgumentException( "Cannot measure distance to a null location"); } - if (!otherLocation.world.equals(world)) { + if (!otherLocation.world.equals(this.world)) { throw new IllegalArgumentException( - "Cannot measure distance between " + world + " and " + "Cannot measure distance between " + this.world + " and " + otherLocation.world); } - return Math.sqrt(Math.pow(x - otherLocation.x, 2.0D) - + Math.pow(y - otherLocation.y, 2.0D) + Math.pow(z - otherLocation.z, 2.0D)); + return Math.sqrt(Math.pow(this.x - otherLocation.x, 2.0D) + + Math.pow(this.y - otherLocation.y, 2.0D) + Math.pow(this.z - otherLocation.z, 2.0D)); } public double getDistanceSquared(final PABlockLocation otherLocation) { @@ -105,77 +105,77 @@ public double getDistanceSquared(final PABlockLocation otherLocation) { throw new IllegalArgumentException( "Cannot measure distance to a null location"); } - if (!otherLocation.world.equals(world)) { + if (!otherLocation.world.equals(this.world)) { throw new IllegalArgumentException( - "Cannot measure distance between " + world + " and " + "Cannot measure distance between " + this.world + " and " + otherLocation.world); } - return Math.pow(x - otherLocation.x, 2.0D) - + Math.pow(y - otherLocation.y, 2.0D) + Math.pow(z - otherLocation.z, 2.0D); + return Math.pow(this.x - otherLocation.x, 2.0D) + + Math.pow(this.y - otherLocation.y, 2.0D) + Math.pow(this.z - otherLocation.z, 2.0D); } public PABlockLocation getMidpoint(final PABlockLocation location) { - return new PABlockLocation(world, (x + location.x) / 2, (y + location.y) / 2, - (z + location.z) / 2); + return new PABlockLocation(this.world, (this.x + location.x) / 2, (this.y + location.y) / 2, + (this.z + location.z) / 2); } public String getWorldName() { - return world; + return this.world; } public int getX() { - return x; + return this.x; } public int getY() { - return y; + return this.y; } public int getZ() { - return z; + return this.z; } public boolean isInAABB(final PABlockLocation min, final PABlockLocation max) { - if (x < min.x || x > max.x) { + if (this.x < min.x || this.x > max.x) { return false; } - if (y < min.y || y > max.y) { + if (this.y < min.y || this.y > max.y) { return false; } - return !(z < min.z || z > max.z); + return !(this.z < min.z || this.z > max.z); } public PABlockLocation pointTo(final PABlockLocation dest, final Double length) { - final Vector source = new Vector(x, y, z); + final Vector source = new Vector(this.x, this.y, this.z); final Vector destination = new Vector(dest.x, dest.y, dest.z); Vector goal = source.subtract(destination); goal = goal.normalize().multiply(length); - return new PABlockLocation(world, x + x + goal.getBlockX(), y - + goal.getBlockY(), z + goal.getBlockZ()); + return new PABlockLocation(this.world, this.x + this.x + goal.getBlockX(), this.y + + goal.getBlockY(), this.z + goal.getBlockZ()); } public void setX(final int value) { - x = value; + this.x = value; } public void setY(final int value) { - y = value; + this.y = value; } public void setZ(final int value) { - z = value; + this.z = value; } public Location toLocation() { - return new Location(Bukkit.getWorld(world), x, y, z); + return new Location(Bukkit.getWorld(this.world), this.x, this.y, this.z); } @Override public String toString() { - return world + ':' + x + ',' + y + ',' + z; + return this.world + ':' + this.x + ',' + this.y + ',' + this.z; } } diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java index 83a506ab0..3c2ac1507 100644 --- a/src/net/slipcor/pvparena/core/ColorUtils.java +++ b/src/net/slipcor/pvparena/core/ColorUtils.java @@ -1,8 +1,13 @@ package net.slipcor.pvparena.core; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.DyeColor; import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; import java.util.Arrays; import java.util.List; @@ -119,4 +124,25 @@ private static List getColorableSuffixes() { .map(ColorUtils::getMaterialSuffix) .collect(Collectors.toList()); } + + /** + * Change flag color keeping rotation and facing + * @param flagBlock Block (location) of the flag + * @param flagColor New flag color + */ + public static void setNewFlagColor(Block flagBlock, ChatColor flagColor) { + final BlockData originalBlockData = flagBlock.getBlockData().clone(); + Material newMaterial = ColorUtils.getColoredMaterialFromChatColor(flagColor, flagBlock.getType()); + BlockData newData = Bukkit.getServer().createBlockData(newMaterial); + + if(originalBlockData instanceof Directional) { + ((Directional) newData).setFacing(((Directional) originalBlockData).getFacing()); + } + + if(originalBlockData instanceof Rotatable) { + ((Rotatable) newData).setRotation(((Rotatable) originalBlockData).getRotation()); + } + + flagBlock.setBlockData(newData); + } } diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index dff88f91f..a67865933 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -206,7 +206,7 @@ public enum CFG { GOAL_DOM_CLAIMRANGE("goal.dom.claimrange", 3, "Domination"), GOAL_DOM_LIVES("goal.dom.dlives", 10, "Domination"), GOAL_DOM_ONLYWHENMORE("goal.dom.onlywhenmore", false, "Domination"), - GOAL_DOM_PARTICLECIRCLE("goal.dom.particlecircle", false, "Domination"), + GOAL_DOM_PARTICLECIRCLE("goal.dom.particlecircle", true, "Domination"), GOAL_DOM_TICKINTERVAL("goal.dom.tickinterval", 60, "Domination"), GOAL_DOM_TICKREWARD("goal.dom.tickreward", 1, "Domination"), @@ -215,6 +215,7 @@ public enum CFG { GOAL_FLAGS_MUSTBESAFE("goal.flags.mustBeSafe", true, "Flags"), GOAL_FLAGS_WOOLFLAGHEAD("goal.flags.woolFlagHead", true, "Flags"), GOAL_FLAGS_FLAGEFFECT("goal.flags.effect", "none", "Flags"), + GOAL_FLAGS_ALTERONCATCH("goal.flags.alterOnCatch", true, "Flags"), GOAL_FOOD_FMAXITEMS("goal.food.fmaxitems", 50, "Food"), GOAL_FOOD_FPLAYERITEMS("goal.food.fplayeritems", 10, "Food"), @@ -228,6 +229,13 @@ public enum CFG { GOAL_LLIVES_LIVES("goal.liberation.llives", 3, "Liberation"), GOAL_PDM_LIVES("goal.playerdm.pdlives", 3, "PlayerDeathMatch"), + + GOAL_PFLAGS_FLAGTYPE("goal.physicalflags.flagType", Material.WHITE_WOOL, "PhysicalFlags"), + GOAL_PFLAGS_LIVES("goal.physicalflags.flives", 3, "PhysicalFlags"), + GOAL_PFLAGS_MUSTBESAFE("goal.physicalflags.mustBeSafe", true, "PhysicalFlags"), + GOAL_PFLAGS_WOOLFLAGHEAD("goal.physicalflags.woolFlagHead", true, "PhysicalFlags"), + GOAL_PFLAGS_FLAGEFFECT("goal.physicalflags.effect", "none", "PhysicalFlags"), + GOAL_PLIVES_LIVES("goal.playerlives.plives", 3, "PlayerLives"), GOAL_TANK_LIVES("goal.tank.tlives", 1, "Tank"), GOAL_TDC_LIVES("goal.teamdc.tdclives", 10, "TeamDeathConfirm"), @@ -534,7 +542,7 @@ public String getType() { } public String getModule() { - return module; + return this.module; } public boolean hasModule() { diff --git a/src/net/slipcor/pvparena/core/StringParser.java b/src/net/slipcor/pvparena/core/StringParser.java index f5e1efe13..e786b150b 100644 --- a/src/net/slipcor/pvparena/core/StringParser.java +++ b/src/net/slipcor/pvparena/core/StringParser.java @@ -91,8 +91,7 @@ public static String colorVar(final String string) { * @return a colored string */ public static String colorVar(final String string, final boolean value) { - return (value ? ChatColor.GREEN.toString() : ChatColor.RED.toString()) + string - + ChatColor.WHITE; + return (value ? ChatColor.GREEN.toString() : ChatColor.RED.toString()) + string + ChatColor.WHITE; } public static String joinArray(final Object[] array, final String glue) { diff --git a/src/net/slipcor/pvparena/goals/GoalDomination.java b/src/net/slipcor/pvparena/goals/GoalDomination.java index 12f3eda32..1778a586c 100644 --- a/src/net/slipcor/pvparena/goals/GoalDomination.java +++ b/src/net/slipcor/pvparena/goals/GoalDomination.java @@ -23,6 +23,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import java.util.*; @@ -37,11 +38,14 @@ public class GoalDomination extends ArenaGoal { + private static final int PRIORITY = 8; + private static final int INTERVAL = 200; + private BukkitTask circleTask = null; public GoalDomination() { super("Domination"); - debug = new Debug(99); + this.debug = new Debug(99); } private Map flagMap = new HashMap<>(); @@ -55,29 +59,27 @@ public String version() { return PVPArena.instance.getDescription().getVersion(); } - private static final int PRIORITY = 8; - @Override public boolean allowsJoinInBattle() { - return arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE); + return this.arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE); } - private void barStart(Location location, String title, ChatColor color, int range, long interval) { - if (!arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_BOSSBAR)) { + private void barStart(Location location, String title, ChatColor color, int range) { + if (!this.arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_BOSSBAR)) { return; } - if (getBarMap().containsKey(location)) { - PAClaimBar claimBar = getBarMap().get(location); - claimBar.restart(title, color, location, range, interval); + if (this.getBarMap().containsKey(location)) { + PAClaimBar claimBar = this.getBarMap().get(location); + claimBar.restart(title, color, location, range, INTERVAL); } else { - PAClaimBar claimBar = new PAClaimBar(arena, title, color, location, range, interval); - getBarMap().put(location, claimBar); + PAClaimBar claimBar = new PAClaimBar(this.arena, title, color, location, range, INTERVAL); + this.getBarMap().put(location, claimBar); } } private void barStop(Location location) { - if (getBarMap().containsKey(location)) { - getBarMap().get(location).stop(); + if (this.getBarMap().containsKey(location)) { + this.getBarMap().get(location).stop(); } } @@ -106,12 +108,12 @@ public PACheck checkEnd(final PACheck res) { return res; } - final int count = TeamManager.countActiveTeams(arena); + final int count = TeamManager.countActiveTeams(this.arena); if (count == 1) { res.setPriority(this, PRIORITY); // yep. only one team left. go! } else if (count == 0) { - arena.getDebugger().i("No teams playing!"); + this.arena.getDebugger().i("No teams playing!"); } return res; @@ -120,7 +122,7 @@ public PACheck checkEnd(final PACheck res) { @Override public String checkForMissingSpawns(final Set list) { - final String team = checkForMissingTeamSpawn(list); + final String team = this.checkForMissingTeamSpawn(list); if (team != null) { return team; } @@ -142,12 +144,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St return res; } - final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS); - final int maxTeamPlayers = arena.getArenaConfig().getInt( + final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS); + final int maxTeamPlayers = this.arena.getArenaConfig().getInt( CFG.READY_MAXTEAMPLAYERS); - if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) { - res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL)); + if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) { + res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL)); return res; } @@ -155,12 +157,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St return res; } - if (!arena.isFreeForAll()) { - final ArenaTeam team = arena.getTeam(args[0]); + if (!this.arena.isFreeForAll()) { + final ArenaTeam team = this.arena.getTeam(args[0]); if (team != null && maxTeamPlayers > 0 && team.getTeamMembers().size() >= maxTeamPlayers) { - res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName())); + res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName())); return res; } } @@ -181,7 +183,7 @@ private Set checkLocationPresentTeams(final Location loc, final int dist final Set result = new HashSet<>(); final Location flagCenter = Utils.getCenteredLocation(loc); - for (final ArenaPlayer p : arena.getFighters()) { + for (final ArenaPlayer p : this.arena.getFighters()) { if (p.get().getLocation().distance(flagCenter) > distance) { continue; @@ -219,130 +221,127 @@ void checkMove() { */ - arena.getDebugger().i("------------------"); - arena.getDebugger().i(" checkMove();"); - arena.getDebugger().i("------------------"); + this.arena.getDebugger().i("------------------"); + this.arena.getDebugger().i(" checkMove();"); + this.arena.getDebugger().i("------------------"); - final int checkDistance = arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE); + final int checkDistance = this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE); - for (final PABlockLocation paLoc : SpawnManager.getBlocksStartingWith(arena, "flag")) { + for (final PABlockLocation paLoc : SpawnManager.getBlocksStartingWith(this.arena, "flag")) { // arena.getDebugger().info("checking location: " + loc.toString()); final Location loc = paLoc.toLocation(); - final Set teams = checkLocationPresentTeams(loc, checkDistance); + final Set teams = this.checkLocationPresentTeams(loc, checkDistance); - arena.getDebugger().i("teams: " + StringParser.joinSet(teams, ", ")); + this.arena.getDebugger().i("teams: " + StringParser.joinSet(teams, ", ")); // teams now contains all teams near the flag if (teams.size() < 1) { // arena.getDebugger().info("=> noone there!"); // no one there - if (getRunnerMap().containsKey(loc)) { - arena.getDebugger().i("flag is being (un)claimed! Cancelling!"); + if (this.getRunnerMap().containsKey(loc)) { + this.arena.getDebugger().i("flag is being (un)claimed! Cancelling!"); // cancel unclaiming/claiming if noone's near - Bukkit.getScheduler().cancelTask(getRunnerMap().get(loc).runID); - getRunnerMap().remove(loc); - barStop(loc); + this.getRunnerMap().get(loc).cancel(); + this.getRunnerMap().remove(loc); + this.barStop(loc); } - if (getFlagMap().containsKey(loc)) { - final String team = getFlagMap().get(loc); + if (this.getFlagMap().containsKey(loc)) { + final String team = this.getFlagMap().get(loc); - if (!getLifeMap().containsKey(team)) { + if (!this.getLifeMap().containsKey(team)) { continue; } // flag claimed! add score! - maybeAddScoreAndBroadCast(team); + this.maybeAddScoreAndBroadCast(team); } continue; } // there are actually teams at the flag - arena.getDebugger().i("=> at least one team is at the flag!"); + this.arena.getDebugger().i("=> at least one team is at the flag!"); - if (getFlagMap().containsKey(loc)) { + if (this.getFlagMap().containsKey(loc)) { // flag is taken. by whom? - if (teams.contains(getFlagMap().get(loc))) { + if (teams.contains(this.getFlagMap().get(loc))) { // owning team is there - arena.getDebugger().i(" - owning team is there"); + this.arena.getDebugger().i(" - owning team is there"); if (teams.size() > 1) { // another team is there - arena.getDebugger().i(" - and another one"); - if (getRunnerMap().containsKey(loc)) { + this.arena.getDebugger().i(" - and another one"); + if (this.getRunnerMap().containsKey(loc)) { // it is being unclaimed - arena.getDebugger().i(" - being unclaimed. continue!"); + this.arena.getDebugger().i(" - being unclaimed. continue!"); } else { // unclaim - arena.getDebugger().i(" - not being unclaimed. do it!"); - ArenaTeam team = arena.getTeam(getFlagMap().get(loc)); - String contestingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_CONTESTING, team.getColoredName() + ChatColor.YELLOW); - arena.broadcast(contestingMsg); + this.arena.getDebugger().i(" - not being unclaimed. do it!"); + ArenaTeam team = this.arena.getTeam(this.getFlagMap().get(loc)); + String contestingMsg = Language.parse(this.arena, MSG.GOAL_DOMINATION_CONTESTING, team.getColoredName() + ChatColor.YELLOW); + this.arena.broadcast(contestingMsg); final DominationRunnable domRunner = new DominationRunnable( - arena, false, loc, - getFlagMap().get(loc), this); - domRunner.runID = Bukkit.getScheduler() - .scheduleSyncRepeatingTask(PVPArena.instance, domRunner, 10 * 20L, 10 * 20L); + this.arena, false, loc, + this.getFlagMap().get(loc), this); - getRunnerMap().put(loc, domRunner); - barStart(loc, contestingMsg, ChatColor.WHITE, checkDistance, 200L); + domRunner.runTaskTimer(PVPArena.instance, INTERVAL, INTERVAL); + + this.getRunnerMap().put(loc, domRunner); + this.barStart(loc, contestingMsg, ChatColor.WHITE, checkDistance); } } else { // just the owning team is there - arena.getDebugger().i(" - noone else"); - if (getRunnerMap().containsKey(loc)) { - arena.getDebugger().i(" - being unclaimed. cancel!"); + this.arena.getDebugger().i(" - noone else"); + if (this.getRunnerMap().containsKey(loc)) { + this.arena.getDebugger().i(" - being unclaimed. cancel!"); // it is being unclaimed // cancel task! - Bukkit.getScheduler() - .cancelTask(getRunnerMap().get(loc).runID); - getRunnerMap().remove(loc); - barStop(loc); + this.getRunnerMap().get(loc).cancel(); + this.getRunnerMap().remove(loc); + this.barStop(loc); } else { - final String team = getFlagMap().get(loc); + final String team = this.getFlagMap().get(loc); - if (!getLifeMap().containsKey(team)) { + if (!this.getLifeMap().containsKey(team)) { continue; } - maybeAddScoreAndBroadCast(team); + this.maybeAddScoreAndBroadCast(team); } } continue; } - arena.getDebugger().i(" - owning team is not there!"); + this.arena.getDebugger().i(" - owning team is not there!"); // owning team is NOT there ==> unclaim! - if (getRunnerMap().containsKey(loc)) { - if (getRunnerMap().get(loc).take) { - arena.getDebugger().i(" - runnable is trying to score, abort"); + if (this.getRunnerMap().containsKey(loc)) { + if (this.getRunnerMap().get(loc).isTaken()) { + this.arena.getDebugger().i(" - runnable is trying to score, abort"); - Bukkit.getScheduler().cancelTask(getRunnerMap().get(loc).runID); - getRunnerMap().remove(loc); + this.getRunnerMap().get(loc).cancel(); + this.getRunnerMap().remove(loc); } else { - arena.getDebugger().i(" - being unclaimed. continue."); + this.arena.getDebugger().i(" - being unclaimed. continue."); } continue; } - arena.getDebugger().i(" - not yet being unclaimed, do it!"); + this.arena.getDebugger().i(" - not yet being unclaimed, do it!"); // create an unclaim runnable - ArenaTeam team = arena.getTeam(getFlagMap().get(loc)); - String unclaimingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_UNCLAIMING, team.getColoredName() + ChatColor.YELLOW); - arena.broadcast(unclaimingMsg); - final DominationRunnable running = new DominationRunnable(arena, - false, loc, getFlagMap().get(loc), this); - final long interval = 20L * 10; - - running.runID = Bukkit.getScheduler().scheduleSyncRepeatingTask( - PVPArena.instance, running, interval, interval); - getRunnerMap().put(loc, running); - barStart(loc, unclaimingMsg, ChatColor.WHITE, checkDistance, interval); + ArenaTeam team = this.arena.getTeam(this.getFlagMap().get(loc)); + String unclaimingMsg = Language.parse(this.arena, MSG.GOAL_DOMINATION_UNCLAIMING, team.getColoredName() + ChatColor.YELLOW); + this.arena.broadcast(unclaimingMsg); + final DominationRunnable running = new DominationRunnable(this.arena, + false, loc, this.getFlagMap().get(loc), this); + + running.runTaskTimer(PVPArena.instance, INTERVAL, INTERVAL); + this.getRunnerMap().put(loc, running); + this.barStart(loc, unclaimingMsg, ChatColor.WHITE, checkDistance); } else { // flag not taken - arena.getDebugger().i("- flag not taken"); + this.arena.getDebugger().i("- flag not taken"); /* * check if a runnable @@ -355,46 +354,43 @@ void checkMove() { * yes => create runnable; * no => continue */ - if (getRunnerMap().containsKey(loc)) { - arena.getDebugger().i(" - being claimed"); + if (this.getRunnerMap().containsKey(loc)) { + this.arena.getDebugger().i(" - being claimed"); if (teams.size() < 2) { - arena.getDebugger().i(" - only one team present"); - if (teams.contains(getRunnerMap().get(loc).team)) { + this.arena.getDebugger().i(" - only one team present"); + if (teams.contains(this.getRunnerMap().get(loc).team)) { // just THE team that is claiming => NEXT - arena.getDebugger().i(" - claiming team present. next!"); + this.arena.getDebugger().i(" - claiming team present. next!"); continue; } } - arena.getDebugger().i(" - more than one team or another team. cancel claim!"); + this.arena.getDebugger().i(" - more than one team or another team. cancel claim!"); // more than THE team that is claiming => cancel! - Bukkit.getScheduler().cancelTask(getRunnerMap().get(loc).runID); - getRunnerMap().remove(loc); - barStop(loc); + this.getRunnerMap().get(loc).cancel(); + this.getRunnerMap().remove(loc); + this.barStop(loc); } else { - arena.getDebugger().i(" - not being claimed"); + this.arena.getDebugger().i(" - not being claimed"); // not being claimed if (teams.size() < 2) { - arena.getDebugger().i(" - just one team present"); + this.arena.getDebugger().i(" - just one team present"); for (final String sName : teams) { - arena.getDebugger().i("TEAM " + sName + " IS CLAIMING " + this.arena.getDebugger().i("TEAM " + sName + " IS CLAIMING " + loc); - final ArenaTeam team = arena.getTeam(sName); - String claimingMsg = Language.parse(arena, MSG.GOAL_DOMINATION_CLAIMING, + final ArenaTeam team = this.arena.getTeam(sName); + String claimingMsg = Language.parse(this.arena, MSG.GOAL_DOMINATION_CLAIMING, team.getColoredName() + ChatColor.YELLOW); - arena.broadcast(claimingMsg); + this.arena.broadcast(claimingMsg); final DominationRunnable running = new DominationRunnable( - arena, true, loc, sName, this); - final long interval = 20L * 10; - running.runID = Bukkit.getScheduler() - .scheduleSyncRepeatingTask( - PVPArena.instance, running, - interval, interval); - getRunnerMap().put(loc, running); - barStart(loc, claimingMsg, team.getColor(), checkDistance, interval); + this.arena, true, loc, sName, this); + + running.runTaskTimer(PVPArena.instance, INTERVAL, INTERVAL); + this.getRunnerMap().put(loc, running); + this.barStart(loc, claimingMsg, team.getColor(), checkDistance); } } else { - arena.getDebugger().i(" - more than one team present. continue!"); + this.arena.getDebugger().i(" - more than one team present. continue!"); } } } @@ -402,9 +398,9 @@ void checkMove() { } private void maybeAddScoreAndBroadCast(final String team) { - if (arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_ONLYWHENMORE)) { + if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_ONLYWHENMORE)) { final Map claimed = new HashMap<>(); - for (final String s : getFlagMap().values()) { + for (final String s : this.getFlagMap().values()) { final int toAdd; if (claimed.containsKey(s)) { toAdd = claimed.get(s) + 1; @@ -423,29 +419,28 @@ private void maybeAddScoreAndBroadCast(final String team) { } } - reduceLivesCheckEndAndCommit(arena, team); + this.reduceLivesCheckEndAndCommit(this.arena, team); - final int max = arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES); - if (!getLifeMap().containsKey(team)) { + final int max = this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES); + if (!this.getLifeMap().containsKey(team)) { return; } - final int lives = getLifeMap().get(team); + final int lives = this.getLifeMap().get(team); - if ((max - lives) % announceOffset != 0) { + if ((max - lives) % this.announceOffset != 0) { return; } - arena.broadcast(Language.parse(arena, MSG.GOAL_DOMINATION_SCORE, - arena.getTeam(team).getColoredName() + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_DOMINATION_SCORE, + this.arena.getTeam(team).getColoredName() + ChatColor.YELLOW, (max - lives) + "/" + max)); } @Override public PACheck checkSetBlock(final PACheck res, final Player player, final Block block) { - if (res.getPriority() > PRIORITY - || !PAA_Region.activeSelections.containsKey(player.getName())) { + if (res.getPriority() > PRIORITY || !PAA_Region.activeSelections.containsKey(player.getName())) { return res; } if (block == null || !ColorUtils.isColorableMaterial(block.getType())) { @@ -505,7 +500,7 @@ private void commit(final Arena arena, final String sTeam) { + ChatColor.YELLOW)); } - getLifeMap().clear(); + this.getLifeMap().clear(); new EndRunnable(arena, arena.getArenaConfig().getInt( CFG.TIME_ENDCOUNTDOWN)); } @@ -514,27 +509,27 @@ private void commit(final Arena arena, final String sTeam) { public void commitCommand(final CommandSender sender, final String[] args) { if (PAA_Region.activeSelections.containsKey(sender.getName())) { PAA_Region.activeSelections.remove(sender.getName()); - arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_SET, "flags")); + this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, "flags")); } else { - PAA_Region.activeSelections.put(sender.getName(), arena); - arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_TOSET, "flags")); + PAA_Region.activeSelections.put(sender.getName(), this.arena); + this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_TOSET, "flags")); } } @Override public void commitEnd(final boolean force) { - if (arena.realEndRunner != null) { - arena.getDebugger().i("[DOMINATION] already ending"); + if (this.arena.realEndRunner != null) { + this.arena.getDebugger().i("[DOMINATION] already ending"); return; } - arena.getDebugger().i("[DOMINATION]"); + this.arena.getDebugger().i("[DOMINATION]"); - final PAGoalEvent gEvent = new PAGoalEvent(arena, this, ""); + final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, ""); Bukkit.getPluginManager().callEvent(gEvent); ArenaTeam aTeam = null; - for (final ArenaTeam team : arena.getTeams()) { + for (final ArenaTeam team : this.arena.getTeams()) { for (final ArenaPlayer ap : team.getTeamMembers()) { if (ap.getStatus() == Status.FIGHT) { aTeam = team; @@ -545,22 +540,22 @@ public void commitEnd(final boolean force) { if (aTeam != null && !force) { ArenaModuleManager.announce( - arena, - Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena, + Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW), "END"); ArenaModuleManager.announce( - arena, - Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena, + Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW), "WINNER"); - arena.broadcast(Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena.broadcast(Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW)); } - if (ArenaModuleManager.commitEnd(arena, aTeam)) { + if (ArenaModuleManager.commitEnd(this.arena, aTeam)) { return; } - new EndRunnable(arena, arena.getArenaConfig().getInt( + new EndRunnable(this.arena, this.arena.getArenaConfig().getInt( CFG.TIME_ENDCOUNTDOWN)); } @@ -568,13 +563,11 @@ public void commitEnd(final boolean force) { public boolean commitSetFlag(final Player player, final Block block) { if (PVPArena.hasAdminPerms(player) - || PVPArena.hasCreatePerms(player, arena) - && player.getEquipment().getItemInMainHand() != null - && player.getEquipment().getItemInMainHand().getType().toString().equals(arena + || PVPArena.hasCreatePerms(player, this.arena) + && player.getInventory().getItemInMainHand().getType().toString().equals(this.arena .getArenaConfig().getString(CFG.GENERAL_WAND))) { - final Set flags = SpawnManager.getBlocksStartingWith(arena, - "flag"); + final Set flags = SpawnManager.getBlocksStartingWith(this.arena,"flag"); if (flags.contains(new PABlockLocation(block.getLocation()))) { return false; @@ -582,10 +575,9 @@ public boolean commitSetFlag(final Player player, final Block block) { final String flagName = "flag" + flags.size(); - SpawnManager.setBlock(arena, - new PABlockLocation(block.getLocation()), flagName); + SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()), flagName); - arena.msg(player, Language.parse(arena, MSG.GOAL_FLAGS_SET, flagName)); + this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, flagName)); return true; } return false; @@ -593,24 +585,22 @@ public boolean commitSetFlag(final Player player, final Block block) { @Override public void displayInfo(final CommandSender sender) { - sender.sendMessage("needed points: " + - arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES)); - sender.sendMessage("claim range: " + - arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE)); + sender.sendMessage("needed points: " + this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES)); + sender.sendMessage("claim range: " + this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_CLAIMRANGE)); } private Map getFlagMap() { - if (flagMap == null) { - flagMap = new HashMap<>(); + if (this.flagMap == null) { + this.flagMap = new HashMap<>(); } - return flagMap; + return this.flagMap; } private Map getBarMap() { - if (flagBars == null) { - flagBars = new HashMap<>(); + if (this.flagBars == null) { + this.flagBars = new HashMap<>(); } - return flagBars; + return this.flagBars; } @Override @@ -618,29 +608,29 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + String.valueOf(this.getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) ); } return res; } private Map getRunnerMap() { - if (runnerMap == null) { - runnerMap = new HashMap<>(); + if (this.runnerMap == null) { + this.runnerMap = new HashMap<>(); } - return runnerMap; + return this.runnerMap; } @Override public boolean hasSpawn(final String string) { - for (final String teamName : arena.getTeamNames()) { + for (final String teamName : this.arena.getTeamNames()) { if (string.toLowerCase().startsWith( teamName.toLowerCase() + "spawn")) { return true; } - if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) { - for (final ArenaClass aClass : arena.getClasses()) { + if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) { + for (final ArenaClass aClass : this.arena.getClasses()) { if (string.toLowerCase().startsWith(teamName.toLowerCase() + aClass.getName().toLowerCase() + "spawn")) { return true; @@ -655,13 +645,13 @@ public boolean hasSpawn(final String string) { public void initate(final Player player) { final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); final ArenaTeam team = aPlayer.getArenaTeam(); - if (!getLifeMap().containsKey(team.getName())) { - getLifeMap().put(aPlayer.getArenaTeam().getName(), arena.getArenaConfig() + if (!this.getLifeMap().containsKey(team.getName())) { + this.getLifeMap().put(aPlayer.getArenaTeam().getName(), this.arena.getArenaConfig() .getInt(CFG.GOAL_DOM_LIVES)); - final Set spawns = SpawnManager.getBlocksStartingWith(arena, "flag"); + final Set spawns = SpawnManager.getBlocksStartingWith(this.arena, "flag"); for (final PABlockLocation spawn : spawns) { - takeFlag(spawn); + this.takeFlag(spawn); } } } @@ -673,68 +663,65 @@ public boolean isInternal() { @Override public void parseStart() { - getLifeMap().clear(); - for (final ArenaTeam team : arena.getTeams()) { + this.getLifeMap().clear(); + for (final ArenaTeam team : this.arena.getTeams()) { if (!team.getTeamMembers().isEmpty()) { - arena.getDebugger().i("adding team " + team.getName()); + this.arena.getDebugger().i("adding team " + team.getName()); // team is active - getLifeMap().put(team.getName(), - arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES, 3)); + this.getLifeMap().put(team.getName(), + this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_LIVES, 3)); } } - final Set spawns = SpawnManager.getBlocksStartingWith(arena, "flag"); + final Set spawns = SpawnManager.getBlocksStartingWith(this.arena, "flag"); for (final PABlockLocation spawn : spawns) { - takeFlag(spawn); + this.takeFlag(spawn); } - final DominationMainRunnable domMainRunner = new DominationMainRunnable(arena, this); - final int tickInterval = arena.getArenaConfig().getInt(CFG.GOAL_DOM_TICKINTERVAL); - domMainRunner.rID = Bukkit.getScheduler().scheduleSyncRepeatingTask( - PVPArena.instance, domMainRunner, tickInterval, tickInterval); + final DominationMainRunnable domMainRunner = new DominationMainRunnable(this.arena, this); + final int tickInterval = this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_TICKINTERVAL); + domMainRunner.runTaskTimer(PVPArena.instance, tickInterval, tickInterval); - announceOffset = arena.getArenaConfig().getInt(CFG.GOAL_DOM_ANNOUNCEOFFSET); + this.announceOffset = this.arena.getArenaConfig().getInt(CFG.GOAL_DOM_ANNOUNCEOFFSET); - if(arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_PARTICLECIRCLE)) { - circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(arena, CFG.GOAL_DOM_CLAIMRANGE, getFlagMap()), 1L, 1L); + if(this.arena.getArenaConfig().getBoolean(CFG.GOAL_DOM_PARTICLECIRCLE)) { + this.circleTask = Bukkit.getScheduler().runTaskTimer(PVPArena.instance, new CircleParticleRunnable(this.arena, CFG.GOAL_DOM_CLAIMRANGE, this.getFlagMap()), 1L, 1L); } } - private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String team) { + private void reduceLivesCheckEndAndCommit(final Arena arena, final String team) { arena.getDebugger().i("reducing lives of team " + team); - if (getLifeMap().get(team) != null) { + if (this.getLifeMap().get(team) != null) { final int score = arena.getArenaConfig().getInt(CFG.GOAL_DOM_TICKREWARD); - final int iLives = getLifeMap().get(team) - score; + final int iLives = this.getLifeMap().get(team) - score; final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "score:null:"+team+":"+score); Bukkit.getPluginManager().callEvent(gEvent); if (iLives > 0) { - getLifeMap().put(team, iLives); + this.getLifeMap().put(team, iLives); } else { - getLifeMap().remove(team); - commit(arena, team); - return true; + this.getLifeMap().remove(team); + this.commit(arena, team); } } - return false; } @Override public void reset(final boolean force) { - getBarMap().clear(); - getLifeMap().clear(); - getRunnerMap().clear(); - getFlagMap().clear(); - if (circleTask != null) { - circleTask.cancel(); - circleTask = null; + this.getBarMap().clear(); + this.getLifeMap().clear(); + this.getRunnerMap().clear(); + this.getFlagMap().clear(); + if (this.circleTask != null) { + this.circleTask.cancel(); + this.circleTask = null; } } @Override public void setDefaults(final YamlConfiguration config) { - if (arena.isFreeForAll()) { + if (this.arena.isFreeForAll()) { return; } @@ -742,7 +729,7 @@ public void setDefaults(final YamlConfiguration config) { config.set("teams", null); } if (config.get("teams") == null) { - arena.getDebugger().i("no teams defined, adding custom red and blue!"); + this.arena.getDebugger().i("no teams defined, adding custom red and blue!"); config.addDefault("teams.red", ChatColor.RED.name()); config.addDefault("teams.blue", ChatColor.BLUE.name()); } @@ -754,15 +741,14 @@ public void setDefaults(final YamlConfiguration config) { * @param paBlockLocation the location to take/reset*/ private void takeFlag(final PABlockLocation paBlockLocation) { Block flagBlock = paBlockLocation.toLocation().getBlock(); - flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(ChatColor.WHITE, flagBlock.getType())); + ColorUtils.setNewFlagColor(flagBlock, ChatColor.WHITE); } @Override public Map timedEnd(final Map scores) { - for (final ArenaTeam team : arena.getTeams()) { - double score = getLifeMap().containsKey(team.getName()) ? getLifeMap() - .get(team.getName()) : 0; + for (final ArenaTeam team : this.arena.getTeams()) { + double score = this.getLifeMap().getOrDefault(team.getName(), 0); if (scores.containsKey(team.getName())) { scores.put(team.getName(), scores.get(team.getName()) + score); } else { @@ -773,13 +759,11 @@ public Map timedEnd(final Map scores) { return scores; } - class DominationRunnable implements Runnable { - public final boolean take; - public final Location loc; - public int runID = -1; + private static class DominationRunnable extends BukkitRunnable { + private final boolean taken; + private final Location loc; private final Arena arena; public final String team; - //private final Debug debug = new Debug(39); private final GoalDomination domination; /** @@ -787,13 +771,13 @@ class DominationRunnable implements Runnable { * * @param arena the arena we are running in */ - public DominationRunnable(final Arena arena, final boolean take, final Location loc2, final String teamName, + public DominationRunnable(final Arena arena, final boolean taken, final Location loc2, final String teamName, final GoalDomination goal) { this.arena = arena; - this.take = take; - team = teamName; - loc = loc2; - domination = goal; + this.taken = taken; + this.team = teamName; + this.loc = loc2; + this.domination = goal; arena.getDebugger().i("Domination constructor"); } @@ -802,33 +786,33 @@ public DominationRunnable(final Arena arena, final boolean take, final Location */ @Override public void run() { - arena.getDebugger().i("DominationRunnable commiting"); - arena.getDebugger().i("team " + team + ", take: " + take); - if (take) { + this.arena.getDebugger().i("DominationRunnable commiting"); + this.arena.getDebugger().i("team " + this.team + ", take: " + this.taken); + if (this.taken) { // claim a flag for the team - if (!domination.getFlagMap().containsKey(loc)) { + if (!this.domination.getFlagMap().containsKey(this.loc)) { // flag unclaimed! claim! - arena.getDebugger().i("clag unclaimed. claim!"); - domination.getFlagMap().put(loc, team); + this.arena.getDebugger().i("clag unclaimed. claim!"); + this.domination.getFlagMap().put(this.loc, this.team); // long interval = 20L * 5; - arena.broadcast(Language.parse(arena, - MSG.GOAL_DOMINATION_CLAIMED, arena.getTeam(team) + this.arena.broadcast(Language.parse(this.arena, + MSG.GOAL_DOMINATION_CLAIMED, this.arena.getTeam(this.team) .getColoredName() + ChatColor.YELLOW)); - takeFlag(arena, loc, team); - domination.getFlagMap().put(loc, team); + this.takeFlag(this.arena, this.loc, this.team); + this.domination.getFlagMap().put(this.loc, this.team); // claim done. end timer - Bukkit.getScheduler().cancelTask(runID); - domination.getRunnerMap().remove(loc); + this.cancel(); + this.domination.getRunnerMap().remove(this.loc); } } else { // unclaim - arena.getDebugger().i("unclaimed"); - takeFlag(arena, loc, ""); - Bukkit.getScheduler().cancelTask(runID); - domination.getRunnerMap().remove(loc); - domination.getFlagMap().remove(loc); + this.arena.getDebugger().i("unclaimed"); + this.takeFlag(this.arena, this.loc, ""); + this.cancel(); + this.domination.getRunnerMap().remove(this.loc); + this.domination.getFlagMap().remove(this.loc); } } @@ -842,22 +826,24 @@ private void takeFlag(final Arena arena, final Location lBlock, final String nam } } if (team == null) { - flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(ChatColor.WHITE, flagBlock.getType())); - return; + ColorUtils.setNewFlagColor(flagBlock, ChatColor.WHITE); + } else { + ColorUtils.setNewFlagColor(flagBlock, team.getColor()); } - flagBlock.setType(ColorUtils.getColoredMaterialFromChatColor(team.getColor(), flagBlock.getType())); + } + + private boolean isTaken() { + return this.taken; } } - class DominationMainRunnable implements Runnable { - public int rID = -1; + private static class DominationMainRunnable extends BukkitRunnable { private final Arena arena; - //private final Debug debug = new Debug(39); private final GoalDomination domination; public DominationMainRunnable(final Arena arena, final GoalDomination goal) { this.arena = arena; - domination = goal; + this.domination = goal; arena.getDebugger().i("DominationMainRunnable constructor"); } @@ -866,10 +852,10 @@ public DominationMainRunnable(final Arena arena, final GoalDomination goal) { */ @Override public void run() { - if (!arena.isFightInProgress() || arena.realEndRunner != null) { - Bukkit.getScheduler().cancelTask(rID); + if (!this.arena.isFightInProgress() || this.arena.realEndRunner != null) { + this.cancel(); } - domination.checkMove(); + this.domination.checkMove(); } } } diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 47cd119b4..764dc332d 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -20,10 +20,11 @@ import net.slipcor.pvparena.managers.StatisticsManager.type; import net.slipcor.pvparena.managers.TeamManager; import net.slipcor.pvparena.runnables.EndRunnable; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; +import org.bukkit.*; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -52,26 +53,26 @@ public class GoalFlags extends ArenaGoal implements Listener { - public GoalFlags() { - super("Flags"); - debug = new Debug(100); - } - + private static final int PRIORITY = 6; + private static final String TOUCHDOWN = "touchdown"; private Map flagMap; private Map headGearMap; private String flagName = ""; + public GoalFlags() { + super("Flags"); + this.debug = new Debug(100); + } + @Override public String version() { return PVPArena.instance.getDescription().getVersion(); } - private static final int PRIORITY = 6; - @Override public boolean allowsJoinInBattle() { - return arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE); + return this.arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE); } @Override @@ -80,13 +81,11 @@ public PACheck checkCommand(final PACheck res, final String string) { return res; } - if ("flagtype".equalsIgnoreCase(string) - || "flageffect".equalsIgnoreCase(string) - || "touchdown".equalsIgnoreCase(string)) { + if ("flagtype".equalsIgnoreCase(string) || "flageffect".equalsIgnoreCase(string) || TOUCHDOWN.equalsIgnoreCase(string)) { res.setPriority(this, PRIORITY); } - for (final ArenaTeam team : arena.getTeams()) { + for (final ArenaTeam team : this.arena.getTeams()) { final String sTeam = team.getName(); if (string.contains(sTeam + "flag")) { res.setPriority(this, PRIORITY); @@ -98,9 +97,9 @@ public PACheck checkCommand(final PACheck res, final String string) { @Override public List getMain() { - final List result = Arrays.asList("flagtype", "flageffect", "touchdown"); - if (arena != null) { - for (final ArenaTeam team : arena.getTeams()) { + final List result = Arrays.asList("flagtype", "flageffect", TOUCHDOWN); + if (this.arena != null) { + for (final ArenaTeam team : this.arena.getTeams()) { final String sTeam = team.getName(); result.add(sTeam + "flag"); } @@ -122,12 +121,12 @@ public PACheck checkEnd(final PACheck res) { return res; } - final int count = TeamManager.countActiveTeams(arena); + final int count = TeamManager.countActiveTeams(this.arena); if (count == 1) { res.setPriority(this, PRIORITY); // yep. only one team left. go! } else if (count == 0) { - arena.getDebugger().i("No teams playing!"); + this.arena.getDebugger().i("No teams playing!"); } return res; @@ -135,12 +134,12 @@ public PACheck checkEnd(final PACheck res) { @Override public String checkForMissingSpawns(final Set list) { - final String team = checkForMissingTeamSpawn(list); + final String team = this.checkForMissingTeamSpawn(list); if (team != null) { return team; } - return checkForMissingTeamCustom(list, "flag"); + return this.checkForMissingTeamCustom(list, "flag"); } /** @@ -156,112 +155,109 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block if (block == null || res.getPriority() > PRIORITY) { return res; } - arena.getDebugger().i("checking interact", player); - if (arena.realEndRunner != null) { - arena.getDebugger().i("[CTF] already ending!!"); + this.arena.getDebugger().i("checking interact", player); + if (this.arena.realEndRunner != null) { + this.arena.getDebugger().i("[CTF] already ending!!"); return res; } - Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + Material flagType = this.arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); if (!ColorUtils.isSubType(block.getType(), flagType)) { - arena.getDebugger().i("block, but not flag", player); + this.arena.getDebugger().i("block, but not flag", player); return res; } - arena.getDebugger().i("flag click!", player); + this.arena.getDebugger().i("flag click!", player); Vector vLoc; Vector vFlag = null; final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); - if (getFlagMap().containsValue(player.getName())) { - arena.getDebugger().i("player " + player.getName() + " has got a flag", player); + if (this.getFlagMap().containsValue(player.getName())) { + this.arena.getDebugger().i("player " + player.getName() + " has got a flag", player); vLoc = block.getLocation().toVector(); final String sTeam = aPlayer.getArenaTeam().getName(); - arena.getDebugger().i("block: " + vLoc, player); - if (!SpawnManager.getBlocksStartingWith(arena, sTeam + "flag").isEmpty()) { + this.arena.getDebugger().i("block: " + vLoc, player); + if (!SpawnManager.getBlocksStartingWith(this.arena, sTeam + "flag").isEmpty()) { vFlag = SpawnManager .getBlockNearest( - SpawnManager.getBlocksStartingWith(arena, sTeam + "flag"), + SpawnManager.getBlocksStartingWith(this.arena, sTeam + "flag"), new PABlockLocation(player.getLocation())) .toLocation().toVector(); } else { - arena.getDebugger().i(sTeam + "flag = null", player); + this.arena.getDebugger().i(sTeam + "flag = null", player); } - arena.getDebugger().i("player is in the team " + sTeam, player); + this.arena.getDebugger().i("player is in the team " + sTeam, player); if (vFlag != null && vLoc.distance(vFlag) < 2) { - arena.getDebugger().i("player is at his flag", player); + this.arena.getDebugger().i("player is at his flag", player); - if (getFlagMap().containsKey(sTeam) - || getFlagMap().containsKey("touchdown")) { - arena.getDebugger().i("the flag of the own team is taken!", player); + if (this.getFlagMap().containsKey(sTeam) || this.getFlagMap().containsKey(TOUCHDOWN)) { + this.arena.getDebugger().i("the flag of the own team is taken!", player); - if (arena.getArenaConfig().getBoolean( + if (this.arena.getArenaConfig().getBoolean( CFG.GOAL_FLAGS_MUSTBESAFE) - && !getFlagMap().containsKey("touchdown")) { - arena.getDebugger().i("cancelling", player); + && !this.getFlagMap().containsKey(TOUCHDOWN)) { + this.arena.getDebugger().i("cancelling", player); - arena.msg(player, - Language.parse(arena, MSG.GOAL_FLAGS_NOTSAFE)); + this.arena.msg(player, + Language.parse(this.arena, MSG.GOAL_FLAGS_NOTSAFE)); return res; } } - String flagTeam = getHeldFlagTeam(player.getName()); + String flagTeam = this.getHeldFlagTeam(player.getName()); - arena.getDebugger().i("the flag belongs to team " + flagTeam, player); + this.arena.getDebugger().i("the flag belongs to team " + flagTeam, player); try { - if ("touchdown".equals(flagTeam)) { - arena.broadcast(Language.parse(arena, - MSG.GOAL_FLAGS_TOUCHHOME, arena.getTeam(sTeam) + if (TOUCHDOWN.equals(flagTeam)) { + this.arena.broadcast(Language.parse(this.arena, + MSG.GOAL_FLAGS_TOUCHHOME, this.arena.getTeam(sTeam) .colorizePlayer(player) + ChatColor.YELLOW, String - .valueOf(getLifeMap().get(aPlayer + .valueOf(this.getLifeMap().get(aPlayer .getArenaTeam().getName()) - 1))); } else { - arena.broadcast(Language.parse(arena, - MSG.GOAL_FLAGS_BROUGHTHOME, arena + this.arena.broadcast(Language.parse(this.arena, + MSG.GOAL_FLAGS_BROUGHTHOME, this.arena .getTeam(sTeam).colorizePlayer(player) + ChatColor.YELLOW, - arena.getTeam(flagTeam).getColoredName() + this.arena.getTeam(flagTeam).getColoredName() + ChatColor.YELLOW, String - .valueOf(getLifeMap().get(flagTeam) - 1))); + .valueOf(this.getLifeMap().get(flagTeam) - 1))); } - getFlagMap().remove(flagTeam); + this.getFlagMap().remove(flagTeam); } catch (final Exception e) { Bukkit.getLogger().severe( "[PVP Arena] team unknown/no lives: " + flagTeam); e.printStackTrace(); } - if ("touchdown".equals(flagTeam)) { - takeFlag(ChatColor.BLACK, false, - SpawnManager.getBlockByExactName(arena, "touchdownflag")); + if (TOUCHDOWN.equals(flagTeam)) { + this.releaseFlag(ChatColor.BLACK, this.getTeamFlagLoc(TOUCHDOWN)); } else { - takeFlag(arena.getTeam(flagTeam).getColor(), false, - SpawnManager.getBlockByExactName(arena, flagTeam + "flag")); + this.releaseFlag(this.arena.getTeam(flagTeam).getColor(), this.getTeamFlagLoc(flagTeam)); } - removeEffects(player); - if (arena.getArenaConfig().getBoolean( + this.removeEffects(player); + if (this.arena.getArenaConfig().getBoolean( CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { - if (getHeadGearMap().get(player.getName()) == null) { + if (this.getHeadGearMap().get(player.getName()) == null) { player.getInventory().setHelmet( new ItemStack(Material.AIR, 1)); } else { player.getInventory().setHelmet( - getHeadGearMap().get(player.getName()).clone()); - getHeadGearMap().remove(player.getName()); + this.getHeadGearMap().get(player.getName()).clone()); + this.getHeadGearMap().remove(player.getName()); } } - flagTeam = "touchdown".equals(flagTeam) ? flagTeam + ':' + aPlayer + flagTeam = TOUCHDOWN.equals(flagTeam) ? flagTeam + ':' + aPlayer .getArenaTeam().getName() : flagTeam; - reduceLivesCheckEndAndCommit(arena, flagTeam); // TODO move to + this.reduceLivesCheckEndAndCommit(this.arena, flagTeam); // TODO move to // "commit" ? - final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "trigger:" + aPlayer.getName()); + final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "trigger:" + aPlayer.getName()); Bukkit.getPluginManager().callEvent(gEvent); } } else { @@ -269,72 +265,72 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block if (pTeam == null) { return res; } - final Set setTeam = new HashSet<>(); - for (final ArenaTeam team : arena.getTeams()) { - setTeam.add(team); - } - setTeam.add(new ArenaTeam("touchdown", "BLACK")); + final Set setTeam = new HashSet<>(this.arena.getTeams()); + + setTeam.add(new ArenaTeam(TOUCHDOWN, "BLACK")); for (final ArenaTeam team : setTeam) { final String aTeam = team.getName(); if (aTeam.equals(pTeam.getName())) { - arena.getDebugger().i("equals!OUT! ", player); + this.arena.getDebugger().i("equals!OUT! ", player); continue; } - if (team.getTeamMembers().size() < 1 - && !"touchdown".equals(team.getName())) { - arena.getDebugger().i("size!OUT! ", player); + + if (team.getTeamMembers().size() < 1 && !TOUCHDOWN.equals(team.getName())) { + this.arena.getDebugger().i("size!OUT! ", player); continue; // dont check for inactive teams } - if (getFlagMap() != null && getFlagMap().containsKey(aTeam)) { - arena.getDebugger().i("taken!OUT! ", player); + + if (this.getFlagMap() != null && this.getFlagMap().containsKey(aTeam)) { + this.arena.getDebugger().i("taken!OUT! ", player); continue; // already taken } - arena.getDebugger().i("checking for flag of team " + aTeam, player); + + this.arena.getDebugger().i("checking for flag of team " + aTeam, player); vLoc = block.getLocation().toVector(); - arena.getDebugger().i("block: " + vLoc, player); - if (!SpawnManager.getBlocksStartingWith(arena, aTeam + "flag").isEmpty()) { + this.arena.getDebugger().i("block: " + vLoc, player); + + if (!SpawnManager.getBlocksStartingWith(this.arena, aTeam + "flag").isEmpty()) { vFlag = SpawnManager .getBlockNearest( - SpawnManager.getBlocksStartingWith(arena, aTeam + SpawnManager.getBlocksStartingWith(this.arena, aTeam + "flag"), new PABlockLocation(player.getLocation())) .toLocation().toVector(); } + if (vFlag != null && vLoc.distance(vFlag) < 2) { - arena.getDebugger().i("flag found!", player); - arena.getDebugger().i("vFlag: " + vFlag, player); + this.arena.getDebugger().i("flag found!", player); + this.arena.getDebugger().i("vFlag: " + vFlag, player); - if ("touchdown".equals(team.getName())) { + if (TOUCHDOWN.equals(team.getName())) { - arena.broadcast(Language.parse(arena, + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_GRABBEDTOUCH, pTeam.colorizePlayer(player) + ChatColor.YELLOW)); } else { - arena.broadcast(Language - .parse(arena, MSG.GOAL_FLAGS_GRABBED, + this.arena.broadcast(Language + .parse(this.arena, MSG.GOAL_FLAGS_GRABBED, pTeam.colorizePlayer(player) + ChatColor.YELLOW, team.getColoredName() + ChatColor.YELLOW)); } try { - getHeadGearMap().put(player.getName(), player.getInventory() - .getHelmet().clone()); - } catch (final Exception e) { + this.getHeadGearMap().put(player.getName(), player.getInventory().getHelmet().clone()); + } catch (final Exception ignored) { } - if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { - final ItemStack itemStack = new ItemStack(getFlagOverrideTeamMaterial(arena, aTeam)); + if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) { + final ItemStack itemStack = new ItemStack(this.getFlagOverrideTeamMaterial(this.arena, aTeam)); player.getInventory().setHelmet(itemStack); } - applyEffects(player); + this.applyEffects(player); - takeFlag(team.getColor(), true, - new PABlockLocation(block.getLocation())); - getFlagMap().put(aTeam, player.getName()); // TODO move to + this.takeFlag(new PABlockLocation(block.getLocation())); + this.getFlagMap().put(aTeam, player.getName()); // TODO move to // "commit" ? return res; @@ -346,7 +342,7 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block } private void applyEffects(final Player player) { - final String value = arena.getArenaConfig().getString( + final String value = this.arena.getArenaConfig().getString( CFG.GOAL_FLAGS_FLAGEFFECT); if ("none".equalsIgnoreCase(value)) { @@ -360,7 +356,7 @@ private void applyEffects(final Player player) { if (split.length > 1) { try { amp = Integer.parseInt(split[1]); - } catch (final Exception e) { + } catch (final Exception ignored) { } } @@ -390,12 +386,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St return res; } - final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS); - final int maxTeamPlayers = arena.getArenaConfig().getInt( + final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS); + final int maxTeamPlayers = this.arena.getArenaConfig().getInt( CFG.READY_MAXTEAMPLAYERS); - if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) { - res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL)); + if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) { + res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL)); return res; } @@ -403,12 +399,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St return res; } - if (!arena.isFreeForAll()) { - final ArenaTeam team = arena.getTeam(args[0]); + if (!this.arena.isFreeForAll()) { + final ArenaTeam team = this.arena.getTeam(args[0]); if (team != null && maxTeamPlayers > 0 && team.getTeamMembers().size() >= maxTeamPlayers) { - res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName())); + res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName())); return res; } } @@ -425,13 +421,13 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block return res; } - Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); + Material flagType = this.arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE); if (block == null || !ColorUtils.isSubType(block.getType(), flagType)) { return res; } if (!PVPArena.hasAdminPerms(player) - && !PVPArena.hasCreatePerms(player, arena)) { + && !PVPArena.hasCreatePerms(player, this.arena)) { return res; } res.setPriority(this, PRIORITY); // success :) @@ -487,7 +483,7 @@ private void commit(final Arena arena, final String sTeam, final boolean win) { + ChatColor.YELLOW)); } - getLifeMap().clear(); + this.getLifeMap().clear(); new EndRunnable(arena, arena.getArenaConfig().getInt( CFG.TIME_ENDCOUNTDOWN)); } @@ -496,9 +492,9 @@ private void commit(final Arena arena, final String sTeam, final boolean win) { public void commitCommand(final CommandSender sender, final String[] args) { if ("flagtype".equalsIgnoreCase(args[0])) { if (args.length < 2) { - arena.msg( + this.arena.msg( sender, - Language.parse(arena, MSG.ERROR_INVALID_ARGUMENT_COUNT, + Language.parse(this.arena, MSG.ERROR_INVALID_ARGUMENT_COUNT, String.valueOf(args.length), "2")); return; } @@ -506,35 +502,35 @@ public void commitCommand(final CommandSender sender, final String[] args) { final Material mat = Material.getMaterial(args[1].toUpperCase()); if (mat == null) { - arena.msg(sender, - Language.parse(arena, MSG.ERROR_MAT_NOT_FOUND, args[1])); + this.arena.msg(sender, + Language.parse(this.arena, MSG.ERROR_MAT_NOT_FOUND, args[1])); return; } - arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGTYPE, mat.name()); + this.arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGTYPE, mat.name()); - arena.getArenaConfig().save(); - arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_TYPESET, + this.arena.getArenaConfig().save(); + this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_TYPESET, CFG.GOAL_FLAGS_FLAGTYPE.toString())); } else if ("flageffect".equalsIgnoreCase(args[0])) { // /pa [arena] flageffect SLOW 2 if (args.length < 2) { - arena.msg( + this.arena.msg( sender, - Language.parse(arena, MSG.ERROR_INVALID_ARGUMENT_COUNT, + Language.parse(this.arena, MSG.ERROR_INVALID_ARGUMENT_COUNT, String.valueOf(args.length), "2")); return; } if ("none".equalsIgnoreCase(args[1])) { - arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, args[1]); + this.arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, args[1]); - arena.getArenaConfig().save(); - arena.msg( + this.arena.getArenaConfig().save(); + this.arena.msg( sender, - Language.parse(arena, MSG.SET_DONE, + Language.parse(this.arena, MSG.SET_DONE, CFG.GOAL_FLAGS_FLAGEFFECT.getNode(), args[1])); return; } @@ -552,7 +548,7 @@ public void commitCommand(final CommandSender sender, final String[] args) { } if (pet == null) { - arena.msg(sender, Language.parse(arena, + this.arena.msg(sender, Language.parse(this.arena, MSG.ERROR_POTIONEFFECTTYPE_NOTFOUND, args[1])); return; } @@ -563,52 +559,52 @@ public void commitCommand(final CommandSender sender, final String[] args) { try { amp = Integer.parseInt(args[2]); } catch (final Exception e) { - arena.msg(sender, - Language.parse(arena, MSG.ERROR_NOT_NUMERIC, args[2])); + this.arena.msg(sender, + Language.parse(this.arena, MSG.ERROR_NOT_NUMERIC, args[2])); return; } } final String value = args[1] + 'x' + amp; - arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, value); + this.arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, value); - arena.getArenaConfig().save(); - arena.msg( + this.arena.getArenaConfig().save(); + this.arena.msg( sender, - Language.parse(arena, MSG.SET_DONE, + Language.parse(this.arena, MSG.SET_DONE, CFG.GOAL_FLAGS_FLAGEFFECT.getNode(), value)); } else if (args[0].contains("flag")) { - for (final ArenaTeam team : arena.getTeams()) { + for (final ArenaTeam team : this.arena.getTeams()) { final String sTeam = team.getName(); if (args[0].contains(sTeam + "flag")) { - flagName = args[0]; - PAA_Region.activeSelections.put(sender.getName(), arena); + this.flagName = args[0]; + PAA_Region.activeSelections.put(sender.getName(), this.arena); - arena.msg(sender, - Language.parse(arena, MSG.GOAL_FLAGS_TOSET, flagName)); + this.arena.msg(sender, + Language.parse(this.arena, MSG.GOAL_FLAGS_TOSET, this.flagName)); } } - } else if ("touchdown".equalsIgnoreCase(args[0])) { - flagName = args[0] + "flag"; - PAA_Region.activeSelections.put(sender.getName(), arena); + } else if (TOUCHDOWN.equalsIgnoreCase(args[0])) { + this.flagName = args[0] + "flag"; + PAA_Region.activeSelections.put(sender.getName(), this.arena); - arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_TOSET, flagName)); + this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_TOSET, this.flagName)); } } @Override public void commitEnd(final boolean force) { - if (arena.realEndRunner != null) { - arena.getDebugger().i("[FLAGS] already ending"); + if (this.arena.realEndRunner != null) { + this.arena.getDebugger().i("[FLAGS] already ending"); return; } - arena.getDebugger().i("[FLAGS]"); + this.arena.getDebugger().i("[FLAGS]"); - final PAGoalEvent gEvent = new PAGoalEvent(arena, this, ""); + final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, ""); Bukkit.getPluginManager().callEvent(gEvent); ArenaTeam aTeam = null; - for (final ArenaTeam team : arena.getTeams()) { + for (final ArenaTeam team : this.arena.getTeams()) { for (final ArenaPlayer ap : team.getTeamMembers()) { if (ap.getStatus() == Status.FIGHT) { aTeam = team; @@ -619,40 +615,40 @@ public void commitEnd(final boolean force) { if (aTeam != null && !force) { ArenaModuleManager.announce( - arena, - Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena, + Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW), "END"); ArenaModuleManager.announce( - arena, - Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena, + Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW), "WINNER"); - arena.broadcast(Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor() + this.arena.broadcast(Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor() + aTeam.getName() + ChatColor.YELLOW)); } - if (ArenaModuleManager.commitEnd(arena, aTeam)) { + if (ArenaModuleManager.commitEnd(this.arena, aTeam)) { return; } - new EndRunnable(arena, arena.getArenaConfig().getInt( + new EndRunnable(this.arena, this.arena.getArenaConfig().getInt( CFG.TIME_ENDCOUNTDOWN)); } @Override public boolean commitSetFlag(final Player player, final Block block) { - arena.getDebugger().i("trying to set a flag", player); + this.arena.getDebugger().i("trying to set a flag", player); // command : /pa redflag1 // location: red1flag: - SpawnManager.setBlock(arena, new PABlockLocation(block.getLocation()), - flagName); + SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()), + this.flagName); - arena.msg(player, Language.parse(arena, MSG.GOAL_FLAGS_SET, flagName)); + this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, this.flagName)); PAA_Region.activeSelections.remove(player.getName()); - flagName = ""; + this.flagName = ""; return true; } @@ -669,76 +665,71 @@ public void configParse(final YamlConfiguration config) { @Override public void disconnect(final ArenaPlayer aPlayer) { - if (getFlagMap() == null) { + if (this.getFlagMap() == null) { return; } - final String sTeam = getHeldFlagTeam(aPlayer.getName()); - final ArenaTeam flagTeam = arena.getTeam(sTeam); + final String sTeam = this.getHeldFlagTeam(aPlayer.getName()); + final ArenaTeam flagTeam = this.arena.getTeam(sTeam); if (flagTeam == null) { if (sTeam == null) { return; } - arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer .getArenaTeam().getColorCodeString() + aPlayer.getName() + ChatColor.YELLOW)); - getFlagMap().remove("touchdown"); - if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) { + this.getFlagMap().remove(TOUCHDOWN); + if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) { if (aPlayer.get() != null) { aPlayer.get().getInventory() - .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone()); + .setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone()); } - getHeadGearMap().remove(aPlayer.getName()); + this.getHeadGearMap().remove(aPlayer.getName()); } - takeFlag(ChatColor.BLACK, false, - SpawnManager.getBlockByExactName(arena, "touchdownflag")); + this.releaseFlag(ChatColor.BLACK, this.getTeamFlagLoc(TOUCHDOWN)); return; } - arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPED, aPlayer + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPED, aPlayer .getArenaTeam().getColorCodeString() + aPlayer.getName() + ChatColor.YELLOW, flagTeam.getName() + ChatColor.YELLOW)); - getFlagMap().remove(flagTeam.getName()); - if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) { + this.getFlagMap().remove(flagTeam.getName()); + if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) { if (aPlayer.get() != null) { aPlayer.get().getInventory() - .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone()); + .setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone()); } - getHeadGearMap().remove(aPlayer.getName()); + this.getHeadGearMap().remove(aPlayer.getName()); } - takeFlag(flagTeam.getColor(), false, - SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag")); + this.releaseFlag(flagTeam.getColor(), this.getTeamFlagLoc(flagTeam.getName())); } @Override public void displayInfo(final CommandSender sender) { - sender.sendMessage("flageffect: " + - arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGEFFECT)); - sender.sendMessage("flagtype: " + - arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)); - sender.sendMessage("lives: " + - arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES)); - sender.sendMessage(StringParser.colorVar("mustbesafe", - arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_MUSTBESAFE)) + - " | " + StringParser.colorVar("flaghead", - arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD))); + Config cfg = this.arena.getArenaConfig(); + sender.sendMessage("flageffect: " + cfg.getString(CFG.GOAL_FLAGS_FLAGEFFECT)); + sender.sendMessage("flagtype: " + cfg.getString(CFG.GOAL_FLAGS_FLAGTYPE)); + sender.sendMessage("lives: " + cfg.getInt(CFG.GOAL_FLAGS_LIVES)); + sender.sendMessage(StringParser.colorVar("mustbesafe", cfg.getBoolean(CFG.GOAL_FLAGS_MUSTBESAFE)) + + " | " + StringParser.colorVar("flaghead", cfg.getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) + + " | " + StringParser.colorVar("alterOnCatch", cfg.getBoolean(CFG.GOAL_FLAGS_ALTERONCATCH))); } private Map getFlagMap() { - if (flagMap == null) { - flagMap = new HashMap<>(); + if (this.flagMap == null) { + this.flagMap = new HashMap<>(); } - return flagMap; + return this.flagMap; } private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) { if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) { - if ("touchdown".equals(team)) { + if (TOUCHDOWN.equals(team)) { return ColorUtils.getWoolMaterialFromChatColor(ChatColor.BLACK); } return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor()); @@ -752,17 +743,17 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) { if (res.getPriority() <= PRIORITY + 1000) { res.setError( this, - String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) + String.valueOf(this.getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0)) ); } return res; } private Map getHeadGearMap() { - if (headGearMap == null) { - headGearMap = new HashMap<>(); + if (this.headGearMap == null) { + this.headGearMap = new HashMap<>(); } - return headGearMap; + return this.headGearMap; } /** @@ -772,15 +763,15 @@ private Map getHeadGearMap() { * @return a team name */ private String getHeldFlagTeam(final String player) { - if (getFlagMap().size() < 1) { + if (this.getFlagMap().size() < 1) { return null; } - arena.getDebugger().i("getting held FLAG of player " + player, player); - for (final String sTeam : getFlagMap().keySet()) { - arena.getDebugger().i("team " + sTeam + " is in " + getFlagMap().get(sTeam) + this.arena.getDebugger().i("getting held FLAG of player " + player, player); + for (final String sTeam : this.getFlagMap().keySet()) { + this.arena.getDebugger().i("team " + sTeam + " is in " + this.getFlagMap().get(sTeam) + "s hands", player); - if (player.equals(getFlagMap().get(sTeam))) { + if (player.equals(this.getFlagMap().get(sTeam))) { return sTeam; } } @@ -789,14 +780,14 @@ private String getHeldFlagTeam(final String player) { @Override public boolean hasSpawn(final String string) { - for (final String teamName : arena.getTeamNames()) { + for (final String teamName : this.arena.getTeamNames()) { if (string.toLowerCase().startsWith( teamName.toLowerCase() + "spawn")) { return true; } - if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) { - for (final ArenaClass aClass : arena.getClasses()) { + if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) { + for (final ArenaClass aClass : this.arena.getClasses()) { if (string.toLowerCase().startsWith(teamName.toLowerCase() + aClass.getName().toLowerCase() + "spawn")) { return true; @@ -811,14 +802,12 @@ public boolean hasSpawn(final String string) { public void initate(final Player player) { final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); final ArenaTeam team = aPlayer.getArenaTeam(); - if (!getLifeMap().containsKey(team.getName())) { - getLifeMap().put(aPlayer.getArenaTeam().getName(), arena.getArenaConfig() + if (!this.getLifeMap().containsKey(team.getName())) { + this.getLifeMap().put(aPlayer.getArenaTeam().getName(), this.arena.getArenaConfig() .getInt(CFG.GOAL_FLAGS_LIVES)); - takeFlag(team.getColor(), false, - SpawnManager.getBlockByExactName(arena, team.getName() + "flag")); - takeFlag(ChatColor.BLACK, false, - SpawnManager.getBlockByExactName(arena, "touchdownflag")); + this.releaseFlag(team.getColor(), this.getTeamFlagLoc(team.getName())); + this.releaseFlag(ChatColor.BLACK, this.getTeamFlagLoc(TOUCHDOWN)); } } @@ -831,99 +820,90 @@ public boolean isInternal() { public void parsePlayerDeath(final Player player, final EntityDamageEvent lastDamageCause) { - if (getFlagMap() == null) { - arena.getDebugger().i("no flags set!!", player); + if (this.getFlagMap() == null) { + this.arena.getDebugger().i("no flags set!!", player); return; } - final String sTeam = getHeldFlagTeam(player.getName()); - final ArenaTeam flagTeam = arena.getTeam(sTeam); + final String sTeam = this.getHeldFlagTeam(player.getName()); + final ArenaTeam flagTeam = this.arena.getTeam(sTeam); final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName()); if (flagTeam == null) { if (sTeam == null) { return; } - arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer .getArenaTeam().getColorCodeString() + aPlayer.getName() + ChatColor.YELLOW)); - getFlagMap().remove("touchdown"); - if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) { + this.getFlagMap().remove(TOUCHDOWN); + if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) { if (aPlayer.get() != null) { aPlayer.get().getInventory() - .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone()); + .setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone()); } - getHeadGearMap().remove(aPlayer.getName()); + this.getHeadGearMap().remove(aPlayer.getName()); } - takeFlag(ChatColor.BLACK, false, - SpawnManager.getBlockByExactName(arena, "touchdownflag")); + this.releaseFlag(ChatColor.BLACK, this.getTeamFlagLoc(TOUCHDOWN)); return; } - arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPED, aPlayer + this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPED, aPlayer .getArenaTeam().colorizePlayer(player) + ChatColor.YELLOW, flagTeam.getColoredName() + ChatColor.YELLOW)); - getFlagMap().remove(flagTeam.getName()); - if (getHeadGearMap() != null - && getHeadGearMap().get(player.getName()) != null) { - player.getInventory().setHelmet( - getHeadGearMap().get(player.getName()).clone()); - getHeadGearMap().remove(player.getName()); + this.getFlagMap().remove(flagTeam.getName()); + if (this.getHeadGearMap() != null && this.getHeadGearMap().get(player.getName()) != null) { + player.getInventory().setHelmet(this.getHeadGearMap().get(player.getName()).clone()); + this.getHeadGearMap().remove(player.getName()); } - takeFlag(flagTeam.getColor(), false, - SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag")); + this.releaseFlag(flagTeam.getColor(), this.getTeamFlagLoc(flagTeam.getName())); } @Override public void parseStart() { - getLifeMap().clear(); - for (final ArenaTeam team : arena.getTeams()) { + this.getLifeMap().clear(); + for (final ArenaTeam team : this.arena.getTeams()) { if (!team.getTeamMembers().isEmpty()) { - arena.getDebugger().i("adding team " + team.getName()); + this.arena.getDebugger().i("adding team " + team.getName()); // team is active - getLifeMap().put(team.getName(), - arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES, 3)); + this.getLifeMap().put(team.getName(), + this.arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES, 3)); } - takeFlag(team.getColor(), false, - SpawnManager.getBlockByExactName(arena, team.getName() + "flag")); + this.releaseFlag(team.getColor(), this.getTeamFlagLoc(team.getName())); } - takeFlag(ChatColor.BLACK, false, - SpawnManager.getBlockByExactName(arena, "touchdownflag")); + this.releaseFlag(ChatColor.BLACK, this.getTeamFlagLoc(TOUCHDOWN)); } - private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String team) { + private void reduceLivesCheckEndAndCommit(final Arena arena, final String team) { arena.getDebugger().i("reducing lives of team " + team); - if (getLifeMap().get(team) == null) { + if (this.getLifeMap().get(team) == null) { if (team.contains(":")) { final String realTeam = team.split(":")[1]; - final int pos = getLifeMap().get(realTeam) - 1; + final int pos = this.getLifeMap().get(realTeam) - 1; if (pos > 0) { - getLifeMap().put(realTeam, pos); + this.getLifeMap().put(realTeam, pos); } else { - getLifeMap().remove(realTeam); - commit(arena, realTeam, true); - return true; + this.getLifeMap().remove(realTeam); + this.commit(arena, realTeam, true); } } } else { - final int pos = getLifeMap().get(team) - 1; + final int pos = this.getLifeMap().get(team) - 1; if (pos > 0) { - getLifeMap().put(team, pos); + this.getLifeMap().put(team, pos); } else { - getLifeMap().remove(team); - commit(arena, team, false); - return true; + this.getLifeMap().remove(team); + this.commit(arena, team, false); } } - return false; } private void removeEffects(final Player player) { - final String value = arena.getArenaConfig().getString( + final String value = this.arena.getArenaConfig().getString( CFG.GOAL_FLAGS_FLAGEFFECT); if ("none".equalsIgnoreCase(value)) { @@ -945,8 +925,7 @@ private void removeEffects(final Player player) { } if (pet == null) { - PVPArena.instance.getLogger().warning( - "Invalid Potion Effect Definition: " + value); + PVPArena.instance.getLogger().warning("Invalid Potion Effect Definition: " + value); return; } @@ -956,14 +935,14 @@ private void removeEffects(final Player player) { @Override public void reset(final boolean force) { - getFlagMap().clear(); - getHeadGearMap().clear(); - getLifeMap().clear(); + this.getFlagMap().clear(); + this.getHeadGearMap().clear(); + this.getLifeMap().clear(); } @Override public void setDefaults(final YamlConfiguration config) { - if (arena.isFreeForAll()) { + if (this.arena.isFreeForAll()) { return; } @@ -971,53 +950,80 @@ public void setDefaults(final YamlConfiguration config) { config.set("teams", null); } if (config.get("teams") == null) { - arena.getDebugger().i("no teams defined, adding custom red and blue!"); + this.arena.getDebugger().i("no teams defined, adding custom red and blue!"); config.addDefault("teams.red", ChatColor.RED.name()); config.addDefault("teams.blue", ChatColor.BLUE.name()); } - if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD) - && config.get("flagColors") == null) { - arena.getDebugger().i("no flagheads defined, adding white and black!"); - config.addDefault("flagColors.red", "WHITE"); - config.addDefault("flagColors.blue", "BLACK"); + if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD) && config.get("flagColors") == null) { + this.arena.getDebugger().i("no flagheads defined, adding white and black!"); + config.addDefault("flagColors.red", ChatColor.WHITE.name()); + config.addDefault("flagColors.blue", ChatColor.BLACK.name()); } } /** - * take/reset an arena flag + * take an arena flag * - * @param flagColor the teamcolor to reset - * @param take true if take, else reset * @param paBlockLocation the location to take/reset */ - void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocation paBlockLocation) { + private void takeFlag(final PABlockLocation paBlockLocation) { if (paBlockLocation == null) { return; } - if (!ColorUtils.isSubType(Material.getMaterial(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) { - paBlockLocation.toLocation() - .getBlock() - .setType( - take ? Material.BEDROCK : Material.valueOf(arena - .getArenaConfig().getString( - CFG.GOAL_FLAGS_FLAGTYPE))); + + if(this.arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_ALTERONCATCH)) { + Block flagBlock = paBlockLocation.toLocation().getBlock(); + + if (ColorUtils.isColorableMaterial(flagBlock.getType())) { + ColorUtils.setNewFlagColor(flagBlock, ChatColor.WHITE); + } else { + flagBlock.setType(Material.BEDROCK); + } + } + } + + /** + * reset an arena flag + * + * @param flagColor the teamcolor to reset + * @param paBlockLocation the location to take/reset + */ + private void releaseFlag(final ChatColor flagColor, final PABlockLocation paBlockLocation) { + if (paBlockLocation == null) { return; } - if (take) { - paBlockLocation.toLocation().getBlock() - .setType(Material.WHITE_WOOL); - } else { - paBlockLocation.toLocation().getBlock() - .setType(ColorUtils.getWoolMaterialFromChatColor(flagColor)); + + if(this.arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_ALTERONCATCH)) { + Block flagBlock = paBlockLocation.toLocation().getBlock(); + + if (ColorUtils.isColorableMaterial(flagBlock.getType())) { + ColorUtils.setNewFlagColor(flagBlock, flagColor); + } else { + flagBlock.setType(this.arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE)); + } + } + } + + private void setNewBlockData(Block block, Material newMaterial) { + final BlockData originalBlockData = block.getBlockData().clone(); + BlockData newData = Bukkit.getServer().createBlockData(newMaterial); + + if(originalBlockData instanceof Directional) { + ((Directional) newData).setFacing(((Directional) originalBlockData).getFacing()); + } + + if(originalBlockData instanceof Rotatable) { + ((Rotatable) newData).setRotation(((Rotatable) originalBlockData).getRotation()); } + + block.setBlockData(newData); } @Override public Map timedEnd(final Map scores) { - for (final ArenaTeam team : arena.getTeams()) { - double score = getLifeMap().containsKey(team.getName()) ? getLifeMap() - .get(team.getName()) : 0; + for (final ArenaTeam team : this.arena.getTeams()) { + double score = this.getLifeMap().getOrDefault(team.getName(), 0); if (scores.containsKey(team.getName())) { scores.put(team.getName(), scores.get(team.getName()) + score); } else { @@ -1030,9 +1036,9 @@ public Map timedEnd(final Map scores) { @Override public void unload(final Player player) { - disconnect(ArenaPlayer.parsePlayer(player.getName())); - if (allowsJoinInBattle()) { - arena.hasNotPlayed(ArenaPlayer.parsePlayer(player.getName())); + this.disconnect(ArenaPlayer.parsePlayer(player.getName())); + if (this.allowsJoinInBattle()) { + this.arena.hasNotPlayed(ArenaPlayer.parsePlayer(player.getName())); } } @@ -1046,8 +1052,7 @@ public void onInventoryClick(final InventoryClickEvent event) { return; } - if (event.isCancelled() - || getHeldFlagTeam(player.getName()) == null) { + if (event.isCancelled() || this.getHeldFlagTeam(player.getName()) == null) { return; } @@ -1060,4 +1065,8 @@ public void onInventoryClick(final InventoryClickEvent event) { event.setCancelled(true); } } + + private PABlockLocation getTeamFlagLoc(String teamName) { + return SpawnManager.getBlockByExactName(this.arena, teamName + "flag"); + } } diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java index 091255b11..8415fb1c2 100644 --- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java @@ -23,6 +23,7 @@ import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -40,6 +41,8 @@ import java.util.*; +import static java.util.Optional.ofNullable; + /** *
  * Arena Goal class "PhysicalFlags"
@@ -52,26 +55,27 @@
 
 public class GoalPhysicalFlags extends ArenaGoal implements Listener {
 
-    public GoalPhysicalFlags() {
-        super("PhysicalFlags");
-        debug = new Debug(100);
-    }
-
+    private static final int PRIORITY = 7;
+    private static final String TOUCHDOWN = "touchdown";
     private Map flagMap;
+    private Map flagDataMap;
     private Map headGearMap;
 
     private String flagName = "";
 
+    public GoalPhysicalFlags() {
+        super("PhysicalFlags");
+        this.debug = new Debug(100);
+    }
+
     @Override
     public String version() {
         return PVPArena.instance.getDescription().getVersion();
     }
 
-    private static final int PRIORITY = 7;
-
     @Override
     public boolean allowsJoinInBattle() {
-        return arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
+        return this.arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
     }
 
     @Override
@@ -80,13 +84,11 @@ public PACheck checkCommand(final PACheck res, final String string) {
             return res;
         }
 
-        if ("flagtype".equalsIgnoreCase(string)
-                || "flageffect".equalsIgnoreCase(string)
-                || "touchdown".equalsIgnoreCase(string)) {
+        if ("flagtype".equalsIgnoreCase(string) || "flageffect".equalsIgnoreCase(string) || TOUCHDOWN.equalsIgnoreCase(string)) {
             res.setPriority(this, PRIORITY);
         }
 
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             final String sTeam = team.getName();
             if (string.contains(sTeam + "flag")) {
                 res.setPriority(this, PRIORITY);
@@ -98,9 +100,9 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList("flagtype", "flageffect", "touchdown");
-        if (arena != null) {
-            for (final ArenaTeam team : arena.getTeams()) {
+        final List result = Arrays.asList("flagtype", "flageffect", TOUCHDOWN);
+        if (this.arena != null) {
+            for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
                 result.add(sTeam + "flag");
             }
@@ -122,12 +124,12 @@ public PACheck checkEnd(final PACheck res) {
             return res;
         }
 
-        final int count = TeamManager.countActiveTeams(arena);
+        final int count = TeamManager.countActiveTeams(this.arena);
 
         if (count == 1) {
             res.setPriority(this, PRIORITY); // yep. only one team left. go!
         } else if (count == 0) {
-            arena.getDebugger().i("No teams playing!");
+            this.arena.getDebugger().i("No teams playing!");
         }
 
         return res;
@@ -135,11 +137,11 @@ public PACheck checkEnd(final PACheck res) {
 
     @Override
     public String checkForMissingSpawns(final Set list) {
-        final String team = checkForMissingTeamSpawn(list);
+        final String team = this.checkForMissingTeamSpawn(list);
         if (team != null) {
             return team;
         }
-        return checkForMissingTeamCustom(list, "flag");
+        return this.checkForMissingTeamCustom(list, "flag");
     }
 
     /**
@@ -150,140 +152,128 @@ public String checkForMissingSpawns(final Set list) {
      * @param block  the block being clicked
      * @return the PACheck instance
      */
-    @SuppressWarnings("deprecation")
     @Override
     public PACheck checkInteract(final PACheck res, final Player player, final Block block) {
         if (block == null || res.getPriority() > PRIORITY) {
             return res;
         }
-        arena.getDebugger().i("checking interact", player);
+        this.arena.getDebugger().i("checking interact", player);
 
-        Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
+        Material flagType = this.arena.getArenaConfig().getMaterial(CFG.GOAL_PFLAGS_FLAGTYPE);
         if (!ColorUtils.isSubType(block.getType(), flagType)) {
-            arena.getDebugger().i("block, but not flag", player);
+            this.arena.getDebugger().i("block, but not flag", player);
             return res;
         }
-        arena.getDebugger().i("flag click!", player);
+        this.arena.getDebugger().i("flag click!", player);
 
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
 
-        if (getFlagMap().containsValue(player.getName())) {
-            arena.getDebugger().i("player " + player.getName() + " has got a flag", player);
+        if (this.getFlagMap().containsValue(player.getName())) {
+            this.arena.getDebugger().i("player " + player.getName() + " has got a flag", player);
 
             final Vector vLoc = block.getLocation().toVector();
             final String sTeam = aPlayer.getArenaTeam().getName();
-            arena.getDebugger().i("block: " + vLoc, player);
+            this.arena.getDebugger().i("block: " + vLoc, player);
             Vector vFlag = null;
-            if (!SpawnManager.getBlocksStartingWith(arena, sTeam + "flag").isEmpty()) {
-                vFlag = SpawnManager
-                        .getBlockNearest(
-                                SpawnManager.getBlocksStartingWith(arena, sTeam + "flag"),
-                                new PABlockLocation(player.getLocation()))
-                        .toLocation().toVector();
+            if (this.getTeamFlagLoc(sTeam) != null) {
+                vFlag = this.getTeamFlagLoc(sTeam).toLocation().toVector();
             } else {
-                arena.getDebugger().i(sTeam + "flag = null", player);
+                this.arena.getDebugger().i(sTeam + "flag = null", player);
             }
 
-            arena.getDebugger().i("player is in the team " + sTeam, player);
+            this.arena.getDebugger().i("player is in the team " + sTeam, player);
             if (vFlag != null && vLoc.distance(vFlag) < 2) {
 
-                arena.getDebugger().i("player is at his flag", player);
+                this.arena.getDebugger().i("player is at his flag", player);
 
-                if (getFlagMap().containsKey(sTeam)
-                        || getFlagMap().containsKey("touchdown")) {
-                    arena.getDebugger().i("the flag of the own team is taken!", player);
+                if (this.getFlagMap().containsKey(sTeam) || this.getFlagMap().containsKey(TOUCHDOWN)) {
+                    this.arena.getDebugger().i("the flag of the own team is taken!", player);
 
-                    if (arena.getArenaConfig().getBoolean(
-                            CFG.GOAL_FLAGS_MUSTBESAFE)
-                            && !getFlagMap().containsKey("touchdown")) {
-                        arena.getDebugger().i("cancelling", player);
+                    if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_PFLAGS_MUSTBESAFE)
+                            && !this.getFlagMap().containsKey(TOUCHDOWN)) {
+                        this.arena.getDebugger().i("cancelling", player);
 
-                        arena.msg(player,
-                                Language.parse(arena, MSG.GOAL_FLAGS_NOTSAFE));
+                        this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_NOTSAFE));
                         return res;
                     }
                 }
 
-                String flagTeam = getHeldFlagTeam(player.getName());
-
-                arena.getDebugger().i("the flag belongs to team " + flagTeam, player);
-
-                if (player.getItemInHand() == null
-                        || !player
-                        .getItemInHand()
-                        .getType()
-                        .name()
-                        .equals(arena.getArenaConfig().getString(
-                                CFG.GOAL_FLAGS_FLAGTYPE))) {
-                    arena.getDebugger().i("player " + player.getName()
-                            + " is not holding the flag", player);
-                    arena.msg(player,
-                            Language.parse(arena, MSG.GOAL_PHYSICALFLAGS_HOLDFLAG));
+                String flagTeam = this.getHeldFlagTeam(player.getName());
+
+                this.arena.getDebugger().i("the flag belongs to team " + flagTeam, player);
+
+                ItemStack mainHandItem = player.getInventory().getItemInMainHand();
+                if (!ColorUtils.isSubType(mainHandItem.getType(), flagType)) {
+                    this.arena.getDebugger().i("player " + player.getName() + " is not holding the flag", player);
+                    this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_PHYSICALFLAGS_HOLDFLAG));
                     return res;
                 }
 
-                player.getInventory().remove(player.getItemInHand());
+                player.getInventory().remove(mainHandItem);
                 player.updateInventory();
 
                 try {
-                    if ("touchdown".equals(flagTeam)) {
-                        arena.broadcast(Language.parse(arena,
-                                MSG.GOAL_FLAGS_TOUCHHOME, arena.getTeam(sTeam)
+                    if (TOUCHDOWN.equals(flagTeam)) {
+                        this.arena.broadcast(Language.parse(this.arena,
+                                MSG.GOAL_FLAGS_TOUCHHOME, this.arena.getTeam(sTeam)
                                         .colorizePlayer(player)
                                         + ChatColor.YELLOW, String
-                                        .valueOf(getLifeMap().get(aPlayer
+                                        .valueOf(this.getLifeMap().get(aPlayer
                                                 .getArenaTeam().getName()) - 1)));
                     } else {
-                        arena.broadcast(Language.parse(arena,
-                                MSG.GOAL_FLAGS_BROUGHTHOME, arena
+                        this.arena.broadcast(Language.parse(this.arena,
+                                MSG.GOAL_FLAGS_BROUGHTHOME, this.arena
                                         .getTeam(sTeam).colorizePlayer(player)
                                         + ChatColor.YELLOW,
-                                arena.getTeam(flagTeam).getColoredName()
+                                this.arena.getTeam(flagTeam).getColoredName()
                                         + ChatColor.YELLOW, String
-                                        .valueOf(getLifeMap().get(flagTeam) - 1)));
+                                        .valueOf(this.getLifeMap().get(flagTeam) - 1)));
                     }
-                    getFlagMap().remove(flagTeam);
+                    this.getFlagMap().remove(flagTeam);
                 } catch (final Exception e) {
                     Bukkit.getLogger().severe(
                             "[PVP Arena] team unknown/no lives: " + flagTeam);
                     e.printStackTrace();
                 }
-                if ("touchdown".equals(flagTeam)) {
-                    takeFlag(ChatColor.BLACK, false,
-                            SpawnManager.getBlockByExactName(arena, "touchdownflag"));
+                if (TOUCHDOWN.equals(flagTeam)) {
+                    this.releaseFlag(TOUCHDOWN);
                 } else {
-                    takeFlag(arena.getTeam(flagTeam).getColor(), false,
-                            SpawnManager.getBlockByExactName(arena, flagTeam + "flag"));
+                    this.releaseFlag(flagTeam);
                 }
-                removeEffects(player);
-                if (arena.getArenaConfig().getBoolean(
-                        CFG.GOAL_FLAGS_WOOLFLAGHEAD)) {
-                    player.getInventory().setHelmet(
-                            new ItemStack(Material.AIR, 1));
+                this.removeEffects(player);
+                if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_PFLAGS_WOOLFLAGHEAD)) {
+                    player.getInventory().setHelmet(new ItemStack(Material.AIR, 1));
                 } else {
-                    if (getHeadGearMap().get(player.getName()) == null) {
-                        player.getInventory().setHelmet(
-                                getHeadGearMap().get(player.getName()).clone());
-                        getHeadGearMap().remove(player.getName());
+                    if (this.getHeadGearMap().get(player.getName()) == null) {
+                        player.getInventory().setHelmet(this.getHeadGearMap().get(player.getName()).clone());
+                        this.getHeadGearMap().remove(player.getName());
                     }
                 }
 
-                flagTeam = "touchdown".equals(flagTeam) ? flagTeam + ':' + aPlayer
-                        .getArenaTeam().getName() : flagTeam;
+                flagTeam = TOUCHDOWN.equals(flagTeam) ? flagTeam + ':' + aPlayer.getArenaTeam().getName() : flagTeam;
 
-                reduceLivesCheckEndAndCommit(arena, flagTeam);
+                this.reduceLivesCheckEndAndCommit(this.arena, flagTeam);
 
-                final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "trigger:" + player.getName());
+                final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "trigger:" + player.getName());
                 Bukkit.getPluginManager().callEvent(gEvent);
+
+                // used to cancel block put event
+                res.setPriority(this, PRIORITY);
             }
         }
 
         return res;
     }
 
+    @Override
+    public void commitInteract(final Player player, final Block clickedBlock) {}
+
+    private PABlockLocation getTeamFlagLoc(String teamName) {
+        return SpawnManager.getBlockByExactName(this.arena, teamName + "flag");
+    }
+
     private void applyEffects(final Player player) {
-        final String value = arena.getArenaConfig().getString(
-                CFG.GOAL_FLAGS_FLAGEFFECT);
+        final String value = this.arena.getArenaConfig().getString(CFG.GOAL_PFLAGS_FLAGEFFECT);
 
         if ("none".equalsIgnoreCase(value)) {
             return;
@@ -296,7 +286,7 @@ private void applyEffects(final Player player) {
         if (split.length > 1) {
             try {
                 amp = Integer.parseInt(split[1]);
-            } catch (final Exception e) {
+            } catch (final Exception ignored) {
 
             }
         }
@@ -327,12 +317,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
-        final int maxTeamPlayers = arena.getArenaConfig().getInt(
+        final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
+        final int maxTeamPlayers = this.arena.getArenaConfig().getInt(
                 CFG.READY_MAXTEAMPLAYERS);
 
-        if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) {
-            res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL));
+        if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) {
+            res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL));
             return res;
         }
 
@@ -340,12 +330,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        if (!arena.isFreeForAll()) {
-            final ArenaTeam team = arena.getTeam(args[0]);
+        if (!this.arena.isFreeForAll()) {
+            final ArenaTeam team = this.arena.getTeam(args[0]);
 
             if (team != null && maxTeamPlayers > 0
                     && team.getTeamMembers().size() >= maxTeamPlayers) {
-                res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
+                res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
                 return res;
             }
         }
@@ -357,18 +347,16 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
     @Override
     public PACheck checkSetBlock(final PACheck res, final Player player, final Block block) {
 
-        if (res.getPriority() > PRIORITY
-                || !PAA_Region.activeSelections.containsKey(player.getName())) {
+        if (res.getPriority() > PRIORITY || !PAA_Region.activeSelections.containsKey(player.getName())) {
             return res;
         }
 
-        Material flagType = arena.getArenaConfig().getMaterial(CFG.GOAL_FLAGS_FLAGTYPE);
+        Material flagType = this.arena.getArenaConfig().getMaterial(CFG.GOAL_PFLAGS_FLAGTYPE);
         if (block == null || !ColorUtils.isSubType(block.getType(), flagType)) {
             return res;
         }
 
-        if (!PVPArena.hasAdminPerms(player)
-                && !PVPArena.hasCreatePerms(player, arena)) {
+        if (!PVPArena.hasAdminPerms(player) && !PVPArena.hasCreatePerms(player, this.arena)) {
             return res;
         }
         res.setPriority(this, PRIORITY); // success :)
@@ -424,18 +412,18 @@ private void commit(final Arena arena, final String sTeam, final boolean win) {
                             + ChatColor.YELLOW));
         }
 
-        getLifeMap().clear();
-        new EndRunnable(arena, arena.getArenaConfig().getInt(
-                CFG.TIME_ENDCOUNTDOWN));
+        this.getLifeMap().clear();
+        this.getFlagDataMap().clear();
+        new EndRunnable(arena, arena.getArenaConfig().getInt(CFG.TIME_ENDCOUNTDOWN));
     }
 
     @Override
     public void commitCommand(final CommandSender sender, final String[] args) {
         if ("flagtype".equalsIgnoreCase(args[0])) {
             if (args.length < 2) {
-                arena.msg(
+                this.arena.msg(
                         sender,
-                        Language.parse(arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
+                        Language.parse(this.arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
                                 String.valueOf(args.length), "2"));
                 return;
             }
@@ -443,36 +431,36 @@ public void commitCommand(final CommandSender sender, final String[] args) {
             final Material mat = Material.getMaterial(args[1].toUpperCase());
 
             if (mat == null) {
-                arena.msg(sender,
-                        Language.parse(arena, MSG.ERROR_MAT_NOT_FOUND, args[1]));
+                this.arena.msg(sender,
+                        Language.parse(this.arena, MSG.ERROR_MAT_NOT_FOUND, args[1]));
                 return;
             }
 
-            arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGTYPE, mat.name());
+            this.arena.getArenaConfig().set(CFG.GOAL_PFLAGS_FLAGTYPE, mat.name());
 
-            arena.getArenaConfig().save();
-            arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_TYPESET,
-                    CFG.GOAL_FLAGS_FLAGTYPE.toString()));
+            this.arena.getArenaConfig().save();
+            this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_TYPESET,
+                    CFG.GOAL_PFLAGS_FLAGTYPE.toString()));
 
         } else if ("flageffect".equalsIgnoreCase(args[0])) {
 
             // /pa [arena] flageffect SLOW 2
             if (args.length < 2) {
-                arena.msg(
+                this.arena.msg(
                         sender,
-                        Language.parse(arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
+                        Language.parse(this.arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
                                 String.valueOf(args.length), "2"));
                 return;
             }
 
             if ("none".equalsIgnoreCase(args[1])) {
-                arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, args[1]);
+                this.arena.getArenaConfig().set(CFG.GOAL_PFLAGS_FLAGEFFECT, args[1]);
 
-                arena.getArenaConfig().save();
-                arena.msg(
+                this.arena.getArenaConfig().save();
+                this.arena.msg(
                         sender,
-                        Language.parse(arena, MSG.SET_DONE,
-                                CFG.GOAL_FLAGS_FLAGEFFECT.getNode(), args[1]));
+                        Language.parse(this.arena, MSG.SET_DONE,
+                                CFG.GOAL_PFLAGS_FLAGEFFECT.getNode(), args[1]));
                 return;
             }
 
@@ -489,7 +477,7 @@ public void commitCommand(final CommandSender sender, final String[] args) {
             }
 
             if (pet == null) {
-                arena.msg(sender, Language.parse(arena,
+                this.arena.msg(sender, Language.parse(this.arena,
                         MSG.ERROR_POTIONEFFECTTYPE_NOTFOUND, args[1]));
                 return;
             }
@@ -500,52 +488,52 @@ public void commitCommand(final CommandSender sender, final String[] args) {
                 try {
                     amp = Integer.parseInt(args[2]);
                 } catch (final Exception e) {
-                    arena.msg(sender,
-                            Language.parse(arena, MSG.ERROR_NOT_NUMERIC, args[2]));
+                    this.arena.msg(sender,
+                            Language.parse(this.arena, MSG.ERROR_NOT_NUMERIC, args[2]));
                     return;
                 }
             }
             final String value = args[1] + 'x' + amp;
-            arena.getArenaConfig().set(CFG.GOAL_FLAGS_FLAGEFFECT, value);
+            this.arena.getArenaConfig().set(CFG.GOAL_PFLAGS_FLAGEFFECT, value);
 
-            arena.getArenaConfig().save();
-            arena.msg(
+            this.arena.getArenaConfig().save();
+            this.arena.msg(
                     sender,
-                    Language.parse(arena, MSG.SET_DONE,
-                            CFG.GOAL_FLAGS_FLAGEFFECT.getNode(), value));
+                    Language.parse(this.arena, MSG.SET_DONE,
+                            CFG.GOAL_PFLAGS_FLAGEFFECT.getNode(), value));
 
         } else if (args[0].contains("flag")) {
-            for (final ArenaTeam team : arena.getTeams()) {
+            for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
                 if (args[0].contains(sTeam + "flag")) {
-                    flagName = args[0];
-                    PAA_Region.activeSelections.put(sender.getName(), arena);
+                    this.flagName = args[0];
+                    PAA_Region.activeSelections.put(sender.getName(), this.arena);
 
-                    arena.msg(sender,
-                            Language.parse(arena, MSG.GOAL_FLAGS_TOSET, flagName));
+                    this.arena.msg(sender,
+                            Language.parse(this.arena, MSG.GOAL_FLAGS_TOSET, this.flagName));
                 }
             }
-        } else if ("touchdown".equalsIgnoreCase(args[0])) {
-            flagName = args[0] + "flag";
-            PAA_Region.activeSelections.put(sender.getName(), arena);
+        } else if (TOUCHDOWN.equalsIgnoreCase(args[0])) {
+            this.flagName = args[0] + "flag";
+            PAA_Region.activeSelections.put(sender.getName(), this.arena);
 
-            arena.msg(sender, Language.parse(arena, MSG.GOAL_FLAGS_TOSET, flagName));
+            this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_FLAGS_TOSET, this.flagName));
         }
     }
 
     @Override
     public void commitEnd(final boolean force) {
-        if (arena.realEndRunner != null) {
-            arena.getDebugger().i("[FLAGS] already ending");
+        if (this.arena.realEndRunner != null) {
+            this.arena.getDebugger().i("[FLAGS] already ending");
             return;
         }
-        arena.getDebugger().i("[FLAGS]");
+        this.arena.getDebugger().i("[FLAGS]");
 
-        final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "");
+        final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "");
         Bukkit.getPluginManager().callEvent(gEvent);
         ArenaTeam aTeam = null;
 
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             for (final ArenaPlayer ap : team.getTeamMembers()) {
                 if (ap.getStatus() == Status.FIGHT) {
                     aTeam = team;
@@ -556,40 +544,38 @@ public void commitEnd(final boolean force) {
 
         if (aTeam != null && !force) {
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+                    this.arena,
+                    Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                             + aTeam.getName() + ChatColor.YELLOW), "END");
 
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+                    this.arena,
+                    Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                             + aTeam.getName() + ChatColor.YELLOW), "WINNER");
-            arena.broadcast(Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+            this.arena.broadcast(Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                     + aTeam.getName() + ChatColor.YELLOW));
         }
 
-        if (ArenaModuleManager.commitEnd(arena, aTeam)) {
+        if (ArenaModuleManager.commitEnd(this.arena, aTeam)) {
             return;
         }
-        new EndRunnable(arena, arena.getArenaConfig().getInt(
-                CFG.TIME_ENDCOUNTDOWN));
+        new EndRunnable(this.arena, this.arena.getArenaConfig().getInt(CFG.TIME_ENDCOUNTDOWN));
     }
 
     @Override
     public boolean commitSetFlag(final Player player, final Block block) {
 
-        arena.getDebugger().i("trying to set a flag", player);
+        this.arena.getDebugger().i("trying to set a flag", player);
 
         // command : /pa redflag1
         // location: red1flag:
 
-        SpawnManager.setBlock(arena, new PABlockLocation(block.getLocation()),
-                flagName);
+        SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()), this.flagName);
 
-        arena.msg(player, Language.parse(arena, MSG.GOAL_FLAGS_SET, flagName));
+        this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, this.flagName));
 
         PAA_Region.activeSelections.remove(player.getName());
-        flagName = "";
+        this.flagName = "";
 
         return true;
     }
@@ -605,74 +591,75 @@ public void configParse(final YamlConfiguration config) {
 
     @Override
     public void disconnect(final ArenaPlayer aPlayer) {
-        if (getFlagMap() == null) {
+        if (this.getFlagMap().isEmpty()) {
             return;
         }
-        final String sTeam = getHeldFlagTeam(aPlayer.getName());
-        final ArenaTeam flagTeam = arena.getTeam(sTeam);
+        final String sTeam = this.getHeldFlagTeam(aPlayer.getName());
+        final ArenaTeam flagTeam = this.arena.getTeam(sTeam);
 
         if (flagTeam == null) {
             if (sTeam != null) {
-                arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer
+                this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer
                         .getArenaTeam().getColorCodeString()
                         + aPlayer.getName()
                         + ChatColor.YELLOW));
 
-                getFlagMap().remove("touchdown");
-                if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) {
+                this.getFlagMap().remove(TOUCHDOWN);
+                if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) {
                     if (aPlayer.get() != null) {
                         aPlayer.get().getInventory()
-                                .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone());
+                                .setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone());
                     }
-                    getHeadGearMap().remove(aPlayer.getName());
+                    this.getHeadGearMap().remove(aPlayer.getName());
                 }
 
-                takeFlag(ChatColor.BLACK, false,
-                        SpawnManager.getBlockByExactName(arena, "touchdownflag"));
+                this.releaseFlag(TOUCHDOWN);
             }
         } else {
-            arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPED, aPlayer
+            this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPED, aPlayer
                     .getArenaTeam().getColorCodeString()
                     + aPlayer.getName()
                     + ChatColor.YELLOW, flagTeam.getName() + ChatColor.YELLOW));
-            getFlagMap().remove(flagTeam.getName());
-            if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) {
+            this.getFlagMap().remove(flagTeam.getName());
+            if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) {
                 if (aPlayer.get() != null) {
                     aPlayer.get().getInventory()
-                            .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone());
+                            .setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone());
                 }
-                getHeadGearMap().remove(aPlayer.getName());
+                this.getHeadGearMap().remove(aPlayer.getName());
             }
 
-            takeFlag(flagTeam.getColor(), false,
-                    SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
+            this.releaseFlag(flagTeam.getName());
         }
     }
 
     @Override
     public void displayInfo(final CommandSender sender) {
-        sender.sendMessage("flageffect: " +
-                arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGEFFECT));
-        sender.sendMessage("flagtype: " +
-                arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE));
-        sender.sendMessage("lives: " +
-                arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES));
-        sender.sendMessage(StringParser.colorVar("mustbesafe",
-                arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_MUSTBESAFE)) +
-                " | " + StringParser.colorVar("flaghead",
-                arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)));
+        Config cfg = this.arena.getArenaConfig();
+        sender.sendMessage("flageffect: " + cfg.getString(CFG.GOAL_PFLAGS_FLAGEFFECT));
+        sender.sendMessage("flagtype: " + cfg.getString(CFG.GOAL_PFLAGS_FLAGTYPE));
+        sender.sendMessage("lives: " + cfg.getInt(CFG.GOAL_PFLAGS_LIVES));
+        sender.sendMessage(StringParser.colorVar("mustbesafe", cfg.getBoolean(CFG.GOAL_PFLAGS_MUSTBESAFE))
+                + " | " + StringParser.colorVar("flaghead", cfg.getBoolean(CFG.GOAL_PFLAGS_WOOLFLAGHEAD)));
     }
 
     private Map getFlagMap() {
-        if (flagMap == null) {
-            flagMap = new HashMap<>();
+        if (this.flagMap == null) {
+            this.flagMap = new HashMap<>();
+        }
+        return this.flagMap;
+    }
+
+    private Map getFlagDataMap() {
+        if (this.flagDataMap == null) {
+            this.flagDataMap = new HashMap<>();
         }
-        return flagMap;
+        return this.flagDataMap;
     }
 
     private Material getFlagOverrideTeamMaterial(final Arena arena, final String team) {
         if (arena.getArenaConfig().getUnsafe("flagColors." + team) == null) {
-            if ("touchdown".equals(team)) {
+            if (TOUCHDOWN.equals(team)) {
                 return ColorUtils.getWoolMaterialFromChatColor(ChatColor.BLACK);
             }
             return ColorUtils.getWoolMaterialFromChatColor(arena.getTeam(team).getColor());
@@ -686,17 +673,17 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
         if (res.getPriority() <= PRIORITY + 1000) {
             res.setError(
                     this,
-                    String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0))
+                    String.valueOf(this.getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0))
             );
         }
         return res;
     }
 
     private Map getHeadGearMap() {
-        if (headGearMap == null) {
-            headGearMap = new HashMap<>();
+        if (this.headGearMap == null) {
+            this.headGearMap = new HashMap<>();
         }
-        return headGearMap;
+        return this.headGearMap;
     }
 
     /**
@@ -706,15 +693,14 @@ private Map getHeadGearMap() {
      * @return a team name
      */
     private String getHeldFlagTeam(final String player) {
-        if (getFlagMap().size() < 1) {
+        if (this.getFlagMap().isEmpty()) {
             return null;
         }
 
-        arena.getDebugger().i("getting held FLAG of player " + player, player);
-        for (final String sTeam : getFlagMap().keySet()) {
-            arena.getDebugger().i("team " + sTeam + " is in " + getFlagMap().get(sTeam)
-                    + "s hands", player);
-            if (player.equals(getFlagMap().get(sTeam))) {
+        this.arena.getDebugger().i("getting held FLAG of player " + player, player);
+        for (final String sTeam : this.getFlagMap().keySet()) {
+            this.arena.getDebugger().i("team " + sTeam + " is in " + this.getFlagMap().get(sTeam) + "s hands", player);
+            if (player.equals(this.getFlagMap().get(sTeam))) {
                 return sTeam;
             }
         }
@@ -723,7 +709,7 @@ private String getHeldFlagTeam(final String player) {
 
     @Override
     public boolean hasSpawn(final String string) {
-        for (final String teamName : arena.getTeamNames()) {
+        for (final String teamName : this.arena.getTeamNames()) {
             if (string.toLowerCase().equals(teamName.toLowerCase() + "flag")) {
                 return true;
             }
@@ -732,8 +718,8 @@ public boolean hasSpawn(final String string) {
                 return true;
             }
 
-            if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-                for (final ArenaClass aClass : arena.getClasses()) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+                for (final ArenaClass aClass : this.arena.getClasses()) {
                     if (string.toLowerCase().startsWith(teamName.toLowerCase() +
                             aClass.getName().toLowerCase() + "spawn")) {
                         return true;
@@ -748,14 +734,8 @@ public boolean hasSpawn(final String string) {
     public void initate(final Player player) {
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
         final ArenaTeam team = aPlayer.getArenaTeam();
-        if (!getLifeMap().containsKey(team.getName())) {
-            getLifeMap().put(aPlayer.getArenaTeam().getName(), arena.getArenaConfig()
-                    .getInt(CFG.GOAL_FLAGS_LIVES));
-
-            takeFlag(team.getColor(), false,
-                    SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
-            takeFlag(ChatColor.BLACK, false,
-                    SpawnManager.getBlockByExactName(arena, "touchdownflag"));
+        if (!this.getLifeMap().containsKey(team.getName())) {
+            this.getLifeMap().put(aPlayer.getArenaTeam().getName(), this.arena.getArenaConfig().getInt(CFG.GOAL_PFLAGS_LIVES));
         }
     }
 
@@ -768,101 +748,94 @@ public boolean isInternal() {
     public void parsePlayerDeath(final Player player,
                                  final EntityDamageEvent lastDamageCause) {
 
-        if (getFlagMap() == null) {
-            arena.getDebugger().i("no flags set!!", player);
+        if (this.getFlagMap().isEmpty()) {
+            this.arena.getDebugger().i("no flags set!!", player);
             return;
         }
-        final String sTeam = getHeldFlagTeam(player.getName());
-        final ArenaTeam flagTeam = arena.getTeam(sTeam);
+        final String sTeam = this.getHeldFlagTeam(player.getName());
+        final ArenaTeam flagTeam = this.arena.getTeam(sTeam);
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
 
         if (flagTeam == null) {
             if (sTeam != null) {
-                arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer
+                this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPEDTOUCH, aPlayer
                         .getArenaTeam().getColorCodeString()
                         + aPlayer.getName()
                         + ChatColor.YELLOW));
 
-                getFlagMap().remove("touchdown");
-                if (getHeadGearMap() != null && getHeadGearMap().get(aPlayer.getName()) != null) {
+                this.getFlagMap().remove(TOUCHDOWN);
+                if (this.getHeadGearMap() != null && this.getHeadGearMap().get(aPlayer.getName()) != null) {
                     if (aPlayer.get() != null) {
-                        aPlayer.get().getInventory()
-                                .setHelmet(getHeadGearMap().get(aPlayer.getName()).clone());
+                        aPlayer.get().getInventory().setHelmet(this.getHeadGearMap().get(aPlayer.getName()).clone());
                     }
-                    getHeadGearMap().remove(aPlayer.getName());
+                    this.getHeadGearMap().remove(aPlayer.getName());
                 }
 
-                takeFlag(ChatColor.BLACK, false,
-                        SpawnManager.getBlockByExactName(arena, "touchdownflag"));
+                this.releaseFlag(TOUCHDOWN);
             }
         } else {
-            arena.broadcast(Language.parse(arena, MSG.GOAL_FLAGS_DROPPED, aPlayer
+            this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_FLAGS_DROPPED, aPlayer
                             .getArenaTeam().colorizePlayer(player) + ChatColor.YELLOW,
                     flagTeam.getColoredName() + ChatColor.YELLOW));
-            getFlagMap().remove(flagTeam.getName());
-            if (getHeadGearMap() != null
-                    && getHeadGearMap().get(player.getName()) != null) {
-                player.getInventory().setHelmet(
-                        getHeadGearMap().get(player.getName()).clone());
-                getHeadGearMap().remove(player.getName());
+            this.getFlagMap().remove(flagTeam.getName());
+            if (this.getHeadGearMap() != null && this.getHeadGearMap().get(player.getName()) != null) {
+                player.getInventory().setHelmet(this.getHeadGearMap().get(player.getName()).clone());
+                this.getHeadGearMap().remove(player.getName());
             }
 
-            takeFlag(flagTeam.getColor(), false,
-                    SpawnManager.getBlockByExactName(arena, flagTeam.getName() + "flag"));
+            this.releaseFlag(flagTeam.getName());
         }
     }
 
     @Override
     public void parseStart() {
-        getLifeMap().clear();
-        for (final ArenaTeam team : arena.getTeams()) {
+        this.getLifeMap().clear();
+        this.getFlagDataMap().clear();
+        for (final ArenaTeam team : this.arena.getTeams()) {
             if (!team.getTeamMembers().isEmpty()) {
-                arena.getDebugger().i("adding team " + team.getName());
+                this.arena.getDebugger().i("adding team " + team.getName());
                 // team is active
-                getLifeMap().put(team.getName(),
-                        arena.getArenaConfig().getInt(CFG.GOAL_FLAGS_LIVES, 3));
+                this.getLifeMap().put(team.getName(), this.arena.getArenaConfig().getInt(CFG.GOAL_PFLAGS_LIVES, 3));
+                Block flagBlock = this.getTeamFlagLoc(team.getName()).toLocation().getBlock();
+                this.getFlagDataMap().put(team.getName(), flagBlock.getBlockData().clone());
             }
-            takeFlag(team.getColor(), false,
-                    SpawnManager.getBlockByExactName(arena, team.getName() + "flag"));
         }
-        takeFlag(ChatColor.BLACK, false,
-                SpawnManager.getBlockByExactName(arena, "touchdownflag"));
+        ofNullable(this.getTeamFlagLoc(TOUCHDOWN)).ifPresent(paBlockLocation -> {
+            Block touchdownFlagBlock = paBlockLocation.toLocation().getBlock();
+            this.getFlagDataMap().put(TOUCHDOWN, touchdownFlagBlock.getBlockData().clone());
+        });
     }
 
-    private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String team) {
+    private void reduceLivesCheckEndAndCommit(final Arena arena, final String team) {
 
         arena.getDebugger().i("reducing lives of team " + team);
-        if (getLifeMap().get(team) == null) {
+        if (this.getLifeMap().get(team) == null) {
             if (team.contains(":")) {
                 final String realTeam = team.split(":")[1];
-                final int iLives = getLifeMap().get(realTeam) - 1;
+                final int iLives = this.getLifeMap().get(realTeam) - 1;
                 if (iLives > 0) {
-                    getLifeMap().put(realTeam, iLives);
+                    this.getLifeMap().put(realTeam, iLives);
                 } else {
-                    getLifeMap().remove(realTeam);
-                    commit(arena, realTeam, true);
-                    return true;
+                    this.getLifeMap().remove(realTeam);
+                    this.commit(arena, realTeam, true);
                 }
             }
         } else {
-            if (getLifeMap().get(team) != null) {
-                final int iLives = getLifeMap().get(team) - 1;
+            if (this.getLifeMap().get(team) != null) {
+                final int iLives = this.getLifeMap().get(team) - 1;
                 if (iLives > 0) {
-                    getLifeMap().put(team, iLives);
+                    this.getLifeMap().put(team, iLives);
                 } else {
-                    getLifeMap().remove(team);
-                    commit(arena, team, false);
-                    return true;
+                    this.getLifeMap().remove(team);
+                    this.commit(arena, team, false);
                 }
             }
         }
-
-        return false;
     }
 
     private void removeEffects(final Player player) {
-        final String value = arena.getArenaConfig().getString(
-                CFG.GOAL_FLAGS_FLAGEFFECT);
+        final String value = this.arena.getArenaConfig().getString(
+                CFG.GOAL_PFLAGS_FLAGEFFECT);
 
         if ("none".equalsIgnoreCase(value)) {
             return;
@@ -883,8 +856,7 @@ private void removeEffects(final Player player) {
         }
 
         if (pet == null) {
-            PVPArena.instance.getLogger().warning(
-                    "Invalid Potion Effect Definition: " + value);
+            PVPArena.instance.getLogger().warning("Invalid Potion Effect Definition: " + value);
             return;
         }
 
@@ -894,14 +866,21 @@ private void removeEffects(final Player player) {
 
     @Override
     public void reset(final boolean force) {
-        getFlagMap().clear();
-        getHeadGearMap().clear();
-        getLifeMap().clear();
+        this.getHeadGearMap().clear();
+        this.getLifeMap().clear();
+        this.getFlagMap().clear();
+        if(!this.getFlagDataMap().isEmpty()) {
+            for (final ArenaTeam team : this.arena.getTeams()) {
+                this.releaseFlag(team.getName());
+            }
+            this.releaseFlag(TOUCHDOWN);
+        }
+        this.getFlagDataMap().clear();
     }
 
     @Override
     public void setDefaults(final YamlConfiguration config) {
-        if (arena.isFreeForAll()) {
+        if (this.arena.isFreeForAll()) {
             return;
         }
 
@@ -909,63 +888,42 @@ public void setDefaults(final YamlConfiguration config) {
             config.set("teams", null);
         }
         if (config.get("teams") == null) {
-            arena.getDebugger().i("no teams defined, adding custom red and blue!");
+            this.arena.getDebugger().i("no teams defined, adding custom red and blue!");
             config.addDefault("teams.red", ChatColor.RED.name());
             config.addDefault("teams.blue", ChatColor.BLUE.name());
         }
-        if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)
+        if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_PFLAGS_WOOLFLAGHEAD)
                 && config.get("flagColors") == null) {
-            arena.getDebugger().i("no flagheads defined, adding white and black!");
+            this.arena.getDebugger().i("no flagheads defined, adding white and black!");
             config.addDefault("flagColors.red", "WHITE");
             config.addDefault("flagColors.blue", "BLACK");
         }
     }
 
     /**
-     * take/reset an arena flag
+     * reset an arena flag
      *
-     * @param flagColor       the teamcolor to reset
-     * @param take            true if take, else reset
-     * @param paBlockLocation the location to take/reset
+     * @param teamName  team whose flag needs to be reset
      */
-    void takeFlag(final ChatColor flagColor, final boolean take, final PABlockLocation paBlockLocation) {
+    private void releaseFlag(final String teamName) {
+        PABlockLocation paBlockLocation = this.getTeamFlagLoc(teamName);
         if (paBlockLocation == null) {
             return;
         }
-        if (!ColorUtils.isSubType(Material.valueOf(arena.getArenaConfig().getString(CFG.GOAL_FLAGS_FLAGTYPE)), Material.WHITE_WOOL)) {
-            paBlockLocation.toLocation()
-                    .getBlock()
-                    .setType(
-                            take ? Material.BEDROCK : Material.valueOf(arena
-                                    .getArenaConfig().getString(
-                                            CFG.GOAL_FLAGS_FLAGTYPE)));
-            return;
-        }
-        if (take) {
-            paBlockLocation.toLocation().getBlock()
-                    .setType(Material.WHITE_WOOL);
-        } else {
-            Material attempt = Material.getMaterial(flagColor+"_"+arena.getArenaConfig().getString(
-                    CFG.GOAL_FLAGS_FLAGTYPE));
-            if (attempt == null) {
-                attempt = Material.valueOf(
-                        arena.getArenaConfig().getString(
-                                CFG.GOAL_FLAGS_FLAGTYPE));
-
-                if (attempt == null) {
-                    attempt = ColorUtils.getWoolMaterialFromChatColor(flagColor);
-                }
-            }
-            paBlockLocation.toLocation().getBlock().setType(attempt);
+
+        Block flagBlock = paBlockLocation.toLocation().getBlock();
+        try {
+            flagBlock.setBlockData(this.getFlagDataMap().get(teamName));
+        } catch (Exception e) {
+            PVPArena.instance.getLogger().warning("Impossible to reset flag data ! You may recreate arena flags.");
         }
     }
 
     @Override
     public Map timedEnd(final Map scores) {
 
-        for (final ArenaTeam team : arena.getTeams()) {
-            double score = getLifeMap().containsKey(team.getName()) ? getLifeMap()
-                    .get(team.getName()) : 0;
+        for (final ArenaTeam team : this.arena.getTeams()) {
+            double score = this.getLifeMap().getOrDefault(team.getName(), 0);
             if (scores.containsKey(team.getName())) {
                 scores.put(team.getName(), scores.get(team.getName()) + score);
             } else {
@@ -978,111 +936,97 @@ public Map timedEnd(final Map scores) {
 
     @Override
     public void unload(final Player player) {
-        disconnect(ArenaPlayer.parsePlayer(player.getName()));
-        if (allowsJoinInBattle()) {
-            arena.hasNotPlayed(ArenaPlayer.parsePlayer(player.getName()));
+        this.disconnect(ArenaPlayer.parsePlayer(player.getName()));
+        if (this.allowsJoinInBattle()) {
+            this.arena.hasNotPlayed(ArenaPlayer.parsePlayer(player.getName()));
         }
     }
 
-    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
+    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
     public void onFlagClaim(final BlockBreakEvent event) {
         final Player player = event.getPlayer();
-        if (!arena.hasPlayer(event.getPlayer())
-                || !event
-                .getBlock()
-                .getType()
-                .name()
-                .equals(arena.getArenaConfig().getString(
-                        CFG.GOAL_FLAGS_FLAGTYPE))) {
-
-            arena.getDebugger().i("block destroy, ignoring", player);
-            arena.getDebugger().i(String.valueOf(arena.hasPlayer(event.getPlayer())), player);
-            arena.getDebugger().i(event.getBlock().getType().name(), player);
+        Material brokenMaterial = event.getBlock().getType();
+        if (!this.arena.hasPlayer(event.getPlayer()) ||
+                !ColorUtils.isSubType(brokenMaterial, this.arena.getArenaConfig().getMaterial(CFG.GOAL_PFLAGS_FLAGTYPE))) {
+
+            this.arena.getDebugger().i("block destroy, ignoring", player);
+            this.arena.getDebugger().i(String.valueOf(this.arena.hasPlayer(event.getPlayer())), player);
+            this.arena.getDebugger().i(event.getBlock().getType().name(), player);
             return;
         }
 
         final Block block = event.getBlock();
 
-        arena.getDebugger().i("flag destroy!", player);
+        this.arena.getDebugger().i("flag destroy!", player);
 
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
 
-        if (getFlagMap().containsValue(player.getName())) {
-            arena.getDebugger().i("already carries a flag!", player);
+        if (this.getFlagMap().containsValue(player.getName())) {
+            this.arena.getDebugger().i("already carries a flag!", player);
             return;
         }
         final ArenaTeam pTeam = aPlayer.getArenaTeam();
         if (pTeam == null) {
             return;
         }
-        final Set setTeam = new HashSet<>();
 
-        for (final ArenaTeam team : arena.getTeams()) {
-            setTeam.add(team);
-        }
-        setTeam.add(new ArenaTeam("touchdown", "BLACK"));
+        final Set setTeam = new HashSet<>(this.arena.getTeams());
+
+        setTeam.add(new ArenaTeam(TOUCHDOWN, "BLACK"));
         Vector vFlag = null;
         for (final ArenaTeam team : setTeam) {
-            final String aTeam = team.getName();
+            final String teamName = team.getName();
+            final PABlockLocation teamFlagLoc = this.getTeamFlagLoc(teamName);
 
-            if (aTeam.equals(pTeam.getName())) {
-                arena.getDebugger().i("equals!OUT! ", player);
+            if (teamName.equals(pTeam.getName())) {
+                this.arena.getDebugger().i("equals!OUT! ", player);
                 continue;
             }
-            if (team.getTeamMembers().size() < 1
-                    && !"touchdown".equals(team.getName())) {
-                arena.getDebugger().i("size!OUT! ", player);
+            if (team.getTeamMembers().size() < 1 && !TOUCHDOWN.equals(team.getName())) {
+                this.arena.getDebugger().i("size!OUT! ", player);
                 continue; // dont check for inactive teams
             }
-            if (getFlagMap() != null && getFlagMap().containsKey(aTeam)) {
-                arena.getDebugger().i("taken!OUT! ", player);
+            if (this.getFlagMap().containsKey(teamName)) {
+                this.arena.getDebugger().i("taken!OUT! ", player);
                 continue; // already taken
             }
-            arena.getDebugger().i("checking for flag of team " + aTeam, player);
+            this.arena.getDebugger().i("checking for flag of team " + teamName, player);
             Vector vLoc = block.getLocation().toVector();
-            arena.getDebugger().i("block: " + vLoc, player);
-            if (!SpawnManager.getBlocksStartingWith(arena, aTeam + "flag").isEmpty()) {
-                vFlag = SpawnManager
-                        .getBlockNearest(
-                                SpawnManager.getBlocksStartingWith(arena, aTeam
-                                        + "flag"),
-                                new PABlockLocation(player.getLocation()))
-                        .toLocation().toVector();
-            }
-            if (vFlag != null && vLoc.distance(vFlag) < 2) {
-                arena.getDebugger().i("flag found!", player);
-                arena.getDebugger().i("vFlag: " + vFlag, player);
+            this.arena.getDebugger().i("block: " + vLoc, player);
+
+            if(teamFlagLoc != null && vLoc.equals(teamFlagLoc.toLocation().toVector())) {
+                this.arena.getDebugger().i("flag found!", player);
+                this.arena.getDebugger().i("vFlag: " + vFlag, player);
 
-                if ("touchdown".equals(team.getName())) {
+                if (TOUCHDOWN.equals(team.getName())) {
 
-                    arena.broadcast(Language.parse(arena,
+                    this.arena.broadcast(Language.parse(this.arena,
                             MSG.GOAL_FLAGS_GRABBEDTOUCH,
                             pTeam.colorizePlayer(player) + ChatColor.YELLOW));
                 } else {
 
-                    arena.broadcast(Language
-                            .parse(arena, MSG.GOAL_FLAGS_GRABBED,
+                    this.arena.broadcast(Language
+                            .parse(this.arena, MSG.GOAL_FLAGS_GRABBED,
                                     pTeam.colorizePlayer(player)
                                             + ChatColor.YELLOW,
                                     team.getColoredName()
                                             + ChatColor.YELLOW));
                 }
                 try {
-                    getHeadGearMap().put(player.getName(), player.getInventory()
-                            .getHelmet().clone());
-                } catch (final Exception e) {
+                    this.getHeadGearMap().put(player.getName(), player.getInventory().getHelmet().clone());
+                } catch (final Exception ignored) {
 
                 }
 
-                if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)) {
-                    final ItemStack itemStack = new ItemStack(getFlagOverrideTeamMaterial(arena, aTeam));
+                if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_PFLAGS_WOOLFLAGHEAD)) {
+                    final ItemStack itemStack = new ItemStack(this.getFlagOverrideTeamMaterial(this.arena, teamName));
                     player.getInventory().setHelmet(itemStack);
                 }
-                applyEffects(player);
-
-                takeFlag(team.getColor(), true, new PABlockLocation(block.getLocation()));
-                getFlagMap().put(aTeam, player.getName());
-
+                this.applyEffects(player);
+                this.getFlagMap().put(teamName, player.getName());
+                player.getInventory().addItem(new ItemStack(block.getType()));
+                block.setType(Material.AIR);;
+                event.setCancelled(true);
                 return;
             }
         }
@@ -1098,13 +1042,11 @@ public void onInventoryClick(final InventoryClickEvent event) {
             return;
         }
 
-        if (event.isCancelled()
-                || getHeldFlagTeam(player.getName()) == null) {
+        if (event.isCancelled() || this.getHeldFlagTeam(player.getName()) == null) {
             return;
         }
 
-        if (event.getInventory().getType() == InventoryType.CRAFTING
-                && event.getRawSlot() != 5) {
+        if (event.getInventory().getType() == InventoryType.CRAFTING && event.getRawSlot() != 5) {
             return;
         }
 
diff --git a/src/net/slipcor/pvparena/loadables/ArenaRegion.java b/src/net/slipcor/pvparena/loadables/ArenaRegion.java
index a352371dd..aa62de5aa 100644
--- a/src/net/slipcor/pvparena/loadables/ArenaRegion.java
+++ b/src/net/slipcor/pvparena/loadables/ArenaRegion.java
@@ -1,6 +1,5 @@
 package net.slipcor.pvparena.loadables;
 
-import com.google.common.collect.ImmutableMap;
 import net.slipcor.pvparena.PVPArena;
 import net.slipcor.pvparena.arena.Arena;
 import net.slipcor.pvparena.arena.ArenaPlayer;
@@ -452,11 +451,7 @@ public void removeEntities() {
         }
 
         for (final Entity entity : getWorld().getEntities()) {
-            if (entity instanceof Player
-                    || !shape.contains(new PABlockLocation(entity.getLocation()
-                    .getWorld().getName(), entity.getLocation().getBlockX(),
-                    entity.getLocation().getBlockY(), entity.getLocation()
-                    .getBlockZ()))) {
+            if (entity instanceof Player || !shape.contains(new PABlockLocation(entity.getLocation()))) {
                 continue;
             }
 
diff --git a/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java b/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
index 36d66125f..aa604c6ea 100644
--- a/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
+++ b/src/net/slipcor/pvparena/runnables/CircleParticleRunnable.java
@@ -7,11 +7,10 @@
 import net.slipcor.pvparena.core.Utils;
 import org.bukkit.*;
 
-import java.util.HashMap;
 import java.util.Map;
 
 public class CircleParticleRunnable implements Runnable {
-    private Map flagMap = new HashMap<>();
+    private Map flagMap;
     private final Arena arena;
     private double radius;
     private int i = 0;
@@ -24,7 +23,7 @@ public CircleParticleRunnable(Arena arena, Config.CFG config, Map= 360) {
-            i = 0;
+        if (this.i >= 360) {
+            this.i = 0;
         }
     }
 }

From 7beea5ce40fe33df73702bafa193eb1f92c195a6 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 11 May 2020 19:22:18 +0200
Subject: [PATCH 046/115] v1.15 - avoid self respawn with death screen - issue
 #36

---
 src/net/slipcor/pvparena/managers/SpawnManager.java | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/net/slipcor/pvparena/managers/SpawnManager.java b/src/net/slipcor/pvparena/managers/SpawnManager.java
index bed26950a..a0ecc29b2 100644
--- a/src/net/slipcor/pvparena/managers/SpawnManager.java
+++ b/src/net/slipcor/pvparena/managers/SpawnManager.java
@@ -622,6 +622,9 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
             return;
         }
 
+        // Trick to avoid death screen
+        Bukkit.getScheduler().scheduleSyncDelayedTask(PVPArena.instance, () -> aPlayer.get().closeInventory(), 1);
+
         if (overrideSpawn == null) {
 
 
@@ -634,7 +637,7 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
                 int pos = new Random().nextInt(spawns.size());
                 for (final PASpawn spawn : spawns) {
                     if (--pos <= 0) {
-                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 1L);
+                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 2);
                         aPlayer.setStatus(Status.FIGHT);
                         return;
                     }
@@ -676,7 +679,7 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
                     int pos = new Random().nextInt(spawns.size());
                     for (final PASpawn spawn : spawns) {
                         if (--pos <= 0) {
-                            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 1L);
+                            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 2);
                             aPlayer.setStatus(Status.FIGHT);
                             return;
                         }
@@ -723,7 +726,7 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
                     if (paLocationDoubleEntry.getValue() == max) {
                         for (final PASpawn spawn : spawns) {
                             if (spawn.getLocation().equals(paLocationDoubleEntry.getKey())) {
-                                Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 1L);
+                                Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 2);
                                 return;
                             }
                         }
@@ -738,7 +741,7 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
             int pos = new Random().nextInt(spawns.size());
             for (final PASpawn spawn : spawns) {
                 if (--pos <= 0) {
-                    Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 1L);
+                    Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, spawn.getName()), 2);
                     aPlayer.setStatus(Status.FIGHT);
                     return;
                 }
@@ -746,7 +749,7 @@ public static void respawn(final Arena arena, final ArenaPlayer aPlayer, final S
 
         }
 
-        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, overrideSpawn), 1L);
+        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, overrideSpawn), 2);
         if (overrideSpawn == null || !overrideSpawn.toLowerCase().endsWith("relay")) {
             aPlayer.setStatus(Status.FIGHT);
         }

From 8d218c4677f861fce09462c8dceedb99c8379e78 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 11 May 2020 20:09:11 +0200
Subject: [PATCH 047/115] v1.15 - repair scoreboard init - issue #35

---
 src/net/slipcor/pvparena/arena/Arena.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index 5dc69a780..f35a1c1ce 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -1660,7 +1660,7 @@ public void run() {
                 }
 
             }
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 1L);
+            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 3L);
         } else {
             final Scoreboard board = getStandardScoreboard();
             ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());

From bc4527a3bb59e8bba430895baa8bb0b74d54962d Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 14 May 2020 20:01:44 +0200
Subject: [PATCH 048/115] v1.15 - fix move checking for "checkpoint" goal -
 issue #32

---
 doc/goals/checkpoints.md                      |   6 +-
 .../pvparena/goals/GoalCheckPoints.java       | 168 +++++++++---------
 2 files changed, 88 insertions(+), 86 deletions(-)

diff --git a/doc/goals/checkpoints.md b/doc/goals/checkpoints.md
index ac3792bd3..49cffcaf3 100644
--- a/doc/goals/checkpoints.md
+++ b/doc/goals/checkpoints.md
@@ -11,12 +11,12 @@ First player to reach every checkpoint up to the last (in order) wins!
 ## Setup
 
 Spawns have to be added. In order to do that, use `/pa [arenaname] checkpoint [number]`. This sets checkpoint number [number].
-Make sure you start with 0 and don't forget to add every single number, or else it will not be possible to win :P
+Make sure you start with 1 and don't forget to add every single number, or else it will not be possible to win :P
 
 ## Config Settings  
 
 - cpclaimrange => how near need players to be? (default: 5)
-- cplives => goal checkpoint index [0, 1, 2, ...] to reach
+- cplives => number of checkpoints to reach
 - cptickinterval => the amount of ticks to wait before checking for position (default: 20 = 1 second)
 
 ## Warnings
@@ -25,4 +25,4 @@ This game mode has to check for player's position. Based on the player and check
 
 ## Supported Game Modes
 
-Free for all - Teams might work but.... no idea
+Free for all
diff --git a/src/net/slipcor/pvparena/goals/GoalCheckPoints.java b/src/net/slipcor/pvparena/goals/GoalCheckPoints.java
index 2ff7d5334..4162d3068 100644
--- a/src/net/slipcor/pvparena/goals/GoalCheckPoints.java
+++ b/src/net/slipcor/pvparena/goals/GoalCheckPoints.java
@@ -24,6 +24,7 @@
 import org.bukkit.Location;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
 
 import java.util.*;
 
@@ -39,7 +40,7 @@ public class GoalCheckPoints extends ArenaGoal {
 
     public GoalCheckPoints() {
         super("CheckPoints");
-        debug = new Debug(99);
+        this.debug = new Debug(99);
     }
 
     @Override
@@ -51,7 +52,7 @@ public String version() {
 
     @Override
     public boolean allowsJoinInBattle() {
-        return arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
+        return this.arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
     }
 
     @Override
@@ -95,10 +96,10 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
+        final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
 
-        if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) {
-            res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL));
+        if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) {
+            res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL));
             return res;
         }
 
@@ -115,7 +116,7 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
     private Set checkLocationPresentPlayers(final Location loc, final int distance) {
         final Set result = new HashSet<>();
 
-        for (final ArenaPlayer p : arena.getFighters()) {
+        for (final ArenaPlayer p : this.arena.getFighters()) {
             if (p.get().getLocation().getWorld().getName().equals(loc.getWorld().getName())) {
                 if (p.get().getLocation().distance(loc) > distance) {
                     continue;
@@ -128,21 +129,20 @@ private Set checkLocationPresentPlayers(final Location loc, final int di
         return result;
     }
 
-    void checkMove() {
+    private void checkMove() {
 
-        arena.getDebugger().i("------------------");
-        arena.getDebugger().i("  GCP checkMove();");
-        arena.getDebugger().i("------------------");
+        this.arena.getDebugger().i("------------------");
+        this.arena.getDebugger().i("  GCP checkMove();");
+        this.arena.getDebugger().i("------------------");
 
-        final int checkDistance = arena.getArenaConfig().getInt(
-                CFG.GOAL_DOM_CLAIMRANGE);
+        final int checkDistance = this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_CLAIMRANGE);
 
-        for (final PASpawn spawn : SpawnManager.getPASpawnsStartingWith(arena, "checkpoint")) {
+        for (final PASpawn spawn : SpawnManager.getPASpawnsStartingWith(this.arena, "checkpoint")) {
             final PALocation paLoc = spawn.getLocation();
-            final Set players = checkLocationPresentPlayers(paLoc.toLocation(),
+            final Set players = this.checkLocationPresentPlayers(paLoc.toLocation(),
                     checkDistance);
 
-            arena.getDebugger().i("players: " + StringParser.joinSet(players, ", "));
+            this.arena.getDebugger().i("players: " + StringParser.joinSet(players, ", "));
 
             // players now contains all players near the checkpoint
 
@@ -151,7 +151,7 @@ void checkMove() {
             }
             int value = Integer.parseInt(spawn.getName().substring(10));
             for (String playerName : players) {
-                maybeAddScoreAndBroadCast(playerName, value);
+                this.maybeAddScoreAndBroadCast(playerName, value);
             }
 
         }
@@ -159,22 +159,22 @@ void checkMove() {
 
     private void maybeAddScoreAndBroadCast(final String playerName, int checkpoint) {
 
-        if (!getLifeMap().containsKey(playerName)) {
+        if (!this.getLifeMap().containsKey(playerName)) {
             return;
         }
 
 
-        final int max = arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES);
+        final int max = this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES);
 
-        final int position = max - getLifeMap().get(playerName);
+        final int position = max - this.getLifeMap().get(playerName) + 1;
 
-        if (checkpoint <= position+1) {
-            arena.broadcast(Language.parse(arena, MSG.GOAL_CHECKPOINTS_SCORE,
-                    playerName, position+1 + "/" + max));
-            reduceLivesCheckEndAndCommit(arena, playerName);
+        if (checkpoint == position) {
+            this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_CHECKPOINTS_SCORE,
+                    playerName, position + "/" + max));
+            this.reduceLivesCheckEndAndCommit(this.arena, playerName);
         } else if (checkpoint > position) {
-            arena.broadcast(Language.parse(arena, MSG.GOAL_CHECKPOINTS_YOUMISSED,
-                    String.valueOf(position + 1), String.valueOf(checkpoint)));
+            this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_CHECKPOINTS_YOUMISSED,
+                    String.valueOf(position), String.valueOf(checkpoint)));
         }
 
     }
@@ -207,7 +207,7 @@ private void commitWin(final Arena arena, final String playerName) {
                     winner.getName()));
         }
 
-        getLifeMap().clear();
+        this.getLifeMap().clear();
         new EndRunnable(arena, arena.getArenaConfig().getInt(
                 CFG.TIME_ENDCOUNTDOWN));
     }
@@ -217,51 +217,59 @@ public void commitCommand(final CommandSender sender, final String[] args) {
         // 0 = checkpoint , [1 = number]
 
         if (!(sender instanceof Player)) {
-            Arena.pmsg(sender, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS));
+            Arena.pmsg(sender, Language.parse(this.arena, MSG.ERROR_ONLY_PLAYERS));
             return;
         }
 
         ArenaPlayer ap = ArenaPlayer.parsePlayer(sender.getName());
+        int cpLives = this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES);
 
-        if (args.length < 2 && arena.getFighters().contains(ap)) {
+        if (args.length < 2 && this.arena.getFighters().contains(ap)) {
             ap.setTelePass(true);
-            int value = arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES) - getLifeMap().get(ap.getName());
-            ap.get().teleport(SpawnManager.getSpawnByExactName(arena, "checkpoint"+value).toLocation());
+            int value = cpLives - this.getLifeMap().get(ap.getName());
+            if(value == 0) {
+                ap.get().teleport(SpawnManager.getSpawnByExactName(this.arena, "spawn").toLocation());
+            } else {
+                ap.get().teleport(SpawnManager.getSpawnByExactName(this.arena, "checkpoint"+value).toLocation());
+            }
             ap.setTelePass(false);
             return;
         }
 
-        if (!AbstractArenaCommand.argCountValid(sender, arena, args, new Integer[]{2})) {
+        if (!AbstractArenaCommand.argCountValid(sender, this.arena, args, new Integer[]{2})) {
             return;
         }
         int value;
         try {
             value = Integer.parseInt(args[1]);
-            Math.sqrt(value);
         } catch (Exception e) {
-            arena.msg(sender, Language.parse(arena, MSG.ERROR_NOT_NUMERIC, args[1]));
+            this.arena.msg(sender, Language.parse(this.arena, MSG.ERROR_NOT_NUMERIC, args[1]));
             return;
         }
         Player player = (Player) sender;
         String spawnName = "checkpoint"+value;
-        arena.spawnSet(spawnName, new PALocation(player.getLocation()));
-        arena.msg(sender, Language.parse(arena, MSG.SPAWN_SET, spawnName));
+        if(value > 0 && value <= cpLives) {
+            this.arena.spawnSet(spawnName, new PALocation(player.getLocation()));
+            this.arena.msg(sender, Language.parse(this.arena, MSG.SPAWN_SET, spawnName));
+        } else {
+            this.arena.msg(sender, Language.parse(this.arena, MSG.SPAWN_UNKNOWN, spawnName));
+        }
     }
 
     @Override
     public void commitEnd(final boolean force) {
-        if (arena.realEndRunner != null) {
-            arena.getDebugger().i("[CP] already ending");
+        if (this.arena.realEndRunner != null) {
+            this.arena.getDebugger().i("[CP] already ending");
             return;
         }
-        arena.getDebugger().i("[CP]");
+        this.arena.getDebugger().i("[CP]");
 
-        final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "");
+        final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "");
         Bukkit.getPluginManager().callEvent(gEvent);
 
         ArenaPlayer ap = null;
 
-        for (ArenaPlayer aPlayer : arena.getFighters()) {
+        for (ArenaPlayer aPlayer : this.arena.getFighters()) {
             if (aPlayer.getStatus() == Status.FIGHT) {
                 ap = aPlayer;
                 break;
@@ -270,30 +278,29 @@ public void commitEnd(final boolean force) {
 
         if (ap != null && !force) {
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.PLAYER_HAS_WON, ap.getName()), "END");
+                    this.arena,
+                    Language.parse(this.arena, MSG.PLAYER_HAS_WON, ap.getName()), "END");
 
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.PLAYER_HAS_WON, ap.getName()), "WINNER");
-            arena.broadcast(Language.parse(arena, MSG.PLAYER_HAS_WON, ap.getName()));
+                    this.arena,
+                    Language.parse(this.arena, MSG.PLAYER_HAS_WON, ap.getName()), "WINNER");
+            this.arena.broadcast(Language.parse(this.arena, MSG.PLAYER_HAS_WON, ap.getName()));
         }
 
-        if (ArenaModuleManager.commitEnd(arena, ap.getArenaTeam())) {
+        if (ArenaModuleManager.commitEnd(this.arena, ap.getArenaTeam())) {
             return;
         }
-        new EndRunnable(arena, arena.getArenaConfig().getInt(
-                CFG.TIME_ENDCOUNTDOWN));
+        new EndRunnable(this.arena, this.arena.getArenaConfig().getInt(CFG.TIME_ENDCOUNTDOWN));
     }
 
     @Override
     public void displayInfo(final CommandSender sender) {
         sender.sendMessage("needed points: " +
-                arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES));
+                this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES));
         sender.sendMessage("claim range: " +
-                arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_CLAIMRANGE));
+                this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_CLAIMRANGE));
         sender.sendMessage("tick interval (ticks): " +
-                arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_TICKINTERVAL));
+                this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_TICKINTERVAL));
     }
 
     @Override
@@ -301,7 +308,7 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
         if (res.getPriority() <= PRIORITY + 1000) {
             res.setError(
                     this,
-                    String.valueOf(getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0))
+                    String.valueOf(this.getLifeMap().getOrDefault(aPlayer.getArenaTeam().getName(), 0))
             );
         }
         return res;
@@ -312,8 +319,8 @@ public boolean hasSpawn(final String string) {
         if (string.startsWith("checkpoint") || string.startsWith("spawn")) {
             return true;
         }
-        if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-            for (final ArenaClass aClass : arena.getClasses()) {
+        if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+            for (final ArenaClass aClass : this.arena.getClasses()) {
                 if (string.toLowerCase().contains(aClass.getName().toLowerCase() + "spawn")) {
                     return true;
                 }
@@ -325,8 +332,8 @@ public boolean hasSpawn(final String string) {
     @Override
     public void initate(final Player player) {
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
-        if (!getLifeMap().containsKey(aPlayer.getName())) {
-            getLifeMap().put(aPlayer.getName(), arena.getArenaConfig()
+        if (!this.getLifeMap().containsKey(aPlayer.getName())) {
+            this.getLifeMap().put(aPlayer.getName(), this.arena.getArenaConfig()
                     .getInt(CFG.GOAL_CHECKPOINTS_LIVES));
         }
     }
@@ -338,51 +345,47 @@ public boolean isInternal() {
 
     @Override
     public void lateJoin(final Player player) {
-        initate(player);
+        this.initate(player);
     }
 
     @Override
     public void parseStart() {
-        getLifeMap().clear();
-        for (final ArenaPlayer player : arena.getFighters()) {
-            arena.getDebugger().i("adding player " + player.getName());
-            getLifeMap().put(player.getName(),
-                    arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES, 3));
+        this.getLifeMap().clear();
+        for (final ArenaPlayer player : this.arena.getFighters()) {
+            this.arena.getDebugger().i("adding player " + player.getName());
+            this.getLifeMap().put(player.getName(),
+                    this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_LIVES, 3));
         }
 
-        final CheckPointsMainRunnable cpMainRunner = new CheckPointsMainRunnable(arena, this);
-        final int tickInterval = arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_TICKINTERVAL);
-        cpMainRunner.rID = Bukkit.getScheduler().scheduleSyncRepeatingTask(
-                PVPArena.instance, cpMainRunner, tickInterval, tickInterval);
+        final CheckPointsMainRunnable cpMainRunner = new CheckPointsMainRunnable(this.arena, this);
+        final int tickInterval = this.arena.getArenaConfig().getInt(CFG.GOAL_CHECKPOINTS_TICKINTERVAL);
+        cpMainRunner.runTaskTimer(PVPArena.instance, tickInterval, tickInterval);
     }
 
-    private boolean reduceLivesCheckEndAndCommit(final Arena arena, final String player) {
+    private void reduceLivesCheckEndAndCommit(final Arena arena, final String player) {
 
         arena.getDebugger().i("reducing lives of player " + player);
-        if (getLifeMap().get(player) != null) {
-            final int iLives = getLifeMap().get(player) - 1;
+        if (this.getLifeMap().get(player) != null) {
+            final int iLives = this.getLifeMap().get(player) - 1;
             if (iLives > 0) {
-                getLifeMap().put(player, iLives);
+                this.getLifeMap().put(player, iLives);
             } else {
-                getLifeMap().remove(player);
-                commitWin(arena, player);
-                return true;
+                this.getLifeMap().remove(player);
+                this.commitWin(arena, player);
             }
         }
-        return false;
     }
 
     @Override
     public void reset(final boolean force) {
-        getLifeMap().clear();
+        this.getLifeMap().clear();
     }
 
     @Override
     public Map timedEnd(final Map scores) {
 
-        for (final ArenaTeam team : arena.getTeams()) {
-            double score = getLifeMap().containsKey(team.getName()) ? getLifeMap()
-                    .get(team.getName()) : 0;
+        for (final ArenaTeam team : this.arena.getTeams()) {
+            double score = this.getLifeMap().getOrDefault(team.getName(), 0);
             if (scores.containsKey(team.getName())) {
                 scores.put(team.getName(), scores.get(team.getName()) + score);
             } else {
@@ -393,8 +396,7 @@ public Map timedEnd(final Map scores) {
         return scores;
     }
 
-    class CheckPointsMainRunnable implements Runnable {
-        public int rID = -1;
+    private class CheckPointsMainRunnable extends BukkitRunnable {
         private final Arena arena;
         //private final Debug debug = new Debug(39);
         private final GoalCheckPoints goal;
@@ -410,10 +412,10 @@ public CheckPointsMainRunnable(final Arena arena, final GoalCheckPoints goal) {
          */
         @Override
         public void run() {
-            if (!arena.isFightInProgress() || arena.realEndRunner != null) {
-                Bukkit.getScheduler().cancelTask(rID);
+            if (!this.arena.isFightInProgress() || this.arena.realEndRunner != null) {
+                this.cancel();
             }
-            goal.checkMove();
+            this.goal.checkMove();
         }
     }
 }

From f67abcd79846b524d3568fb645d6f4936209ec61 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 14 May 2020 21:39:46 +0200
Subject: [PATCH 049/115] v1.15 - fix "loungeinteract" parameter not working -
 issue #27

---
 .../slipcor/pvparena/listeners/PlayerListener.java    | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java
index 1bec57349..6f38f42f0 100644
--- a/src/net/slipcor/pvparena/listeners/PlayerListener.java
+++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java
@@ -46,6 +46,8 @@
 
 import java.util.*;
 
+import static java.util.Arrays.asList;
+
 /**
  * 
  * Player Listener class
@@ -526,7 +528,11 @@ public void onPlayerInteract(final PlayerInteractEvent event) {
             if (whyMe) {
                 arena.getDebugger().i("exiting! fight in progress AND no INBATTLEJOIN arena!", player); return;
             }
-            if (aPlayer.getStatus() != Status.LOUNGE && aPlayer.getStatus() != Status.READY) {
+            if (asList(Status.LOUNGE, Status.READY).contains(aPlayer.getStatus()) &&
+                    arena.getArenaConfig().getBoolean(CFG.PERMS_LOUNGEINTERACT)) {
+                arena.getDebugger().i("allowing lounge interaction due to config setting!");
+                event.setCancelled(false);
+            } else if (aPlayer.getStatus() != Status.LOUNGE && aPlayer.getStatus() != Status.READY) {
                 arena.getDebugger().i("cancelling: not fighting nor in the lounge", player);
                 event.setCancelled(true);
             } else if (aPlayer.getArena() != null && team != null) {
@@ -570,7 +576,8 @@ public void onPlayerInteract(final PlayerInteractEvent event) {
             }
 
             if (whyMe) {
-                arena.getDebugger().i("exiting! fight in progress AND no INBATTLEJOIN arena!", player); return;
+                arena.getDebugger().i("exiting! fight in progress AND no INBATTLEJOIN arena!", player);
+                return;
             }
             arena.getDebugger().i("block click!", player);
 

From 568dbe89e261cf7316d252995b8a10e15ceaf772 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Sat, 16 May 2020 19:50:54 +0200
Subject: [PATCH 050/115] v1.15 - add update documentation for this version

---
 doc/update-from-1-3-x.md | 23 ---------------
 doc/update-version.md    | 62 ++++++++++++++++++++++++++++++++++++++++
 readme.md                |  4 +--
 3 files changed, 64 insertions(+), 25 deletions(-)
 delete mode 100644 doc/update-from-1-3-x.md
 create mode 100644 doc/update-version.md

diff --git a/doc/update-from-1-3-x.md b/doc/update-from-1-3-x.md
deleted file mode 100644
index 53ea8d859..000000000
--- a/doc/update-from-1-3-x.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Upgrading from 1.3.x
-
-If you want to upgrade your arena configurations to PVPArena 1.13 version or above, you have
-to update two things : Item Lists and Schematics
-
-## Item lists
-
-Probably the worst thing to upgrade, just clear the inventories of your arena classes and
-re-create them. Be also careful to remove items list of pvparena modules like **chestfiller** 
-or **blockdissolve**.
-
-## WorldEdit
-
-You have to remove Worldedit schematics too. A big part of blocks will not be pasted if you
-keep it as it is and chest orientation will be broken.
-
-So just remove your schematics files and re-create them with `/pa [arena] regsave [regionname]`
-
-
-## Miscellaneous
-
-**In "flags" goal :** Just replace `WOOL` block name by `WHITE_WOOL`. The color will be
-automatically defined with the color of the team.
\ No newline at end of file
diff --git a/doc/update-version.md b/doc/update-version.md
new file mode 100644
index 000000000..d9385b332
--- /dev/null
+++ b/doc/update-version.md
@@ -0,0 +1,62 @@
+# Upgrading from 1.14.x
+
+If you want to upgrade your arena configurations to PVPArena 1.15 version or above, please update
+these two things :
+
+## Goal PhysicalFlags
+
+If you use *physicalFlags* goal for your arenas, just rename `flags` block to `physicalFlags` in
+your config file.
+
+Example : 
+
+*Replace this*
+```yaml
+goal:
+  endCountDown: 5
+  flags:
+    flives: 3
+    mustBeSafe: true
+    woolFlagHead: true
+    effect: none
+    flagType: WHITE_WOOL
+```
+*with this*
+```yaml
+goal:
+  endCountDown: 5
+  physicalFlags:
+    flives: 3
+    mustBeSafe: true
+    woolFlagHead: true
+    effect: none
+    flagType: WHITE_WOOL
+```
+
+## Goal checkpoints
+
+In checkpoint goal, checkpoint indexes started at 0, now they start at 1. Just edit your config
+file and decrease all checkpoints number by one in `spawns` block.
+
+Example : 
+
+*Replace this*
+```yaml
+spawns:
+  checkpoint0: world,299,64,1276,-357.7568359375,4.2000017166137695
+  checkpoint1: world,299,64,1276,11.695333480834961,22.20012664794922
+  checkpoint2: world,300,64,1281,-5.704666614532471,23.700136184692383
+  checkpoint3: world,297,64,1285,14.695302963256836,50.40021514892578
+  checkpoint4: world,298,64,1289,53.69533920288086,54.75028610229492
+  checkpoint5: world,295,64,1292,1.795335054397583,46.80023193359375
+```
+*with this*
+```yaml
+spawns:
+  checkpoint1: world,299,64,1276,-357.7568359375,4.2000017166137695
+  checkpoint2: world,299,64,1276,11.695333480834961,22.20012664794922
+  checkpoint3: world,300,64,1281,-5.704666614532471,23.700136184692383
+  checkpoint4: world,297,64,1285,14.695302963256836,50.40021514892578
+  checkpoint5: world,298,64,1289,53.69533920288086,54.75028610229492
+  checkpoint6: world,295,64,1292,1.795335054397583,46.80023193359375
+```
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 086970c9b..1165b3c39 100644
--- a/readme.md
+++ b/readme.md
@@ -1,7 +1,7 @@
 ![PVP-Arena](/doc/images/logo.png)
 
 ***
-**IF YOU'RE UPGRADING FROM 1.3.x VERSION OR BELOW, PLEASE READ [UPGRADE DOCUMENTATION](doc/update-from-1-3-x.md)**
+**IF YOU'RE UPGRADING FROM 1.14.x VERSION OR BELOW, PLEASE READ [UPGRADE DOCUMENTATION](doc/update-version.md)**
 ***
 
 **Enhance your server by adding a new dimension of PVP battles!**
@@ -33,7 +33,7 @@ This flexibility is achieved on the one hand by a module loader created by Nodin
 
 ## Dependencies
 
-- Spigot 1.13
+- Spigot 1.13+
 
 ***
 

From 928dfe17a798632fcbf0dabf56609428a78bf1aa Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Sat, 16 May 2020 19:54:48 +0200
Subject: [PATCH 051/115] temp documentation

---
 readme.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/readme.md b/readme.md
index 086970c9b..059e25845 100644
--- a/readme.md
+++ b/readme.md
@@ -2,6 +2,8 @@
 
 ***
 **IF YOU'RE UPGRADING FROM 1.3.x VERSION OR BELOW, PLEASE READ [UPGRADE DOCUMENTATION](doc/update-from-1-3-x.md)**
+
+Are you testing 1.15-snapshot ? Documentation is [available here](https://github.com/Eredrim/pvparena/tree/1.15).
 ***
 
 **Enhance your server by adding a new dimension of PVP battles!**

From ef3aa9e017074fc6ed48a9373c9cbd55bece40b3 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 22 May 2020 02:07:05 +0200
Subject: [PATCH 052/115] v1.15 - fix handling of colorable items

---
 src/net/slipcor/pvparena/core/ColorUtils.java | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java
index 3c2ac1507..3d409c14f 100644
--- a/src/net/slipcor/pvparena/core/ColorUtils.java
+++ b/src/net/slipcor/pvparena/core/ColorUtils.java
@@ -14,8 +14,6 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import static net.slipcor.pvparena.core.StringParser.joinArray;
-
 public final class ColorUtils {
 
     private static final Debug DEBUG = new Debug(18);
@@ -101,9 +99,8 @@ public static boolean isColorableMaterial(Material type) {
      */
     public static Material getColoredMaterial(DyeColor dyeColor, Material typeMaterial) {
         String color = dyeColor.name();
-        String[] typeNameArr = typeMaterial.name().split("_");
-        String uncoloredMaterial = joinArray(Arrays.copyOfRange(typeNameArr, 1, typeNameArr.length), "_");
-        return Material.valueOf(color + "_" + uncoloredMaterial);
+        String materialSuffix = getMaterialSuffix(typeMaterial);
+        return Material.valueOf(color + "_" + materialSuffix);
     }
 
     public static boolean isSubType(Material type, Material check) {
@@ -111,7 +108,10 @@ public static boolean isSubType(Material type, Material check) {
     }
 
     private static String getMaterialSuffix(Material material) {
-        return material.name().contains("_") ? material.name().split("_", 2)[1] : "";
+        return getColorableSuffixes().stream()
+                .filter(suffix -> material.name().endsWith(suffix))
+                .findFirst()
+                .orElse("");
     }
 
     /**
@@ -121,7 +121,7 @@ private static List getColorableSuffixes() {
         return Stream.of(Material.values())
                 .filter(m -> m.name().startsWith("MAGENTA_"))
                 .filter(Material::isBlock)
-                .map(ColorUtils::getMaterialSuffix)
+                .map(m -> m.name().split("MAGENTA_", 2)[1])
                 .collect(Collectors.toList());
     }
 

From 43de715fe4530e144f94a055512c190617d8cd0d Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 26 May 2020 14:47:19 +0200
Subject: [PATCH 053/115] v1.15 - delay scoreboard reset

---
 src/net/slipcor/pvparena/arena/Arena.java | 26 ++++++++++-------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index f35a1c1ce..9bd6a7ac5 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -1346,8 +1346,8 @@ public void run() {
                     new RunLater().run();
                 } else {
                     try {
-                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 2L);
-                    } catch (IllegalStateException e) {
+                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 4L);
+                    } catch (IllegalStateException ignored) {
 
                     }
                 }
@@ -1365,21 +1365,17 @@ public void run() {
             }
             final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
             try {
-                Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() {
-                    @Override
-                    public void run() {
-
-                        if (ap.hasBackupScoreboard()) {
-                            player.setScoreboard(ap.getBackupScoreboard());
-                            if (ap.getBackupScoreboardTeam() != null) {
-                                ap.getBackupScoreboardTeam().addEntry(ap.getName());
-                            }
-                            ap.setBackupScoreboardTeam(null);
-                            ap.setBackupScoreboard(null);
+                Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+                    if (ap.hasBackupScoreboard()) {
+                        player.setScoreboard(ap.getBackupScoreboard());
+                        if (ap.getBackupScoreboardTeam() != null) {
+                            ap.getBackupScoreboardTeam().addEntry(ap.getName());
                         }
+                        ap.setBackupScoreboardTeam(null);
+                        ap.setBackupScoreboard(null);
                     }
-                }, 3L);
-            } catch (IllegalPluginAccessException e) {
+                }, 5L);
+            } catch (IllegalPluginAccessException ignored) {
 
             }
         }

From cea80e6cc458a939512eef8f871fc1247576067c Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Wed, 27 May 2020 18:56:48 +0200
Subject: [PATCH 054/115] v1.15 - delay scoreboard init (once again) - issue
 #35

---
 src/net/slipcor/pvparena/arena/Arena.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index 9bd6a7ac5..783265661 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -1656,7 +1656,7 @@ public void run() {
                 }
 
             }
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 3L);
+            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 5L);
         } else {
             final Scoreboard board = getStandardScoreboard();
             ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());

From 67393d596c333b74a126f03961279955ce8605cd Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Wed, 27 May 2020 21:03:07 +0200
Subject: [PATCH 055/115] v1.15 - fix worldguard sofdepend warning on load

---
 src/plugin.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plugin.yml b/src/plugin.yml
index 637ee047c..a85f83219 100644
--- a/src/plugin.yml
+++ b/src/plugin.yml
@@ -5,7 +5,7 @@ prefix: PVP Arena
 main: net.slipcor.pvparena.PVPArena
 version: ${project.version}${buildVersion}
 api-version: 1.13
-softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,LibsDisguises,DisguiseCraft,TagAPI,My Worlds,CrackShot]
+softdepend: [Spout,Multiverse-Core,MultiWorld,WormholeXTreme,Vault,WorldEdit,WorldGuard,LibsDisguises,DisguiseCraft,My Worlds,CrackShot]
 description: create, manage and enhance PvP arenas
 website: http://dev.bukkit.org/server-mods/pvparena
 dev-url: http://dev.bukkit.org/server-mods/pvparena

From 980a9129997464071d0a018817df56d49bc95d8c Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Wed, 27 May 2020 21:04:04 +0200
Subject: [PATCH 056/115] v1.15 - fix "/pa class load" error appearing with
 some mods

---
 src/net/slipcor/pvparena/arena/ArenaPlayer.java  | 6 +++---
 src/net/slipcor/pvparena/commands/PAA_Class.java | 7 ++++++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
index 037fe7053..f7f415db9 100644
--- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java
+++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
@@ -768,11 +768,11 @@ public final void setArena(final Arena arena) {
      * @param aClass the arena class to set
      */
     public void setArenaClass(final ArenaClass aClass) {
-        final PAPlayerClassChangeEvent event = new PAPlayerClassChangeEvent(arena, get(), aClass);
+        final PAPlayerClassChangeEvent event = new PAPlayerClassChangeEvent(this.arena, this.get(), aClass);
         Bukkit.getServer().getPluginManager().callEvent(event);
         this.aClass = event.getArenaClass();
-        if (arena != null) {
-            ArenaModuleManager.parseClassChange(arena, get(), this.aClass);
+        if (this.arena != null && this.getStatus() != Status.NULL) {
+            ArenaModuleManager.parseClassChange(this.arena, this.get(), this.aClass);
         }
     }
 
diff --git a/src/net/slipcor/pvparena/commands/PAA_Class.java b/src/net/slipcor/pvparena/commands/PAA_Class.java
index 8b13862a9..c6769c098 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Class.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Class.java
@@ -8,6 +8,7 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
+import net.slipcor.pvparena.managers.InventoryManager;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.inventory.ItemStack;
@@ -79,7 +80,11 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
             Arena.pmsg(player, Language.parse(arena, MSG.CLASS_SAVED, args[1]));
         } else if ("load".equalsIgnoreCase(args[0])) {
             final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(sender.getName());
-            ArenaPlayer.backupAndClearInventory(arena, aPlayer.get());
+            if(aPlayer.getArenaClass() == null) {
+                ArenaPlayer.backupAndClearInventory(arena, aPlayer.get());
+            } else {
+                InventoryManager.clearInventory(aPlayer.get());
+            }
             arena.selectClass(aPlayer, args[1]);
         } else if ("remove".equalsIgnoreCase(args[0])) {
             final Player player = (Player) sender;

From 962df4e2958984a70ce03743f95679406b6edcc6 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 29 May 2020 00:44:17 +0200
Subject: [PATCH 057/115] v1.15 - add special leave hook for mods and leave
 command for LateLounge

---
 lang/lang_en.yml                                    |  1 +
 lang/lang_fr.yml                                    |  1 +
 src/net/slipcor/pvparena/commands/PAG_Leave.java    |  8 ++++++++
 src/net/slipcor/pvparena/core/Language.java         |  1 +
 src/net/slipcor/pvparena/loadables/ArenaModule.java | 10 ++++++++++
 5 files changed, 21 insertions(+)

diff --git a/lang/lang_en.yml b/lang/lang_en.yml
index b7cd3d217..86a69781b 100644
--- a/lang/lang_en.yml
+++ b/lang/lang_en.yml
@@ -544,6 +544,7 @@ nulang:
       llposition: You are on queue position %1%!
       llrejoin: Ready check has caught you not being able to join. Rejoin when you can!
       llwait: Arena will be starting soon, please wait!
+      llleave: You have left the queue of the %1% arena.
     playerfinder:
       near: 'Nearest player: %1% blocks!'
       point: Compass pointing to nearest player!
diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml
index a913bd22a..c4c4c7990 100644
--- a/lang/lang_fr.yml
+++ b/lang/lang_fr.yml
@@ -595,6 +595,7 @@ nulang:
       llrejoin: Vous n'êtes pas en mesure de rejoindre les joueurs prêts. Rejoignez-les
         quand vous pouvez !
       llwait: L'arène va ouvrir prochainement, veuillez être patient !
+      llleave: Vous venez de quitter la file d'attente de l'arène %1%.
     playerfinder:
       near: 'Joueur le plus proche: %1% blocs!'
       point: La boussole pointe sur le joueur le plus proche !
diff --git a/src/net/slipcor/pvparena/commands/PAG_Leave.java b/src/net/slipcor/pvparena/commands/PAG_Leave.java
index da8e053b5..1cef43aa1 100644
--- a/src/net/slipcor/pvparena/commands/PAG_Leave.java
+++ b/src/net/slipcor/pvparena/commands/PAG_Leave.java
@@ -7,6 +7,7 @@
 import net.slipcor.pvparena.core.Help.HELP;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
+import net.slipcor.pvparena.loadables.ArenaModule;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 
@@ -45,6 +46,13 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
 
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(sender.getName());
 
+        // Handle modules which need to leave even if players aren't in an arena
+        for (final ArenaModule mod : arena.getMods()) {
+            if(mod.handleSpecialLeave(aPlayer)) {
+                return;
+            }
+        }
+
         if (!arena.hasPlayer(aPlayer.get())) {
 
             arena.msg(sender, Language.parse(arena, MSG.ERROR_NOT_IN_ARENA));
diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java
index e76b9ef6b..ce7753037 100644
--- a/src/net/slipcor/pvparena/core/Language.java
+++ b/src/net/slipcor/pvparena/core/Language.java
@@ -648,6 +648,7 @@ public enum MSG {
         MODULE_LATELOUNGE_POSITION("nulang.mod.latelounge.llposition", "You are in queue. Position: #%1%"),
         MODULE_LATELOUNGE_REJOIN("nulang.mod.latelounge.llrejoin", "Ready check has caught you not being able to join. Rejoin when you can!"),
         MODULE_LATELOUNGE_WAIT("nulang.mod.latelounge.llwait", "Arena will be starting soon, please wait!"),
+        MODULE_LATELOUNGE_LEAVE("nulang.mod.latelounge.llleave", "You have left the queue of the %1% arena."),
 
         MODULE_PLAYERFINDER_NEAR("nulang.mod.playerfinder.near", "Nearest player: %1% blocks!"),
         MODULE_PLAYERFINDER_POINT("nulang.mod.playerfinder.point", "Compass pointing to nearest player!"),
diff --git a/src/net/slipcor/pvparena/loadables/ArenaModule.java b/src/net/slipcor/pvparena/loadables/ArenaModule.java
index fd7149667..965827374 100644
--- a/src/net/slipcor/pvparena/loadables/ArenaModule.java
+++ b/src/net/slipcor/pvparena/loadables/ArenaModule.java
@@ -493,6 +493,16 @@ public boolean tryDeathOverride(final ArenaPlayer aPlayer,
         return false;
     }
 
+    /**
+     * Call a special leave directly from the module
+     *
+     * @param aPlayer the player who leaves
+     * @return true if a module cares
+     */
+    public boolean handleSpecialLeave(final ArenaPlayer aPlayer) {
+        return false;
+    }
+
     /**
      * hook into a player removal
      *

From d52d04444a637503d3ac8f00be7f10412eeebe07 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 5 Jun 2020 01:58:03 +0200
Subject: [PATCH 058/115] v1.15 - simplify scoreboard management

---
 src/net/slipcor/pvparena/arena/Arena.java     | 402 +++++++-----------
 .../slipcor/pvparena/arena/ArenaPlayer.java   |   9 +-
 2 files changed, 153 insertions(+), 258 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index 783265661..f178a07ec 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -41,6 +41,9 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.*;
+import java.util.stream.Collectors;
+
+import static java.util.Optional.ofNullable;
 
 /**
  * 
@@ -410,15 +413,9 @@ public Player getEntityOwner(final Entity entity) {
      * hand over everyone being part of the arena
      */
     public Set getEveryone() {
-
-        final Set players = new HashSet<>();
-
-        for (final ArenaPlayer ap : ArenaPlayer.getAllArenaPlayers()) {
-            if (equals(ap.getArena())) {
-                players.add(ap);
-            }
-        }
-        return players;
+        return ArenaPlayer.getAllArenaPlayers().stream()
+                .filter(ap -> this.equals(ap.getArena()))
+                .collect(Collectors.toSet());
     }
 
     /**
@@ -529,90 +526,63 @@ public Set getSpawns() {
     }
 
     private Scoreboard getSpecialScoreboard() {
-        if (scoreboard == null) {
-            scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
-/*
-            Objective oBM = Bukkit.getScoreboardManager().getMainScoreboard().getObjective(DisplaySlot.BELOW_NAME);
-            if (oBM != null) {
-                oBM = scoreboard.registerNewObjective(oBM.getCriteria(), oBM.getDisplayName());
-                oBM.setDisplaySlot(DisplaySlot.BELOW_NAME);
+        if (this.scoreboard == null) {
+            this.scoreboard = this.getCommonScoreboard(true);
 
-            }
-
-            Objective oTB = Bukkit.getScoreboardManager().getMainScoreboard().getObjective(DisplaySlot.PLAYER_LIST);
-            if (oTB != null) {
-                oTB = scoreboard.registerNewObjective(oTB.getCriteria(), oTB.getDisplayName());
-                oTB.setDisplaySlot(DisplaySlot.PLAYER_LIST);
-            }
-*/
-            for (final ArenaTeam team : getTeams()) {
+            // length = 18 without arena name
+            String sbHeaderPrefix = ChatColor.GREEN + "PVP Arena" + ChatColor.RESET + " - " + ChatColor.YELLOW;
+            String sbHeaderName = sbHeaderPrefix + this.getName();
 
-                try {
-                    scoreboard.registerNewTeam(team.getName());
-                    final Team bukkitTeam = scoreboard.getTeam(team.getName());
-                    if (!getArenaConfig().getBoolean(CFG.PLAYER_COLLISION)) {
-                        bukkitTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
-                    }
-                    bukkitTeam.setPrefix(team.getColor().toString());
-                    bukkitTeam.setSuffix(ChatColor.RESET.toString());
-                    bukkitTeam.setColor(team.getColor());
-                    bukkitTeam.addEntry(team.getName());
-                    bukkitTeam.setAllowFriendlyFire(getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL));
-
-                    bukkitTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-            }
-
-            if (scoreboard.getObjective("lives") != null) {
-                scoreboard.getObjective("lives").unregister();
-                if (scoreboard.getObjective(DisplaySlot.SIDEBAR) != null) {
-                    scoreboard.getObjective(DisplaySlot.SIDEBAR).unregister();
+            if (sbHeaderName.length() > 32) {
+                if (this.prefix.length() <= 14) {
+                    sbHeaderName = sbHeaderPrefix + this.prefix;
+                } else {
+                    sbHeaderName = sbHeaderName.substring(0, 32);
                 }
             }
 
-
-
-            String name = ChatColor.GREEN + "PVP Arena" + ChatColor.RESET + " - " + ChatColor.YELLOW + getName();
-
-            if (name.length() > 32) {
-                if (prefix.length() < getName().length()) {
-                    name = ChatColor.GREEN + "PVP Arena" + ChatColor.RESET + " - " + ChatColor.YELLOW + prefix;
-                } else {
-                    name = name.substring(0, 32);
+            if (this.scoreboard.getObjective("lives") != null) {
+                this.scoreboard.getObjective("lives").unregister();
+                if (this.scoreboard.getObjective(DisplaySlot.SIDEBAR) != null) {
+                    this.scoreboard.getObjective(DisplaySlot.SIDEBAR).unregister();
                 }
             }
-            Objective obj = scoreboard.registerNewObjective("lives", "dummy", name); //deathCount
+            Objective obj = this.scoreboard.registerNewObjective("lives", "dummy", sbHeaderName); //deathCount
 
             if (this.isFightInProgress()) {
                 obj.setDisplaySlot(DisplaySlot.SIDEBAR);
             }
         }
-        return scoreboard;
+        return this.scoreboard;
     }
 
     private Scoreboard getStandardScoreboard() {
-        if (scoreboard == null) {
-            scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
-            for (final ArenaTeam team : getTeams()) {
-                final Team sTeam = scoreboard.registerNewTeam(team.getName());
-                sTeam.setPrefix(team.getColor().toString());
-                sTeam.setSuffix(ChatColor.RESET.toString());
-                sTeam.setColor(team.getColor());
-                sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
-                if (!getArenaConfig().getBoolean(CFG.PLAYER_COLLISION)) {
-                    sTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
+        if (this.scoreboard == null) {
+            return this.getCommonScoreboard(false);
+        }
+        return this.scoreboard;
+    }
+
+    private Scoreboard getCommonScoreboard(boolean addTeamEntry) {
+        if (this.scoreboard == null) {
+            this.scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
+            for (final ArenaTeam team : this.getTeams()) {
+                final Team sbTeam = this.scoreboard.registerNewTeam(team.getName());
+                sbTeam.setPrefix(team.getColor().toString());
+                sbTeam.setSuffix(ChatColor.RESET.toString());
+                sbTeam.setColor(team.getColor());
+                sbTeam.setCanSeeFriendlyInvisibles(!this.isFreeForAll());
+                sbTeam.setAllowFriendlyFire(this.getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL));
+                if (!this.getArenaConfig().getBoolean(CFG.PLAYER_COLLISION)) {
+                    sbTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
                 }
-                for (final ArenaPlayer aPlayer : team.getTeamMembers()) {
-                    sTeam.addEntry(aPlayer.getName());
+
+                if(addTeamEntry) {
+                    sbTeam.addEntry(team.getName());
                 }
-            } /*
-            for (Objective o : scoreboard.getObjectives()) {
-                o.setDisplaySlot(DisplaySlot.PLAYER_LIST);
-            } */
+            }
         }
-        return scoreboard;
+        return this.scoreboard;
     }
 
     public ArenaTeam getTeam(final String name) {
@@ -1309,46 +1279,50 @@ public void resetPlayers(final boolean force) {
     }
 
     private void resetScoreboard(final Player player, final boolean force, final boolean soft) {
-        if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
-            getDebugger().i("ScoreBoards: "+(soft?"(soft) ":"")+"remove: " + player.getName(), player);
+        if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+            this.getDebugger().i("ScoreBoards: "+(soft?"(soft) ":"")+"remove: " + player.getName(), player);
             try {
-                if (scoreboard != null) {
-                    for (final Team team : scoreboard.getTeams()) {
+                if (this.scoreboard != null) {
+                    for (final Team team : this.scoreboard.getTeams()) {
                         if (team.hasEntry(player.getName())) {
                             team.removeEntry(player.getName());
                             if (soft) {
-                                updateScoreboards();
+                                this.updateScoreboards();
                                 return;
                             }
-                            scoreboard.resetScores(player.getName());
+                            this.scoreboard.resetScores(player.getName());
                         }
                     }
                 } else {
-                    getDebugger().i("ScoreBoards: scoreboard is null!");
+                    this.getDebugger().i("ScoreBoards: scoreboard is null!");
                     return;
                 }
+
                 final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
-                class RunLater implements Runnable {
-                    @Override
-                    public void run() {
-                        if (ap.hasBackupScoreboard()) {
-                            player.setScoreboard(ap.getBackupScoreboard());
+                if (ap.hasBackupScoreboard()) {
+                    this.getDebugger().i("ScoreBoards: restoring " + ap.get());
+
+                    class RunLater extends BukkitRunnable {
+                        @Override
+                        public void run() {
+                            Scoreboard backupScoreboard = ap.getBackupScoreboard();
                             if (ap.getBackupScoreboardTeam() != null && !force) {
-                                ap.getBackupScoreboardTeam().addEntry(ap.getName());
+                                backupScoreboard.getTeam(ap.getBackupScoreboardTeam()).addEntry(ap.getName());
                             }
+                            player.setScoreboard(backupScoreboard);
                             ap.setBackupScoreboardTeam(null);
                             ap.setBackupScoreboard(null);
                         }
                     }
-                }
-                getDebugger().i("ScoreBoards: maybe restoring " + ap.get());
-                if (force) {
-                    new RunLater().run();
-                } else {
-                    try {
-                        Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 4L);
-                    } catch (IllegalStateException ignored) {
 
+                    if (force) {
+                        new RunLater().run();
+                    } else {
+                        try {
+                            new RunLater().runTaskLater(PVPArena.instance, 2L);
+                        } catch (IllegalStateException ignored) {
+
+                        }
                     }
                 }
 
@@ -1356,7 +1330,7 @@ public void run() {
                 e.printStackTrace();
             }
         } else {
-            Team team = getStandardScoreboard().getEntryTeam(player.getName());
+            Team team = this.getStandardScoreboard().getEntryTeam(player.getName());
             if (team != null) {
                 team.removeEntry(player.getName());
                 if (soft) {
@@ -1364,19 +1338,19 @@ public void run() {
                 }
             }
             final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
-            try {
-                Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
-                    if (ap.hasBackupScoreboard()) {
-                        player.setScoreboard(ap.getBackupScoreboard());
+            if (ap.hasBackupScoreboard()) {
+                try {
+                    Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+                        Scoreboard backupScoreboard = ap.getBackupScoreboard();
                         if (ap.getBackupScoreboardTeam() != null) {
-                            ap.getBackupScoreboardTeam().addEntry(ap.getName());
+                            backupScoreboard.getTeam(ap.getBackupScoreboardTeam()).addEntry(ap.getName());
                         }
+                        player.setScoreboard(backupScoreboard);
                         ap.setBackupScoreboardTeam(null);
-                        ap.setBackupScoreboard(null);
-                    }
-                }, 5L);
-            } catch (IllegalPluginAccessException ignored) {
+                    }, 3L);
+                } catch (IllegalPluginAccessException ignored) {
 
+                }
             }
         }
     }
@@ -1526,7 +1500,7 @@ private void resetPlayer(final Player player, final String destination, final bo
         if (aPlayer.getState() != null) {
             aPlayer.getState().unload(soft);
         }
-        resetScoreboard(player, force, soft);
+        this.resetScoreboard(player, force, soft);
 
         //noinspection deprecation
         ArenaModuleManager.resetPlayer(this, player, soft, force);
@@ -1600,88 +1574,40 @@ public void run() {
     }
 
     public void setupScoreboard(final Player player) {
-        if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
-            final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
-            getDebugger().i("ScoreBoards: Initiating scoreboard for player " + player.getName());
-            if (!ap.hasBackupScoreboard() && player.getScoreboard() != null) {
-                ap.setBackupScoreboard(player.getScoreboard());
-                ap.setBackupScoreboardTeam(player.getScoreboard().getEntryTeam(ap.getName()));
-            } else if (ap.hasBackupScoreboard()) {
-                getDebugger().i("ScoreBoards: has backup: " + ap.hasBackupScoreboard());
-                getDebugger().i("ScoreBoards: player.getScoreboard == null: " + (player.getScoreboard() == null));
-            } else {
-                getDebugger().i("ScoreBoards: has backup: false");
-                getDebugger().i("ScoreBoards: player.getScoreboard == null: " + (player.getScoreboard() == null));
-            }
+        final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
 
-            // first, check if the scoreboard exists
-            class RunLater implements Runnable {
-                final Scoreboard board = getSpecialScoreboard();
-                @Override
-                public void run() {
+        this.getDebugger().i("ScoreBoards: Initiating scoreboard for player " + player.getName());
+        this.getDebugger().i("ScoreBoards: has backup: " + ap.hasBackupScoreboard());
+        this.getDebugger().i("ScoreBoards: player.getScoreboard == null: " + (player.getScoreboard() == null));
+        if (!ap.hasBackupScoreboard() && player.getScoreboard() != null) {
+            ap.setBackupScoreboard(player.getScoreboard());
+            ofNullable(player.getScoreboard().getEntryTeam(ap.getName())).ifPresent(team ->
+                    ap.setBackupScoreboardTeam(team.getName())
+            );
+        }
 
+        if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+            Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+                final Scoreboard board = this.getSpecialScoreboard();
 
-                    for (final ArenaTeam team : getTeams()) {
+                Optional optBoardTeam = ofNullable(ap.getArenaTeam()).map(team -> board.getTeam(team.getName()));
+                optBoardTeam.ifPresent(boardTeam -> boardTeam.addEntry(player.getName()));
 
-                        if (team == ArenaPlayer.parsePlayer(player.getName()).getArenaTeam()) {
-                            board.getTeam(team.getName()).addEntry(player.getName());
-                            updateScoreboard(player);
-                            return;
-                        }
-                    }
-                    try {
-                        ArenaTeam team = ap.getArenaTeam();
-                        if (team == null) {
-                            updateScoreboard(player);
-                            return;
-                        }
-                        scoreboard.registerNewTeam(team.getName());
-                        final Team bukkitTeam = scoreboard.getTeam(team.getName());
-                        bukkitTeam.setPrefix(team.getColor().toString());
-                        bukkitTeam.setSuffix(ChatColor.RESET.toString());
-                        bukkitTeam.setColor(team.getColor());
-                        bukkitTeam.addEntry(team.getName());
-                        bukkitTeam.setAllowFriendlyFire(getArenaConfig().getBoolean(CFG.PERMS_TEAMKILL));
-                        bukkitTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
-                    } catch (final Exception e) {
-                        e.printStackTrace();
-                    }
+                this.updateScoreboard(player);
 
-                    if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARDROUNDDISPLAY)) {
-                        addCustomScoreBoardEntry(null, Language.parse(MSG.ROUNDS_DISPLAY,
-                                String.valueOf(getRound()),
-                                String.valueOf(getRoundCount())),  199);
-                        addCustomScoreBoardEntry(null, Language.parse(MSG.ROUNDS_DISPLAYSEPARATOR), 198);
-                    }
+                if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARDROUNDDISPLAY)) {
+                    this.addCustomScoreBoardEntry(null, Language.parse(MSG.ROUNDS_DISPLAY,
+                            String.valueOf(this.getRound()),
+                            String.valueOf(this.getRoundCount())),  199);
+                    this.addCustomScoreBoardEntry(null, Language.parse(MSG.ROUNDS_DISPLAYSEPARATOR), 198);
                 }
-
-            }
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 5L);
+            }, 1L);
         } else {
-            final Scoreboard board = getStandardScoreboard();
-            ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
-            final ArenaTeam team = ap.getArenaTeam();
-            if (!ap.hasBackupScoreboard() && player.getScoreboard() != null) {
-                ap.setBackupScoreboard(player.getScoreboard());
-                ap.setBackupScoreboardTeam(player.getScoreboard().getEntryTeam(ap.getName()));
-            }
+            final Scoreboard board = this.getStandardScoreboard();
 
             player.setScoreboard(board);
-            if (team == null) {
-                return;
-            }
-            for (final Team sTeam : board.getTeams()) {
-                if (sTeam.getName().equals(team.getName())) {
-                    sTeam.addEntry(player.getName());
-                    return;
-                }
-            }
-            final Team sTeam = board.registerNewTeam(team.getName());
-            sTeam.setPrefix(team.getColor().toString());
-            sTeam.setColor(team.getColor());
-            sTeam.setSuffix(ChatColor.RESET.toString());
-            sTeam.addEntry(player.getName());
-            sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
+            Optional optBoardTeam = ofNullable(ap.getArenaTeam()).map(team -> board.getTeam(team.getName()));
+            optBoardTeam.ifPresent(boardTeam -> boardTeam.addEntry(player.getName()));
         }
     }
 
@@ -2391,34 +2317,31 @@ public void updateRounds() {
     }
 
     public void updateScoreboards() {
-        if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() {
-                @Override
-                public void run() {
-                    if (isFreeForAll()) {
-                        for (ArenaPlayer ap : getEveryone()) {
-                            int value = PACheck.handleGetLives(Arena.this, ap);
-                            if (value >= 0) {
-                                getSpecialScoreboard().getObjective("lives").getScore(ap.getName()).setScore(value);
-                            }
-                            Player player = ap.get();
-                            if (player != null && (player.getScoreboard() == null || !player.getScoreboard().equals(getSpecialScoreboard()))) {
-                                player.setScoreboard(getSpecialScoreboard());
-                            }
+        if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+            Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+                final Scoreboard currentScoreboard = this.getSpecialScoreboard();
+                if (this.isFreeForAll()) {
+                    for (ArenaPlayer ap : this.getEveryone()) {
+                        int value = PACheck.handleGetLives(this, ap);
+                        if (value >= 0) {
+                            currentScoreboard.getObjective("lives").getScore(ap.getName()).setScore(value);
                         }
-                    } else {
-                        for (ArenaTeam team : getTeams()) {
-                            for (ArenaPlayer ap : team.getTeamMembers()) {
-                                getSpecialScoreboard().getObjective("lives").getScore(team.getName()).setScore(
-                                        PACheck.handleGetLives(Arena.this, ap));
-                                break;
-                            }
+                        Player player = ap.get();
+                        if (player != null && !currentScoreboard.equals(player.getScoreboard())) {
+                            player.setScoreboard(currentScoreboard);
                         }
-                        for (ArenaPlayer ap : getEveryone()) {
-                            Player player = ap.get();
-                            if (player != null && (player.getScoreboard() == null || !player.getScoreboard().equals(getSpecialScoreboard()))) {
-                                player.setScoreboard(getSpecialScoreboard());
-                            }
+                    }
+                } else {
+                    for (ArenaTeam team : this.getTeams()) {
+                        ArenaPlayer randomTeamPlayer = team.getTeamMembers().iterator().next();
+                        currentScoreboard.getObjective("lives")
+                                .getScore(team.getName())
+                                .setScore(PACheck.handleGetLives(this, randomTeamPlayer));
+                    }
+                    for (ArenaPlayer ap : this.getEveryone()) {
+                        Player player = ap.get();
+                        if (player != null && !currentScoreboard.equals(player.getScoreboard())) {
+                            player.setScoreboard(currentScoreboard);
                         }
                     }
                 }
@@ -2427,59 +2350,38 @@ public void run() {
     }
 
     private void updateScoreboard(final Player player) {
-        if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+        if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+            Scoreboard currentScoreboard = this.getSpecialScoreboard();
             final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
-            if (ap.getArenaTeam() == null) {
-                // a spectator, special case. Just update and do not add to the scores
-                if (player.getScoreboard() == null || !player.getScoreboard().equals(getSpecialScoreboard())) {
-                    player.setScoreboard(getSpecialScoreboard());
-                }
-                return;
-            }
-            if (isFreeForAll()) {
-                final Score score = getSpecialScoreboard().getObjective("lives").getScore(player.getName());
-                score.setScore(PACheck.handleGetLives(this, ArenaPlayer.parsePlayer(player.getName())));
-            } else {
-                getSpecialScoreboard().getObjective("lives").getScore(ap.getArenaTeam().getName()).setScore(PACheck.handleGetLives(this, ap));
-            }
-            if (player.getScoreboard() == null || !player.getScoreboard().equals(getSpecialScoreboard())) {
-                player.setScoreboard(getSpecialScoreboard());
+
+            // if player is a spectator, special case. Just update and do not add to the scores
+            if (ap.getArenaTeam() != null) {
+                currentScoreboard.getObjective("lives")
+                        .getScore(this.isFreeForAll() ? player.getName() : ap.getArenaTeam().getName())
+                        .setScore(PACheck.handleGetLives(this, ap));
             }
+
+            player.setScoreboard(currentScoreboard);
         }
     }
 
     public void updateScoreboardTeam(final Player player, final ArenaTeam oldTeam, final ArenaTeam newTeam) {
-        if (getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
-            final Scoreboard board = getSpecialScoreboard();
-            class RunLater implements Runnable {
-
-                @Override
-                public void run() {
+        if (this.getArenaConfig().getBoolean(CFG.USES_SCOREBOARD)) {
+            final Scoreboard board = this.getSpecialScoreboard();
 
-                    final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
-                    if (aPlayer.getArenaTeam() != null) {
-                        board.getTeam(oldTeam.getName()).removeEntry(player.getName());
+            Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+                board.getTeam(oldTeam.getName()).removeEntry(player.getName());
 
-                        for (final Team sTeam : board.getTeams()) {
-                            if (sTeam.getName().equals(newTeam.getName())) {
-                                sTeam.addEntry(player.getName());
-                                return;
-                            }
-                        }
-                        final Team sTeam = board.registerNewTeam(newTeam.getName());
-                        sTeam.setPrefix(newTeam.getColor().toString());
-                        sTeam.setSuffix(ChatColor.RESET.toString());
-                        sTeam.setColor(newTeam.getColor());
+                for (final Team sTeam : board.getTeams()) {
+                    if (sTeam.getName().equals(newTeam.getName())) {
                         sTeam.addEntry(player.getName());
-                        sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
+                        return;
                     }
-                    updateScoreboard(player);
                 }
-
-            }
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 1L);
+                this.updateScoreboard(player);
+            }, 1L);
         } else {
-            Scoreboard board = getStandardScoreboard();
+            Scoreboard board = this.getStandardScoreboard();
             board.getTeam(oldTeam.getName()).removeEntry(player.getName());
 
             for (final Team sTeam : board.getTeams()) {
@@ -2488,12 +2390,6 @@ public void run() {
                     return;
                 }
             }
-            final Team sTeam = board.registerNewTeam(newTeam.getName());
-            sTeam.setPrefix(newTeam.getColor().toString());
-            sTeam.setSuffix(ChatColor.RESET.toString());
-            sTeam.setColor(newTeam.getColor());
-            sTeam.setCanSeeFriendlyInvisibles(!isFreeForAll());
-            sTeam.addEntry(player.getName());
         }
     }
 
diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
index f7f415db9..8bdf1f713 100644
--- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java
+++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
@@ -24,7 +24,6 @@
 import org.bukkit.permissions.PermissionAttachment;
 import org.bukkit.projectiles.ProjectileSource;
 import org.bukkit.scoreboard.Scoreboard;
-import org.bukkit.scoreboard.Team;
 
 import java.io.File;
 import java.util.*;
@@ -64,7 +63,7 @@ public class ArenaPlayer {
     private final Map statistics = new HashMap<>();
 
     private Scoreboard backupBoard;
-    private Team backupBoardTeam;
+    private String backupBoardTeam;
 
     /**
      * Status
@@ -516,7 +515,7 @@ public Scoreboard getBackupScoreboard() {
         return backupBoard;
     }
 
-    public Team getBackupScoreboardTeam() {
+    public String getBackupScoreboardTeam() {
         return backupBoardTeam;
     }
 
@@ -798,8 +797,8 @@ public void setBackupScoreboard(Scoreboard board) {
         backupBoard = board;
     }
 
-    public void setBackupScoreboardTeam(Team team) {
-        backupBoardTeam = team;
+    public void setBackupScoreboardTeam(String sbTeamName) {
+        this.backupBoardTeam = sbTeamName;
     }
 
     public void setMayDropInventory(boolean value) {

From 04626ae708b9cd861672933c47686bde30e1d407 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 15 Jun 2020 21:41:08 +0200
Subject: [PATCH 059/115] v1.15 - init scoreboard after teleportation

---
 src/net/slipcor/pvparena/arena/Arena.java     | 52 +++++++++++--------
 .../slipcor/pvparena/commands/PAG_Join.java   |  4 +-
 .../pvparena/commands/PAG_Spectate.java       |  4 +-
 .../slipcor/pvparena/goals/GoalInfect.java    |  2 +-
 src/net/slipcor/pvparena/goals/GoalTank.java  |  2 +-
 .../pvparena/listeners/PlayerListener.java    |  2 +-
 .../pvparena/managers/SpawnManager.java       | 12 ++---
 .../pvparena/modules/BattlefieldJoin.java     |  2 +-
 .../pvparena/modules/StandardLounge.java      |  8 +--
 .../pvparena/modules/StandardSpectate.java    |  6 +--
 .../pvparena/runnables/RespawnRunnable.java   |  4 +-
 11 files changed, 52 insertions(+), 46 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index f178a07ec..6fcac2249 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -35,7 +35,10 @@
 import org.bukkit.plugin.IllegalPluginAccessException;
 import org.bukkit.projectiles.ProjectileSource;
 import org.bukkit.scheduler.BukkitRunnable;
-import org.bukkit.scoreboard.*;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.bukkit.scoreboard.Objective;
+import org.bukkit.scoreboard.Scoreboard;
+import org.bukkit.scoreboard.Team;
 import org.bukkit.util.Vector;
 
 import java.io.File;
@@ -1573,8 +1576,8 @@ public void run() {
         }
     }
 
-    public void setupScoreboard(final Player player) {
-        final ArenaPlayer ap = ArenaPlayer.parsePlayer(player.getName());
+    public void setupScoreboard(final ArenaPlayer ap) {
+        Player player = ap.get();
 
         this.getDebugger().i("ScoreBoards: Initiating scoreboard for player " + player.getName());
         this.getDebugger().i("ScoreBoards: has backup: " + ap.hasBackupScoreboard());
@@ -1930,8 +1933,10 @@ public String toString() {
         return name;
     }
 
-    public void tpPlayerToCoordName(Player player, String place) {
-        this.tpPlayerToCoordName(player, place, false);
+    public void tpPlayerToCoordName(ArenaPlayer player, String place) {
+        Location destination = this.prepareTeleportation(player, place);
+        this.teleportPlayer(place, player, destination);
+        this.execPostTeleportationFixes(player);
     }
 
     /**
@@ -1940,12 +1945,23 @@ public void tpPlayerToCoordName(Player player, String place) {
      * @param player the player to teleport
      * @param place  the coord string
      */
-    public void tpPlayerToCoordName(final Player player, final String place, final boolean runAsync) {
+    public void tpPlayerToCoordNameForJoin(final ArenaPlayer player, final String place, boolean async) {
+        Location destination = this.prepareTeleportation(player, place);
+        int delay = async ? 2 : 0;
+        Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
+            teleportPlayer(place, player, destination);
+            setupScoreboard(player);
+        }, delay);
+        this.execPostTeleportationFixes(player);
+    }
+
+    private Location prepareTeleportation(ArenaPlayer aPlayer, String place) {
+        Player player = aPlayer.get();
         getDebugger().i("teleporting " + player + " to coord " + place, player);
 
         if (player == null) {
             PVPArena.instance.getLogger().severe("Player null!");
-            return;
+            throw new RuntimeException("Player null!");
         }
 
         if (player.isInsideVehicle()) {
@@ -1954,8 +1970,6 @@ public void tpPlayerToCoordName(final Player player, final String place, final b
 
         ArenaModuleManager.tpPlayerToCoordName(this, player, place);
 
-        final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
-
         if ("spectator".equals(place)) {
             if (getFighters().contains(aPlayer)) {
                 aPlayer.setStatus(Status.LOST);
@@ -1968,8 +1982,7 @@ public void tpPlayerToCoordName(final Player player, final String place, final b
             loc = aPlayer.getSavedLocation();
         }
         if (loc == null) {
-            new Exception("TP Spawn null: " + name + "->" + place).printStackTrace();
-            return;
+            throw new RuntimeException("TP Spawn null: " + name + "->" + place);
         }
 
         debug.i("raw location: " + loc.toString());
@@ -1982,16 +1995,13 @@ public void tpPlayerToCoordName(final Player player, final String place, final b
 
         aPlayer.setTeleporting(true);
         aPlayer.setTelePass(true);
-        final Location destination = loc.toLocation().add(offset.getX(), offset.getY(), offset.getZ());
-        if(runAsync) {
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> teleportPlayer(place, aPlayer, destination), 2);
-        } else {
-            this.teleportPlayer(place, aPlayer, destination);
-        }
+        return loc.toLocation().add(offset.getX(), offset.getY(), offset.getZ());
+    }
 
+    private void execPostTeleportationFixes(ArenaPlayer aPlayer) {
         if (cfg.getBoolean(CFG.PLAYER_REMOVEARROWS)) {
             try {
-                new ArrowHack(player);
+                new ArrowHack(aPlayer.get());
             } catch (final Exception e) {
             }
         }
@@ -2016,8 +2026,8 @@ public void run() {
             Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() {
                 @Override
                 public void run() {
-                    player.setAllowFlight(false);
-                    player.setFlying(false);
+                    aPlayer.get().setAllowFlight(false);
+                    aPlayer.get().setFlying(false);
                 }
             }, 5L);
         }
@@ -2142,7 +2152,7 @@ && getClass(autoClass) == null) {
 
         for (final PASpawn spawn : spawns) {
             if (--pos < 0) {
-                tpPlayerToCoordName(player, spawn.getName());
+                this.tpPlayerToCoordName(aPlayer, spawn.getName());
                 break;
             }
         }
diff --git a/src/net/slipcor/pvparena/commands/PAG_Join.java b/src/net/slipcor/pvparena/commands/PAG_Join.java
index 8b495367b..94f1c61dc 100644
--- a/src/net/slipcor/pvparena/commands/PAG_Join.java
+++ b/src/net/slipcor/pvparena/commands/PAG_Join.java
@@ -86,9 +86,7 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
                 arena.getDebugger().i("Join_2", sender);
                 arena.msg(sender, Language.parse(arena, MSG.ERROR_ARENA_ALREADY_PART_OF, ArenaManager.getIndirectArenaName(arena)));
             } else {
-                if (PACheck.handleJoin(arena, sender, args)) {
-                    arena.setupScoreboard(aPlayer.get());
-                }
+                PACheck.handleJoin(arena, sender, args);
             }
         } else {
             final Arena pArena = aPlayer.getArena();
diff --git a/src/net/slipcor/pvparena/commands/PAG_Spectate.java b/src/net/slipcor/pvparena/commands/PAG_Spectate.java
index 40082880a..a46415d67 100644
--- a/src/net/slipcor/pvparena/commands/PAG_Spectate.java
+++ b/src/net/slipcor/pvparena/commands/PAG_Spectate.java
@@ -49,9 +49,7 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
             return;
         }
 
-        if (PACheck.handleSpectate(arena, sender)) {
-            arena.setupScoreboard((Player) sender);
-        }
+        PACheck.handleSpectate(arena, sender);
     }
 
     @Override
diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java
index 03b6b2058..1479994d4 100644
--- a/src/net/slipcor/pvparena/goals/GoalInfect.java
+++ b/src/net/slipcor/pvparena/goals/GoalInfect.java
@@ -701,7 +701,7 @@ public void parseStart() {
 
         for (final PASpawn spawn : spawns) {
             if (pos-- < 0) {
-                arena.tpPlayerToCoordName(infected.get(), spawn.getName());
+                this.arena.tpPlayerToCoordName(infected, spawn.getName());
                 break;
             }
         }
diff --git a/src/net/slipcor/pvparena/goals/GoalTank.java b/src/net/slipcor/pvparena/goals/GoalTank.java
index ec2b41483..9cc37e0ed 100644
--- a/src/net/slipcor/pvparena/goals/GoalTank.java
+++ b/src/net/slipcor/pvparena/goals/GoalTank.java
@@ -376,7 +376,7 @@ public void parseStart() {
 
         for (final PASpawn spawn : spawns) {
             if (--pos < 0) {
-                arena.tpPlayerToCoordName(tank.get(), spawn.getName());
+                this.arena.tpPlayerToCoordName(tank, spawn.getName());
                 break;
             }
         }
diff --git a/src/net/slipcor/pvparena/listeners/PlayerListener.java b/src/net/slipcor/pvparena/listeners/PlayerListener.java
index 6f38f42f0..c096b4e92 100644
--- a/src/net/slipcor/pvparena/listeners/PlayerListener.java
+++ b/src/net/slipcor/pvparena/listeners/PlayerListener.java
@@ -672,7 +672,7 @@ public void run() {
                 for (final PASpawn spawn : spawns) {
 
                     if (--pos < 0) {
-                        arena.tpPlayerToCoordName(player, spawn.getName());
+                        arena.tpPlayerToCoordName(aPlayer, spawn.getName());
                         break;
                     }
                 }
diff --git a/src/net/slipcor/pvparena/managers/SpawnManager.java b/src/net/slipcor/pvparena/managers/SpawnManager.java
index a0ecc29b2..528cd1f09 100644
--- a/src/net/slipcor/pvparena/managers/SpawnManager.java
+++ b/src/net/slipcor/pvparena/managers/SpawnManager.java
@@ -137,13 +137,13 @@ public void run() {
                             int pos = new Random().nextInt(spawns.size());
                             for (final PASpawn spawn : spawns) {
                                 if (--pos < 0) {
-                                    arena.tpPlayerToCoordName(ap.get(), spawn.getName());
+                                    arena.tpPlayerToCoordName(ap, spawn.getName());
                                     break;
                                 }
                             }
 
                         } else {
-                            arena.tpPlayerToCoordName(ap.get(), locations[pos++ % locations.length].getName());
+                            arena.tpPlayerToCoordName(ap, locations[pos++ % locations.length].getName());
                         }
                         ap.setStatus(Status.FIGHT);
                         teamMembers.remove(ap);
@@ -210,14 +210,14 @@ public void run() {
                         int pos = new Random().nextInt(spawns.size());
                         for (final PASpawn spawn : spawns) {
                             if (--pos < 0) {
-                                arena.tpPlayerToCoordName(ap.get(), spawn.getName());
+                                arena.tpPlayerToCoordName(ap, spawn.getName());
                                 break;
                             }
                         }
 
                     } else {
                         for (final PASpawn s : spawns) {
-                            arena.tpPlayerToCoordName(ap.get(), s.getName());
+                            arena.tpPlayerToCoordName(ap, s.getName());
                             if (spawns.size() > 1) {
                                 spawns.remove(s);
                             }
@@ -307,7 +307,7 @@ public void run() {
                     if (spawnName == null) {
                         PVPArena.instance.getLogger().warning("Element #" + pos + " is null: [" + StringParser.joinArray(iteratings, ",") + ']');
                     }
-                    arena.tpPlayerToCoordName(ap.get(), spawnName);
+                    arena.tpPlayerToCoordName(ap, spawnName);
                     set.remove(ap);
                     return;
                 }
@@ -518,7 +518,7 @@ public void run() {
 
                 aPlayer.setStatus(Status.FIGHT);
 
-                arena.tpPlayerToCoordName(aPlayer.get(), "old");
+                arena.tpPlayerToCoordName(aPlayer, "old");
                 Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable() {
                             @Override
                             public void run() {
diff --git a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java
index 4a9b8bf1d..dc342c798 100644
--- a/src/net/slipcor/pvparena/modules/BattlefieldJoin.java
+++ b/src/net/slipcor/pvparena/modules/BattlefieldJoin.java
@@ -113,7 +113,7 @@ public void commitJoin(final Player sender, final ArenaTeam team) {
 
         for (final PASpawn spawn : spawns) {
             if (--pos < 0) {
-                arena.tpPlayerToCoordName(player.get(), spawn.getName(), true);
+                this.arena.tpPlayerToCoordNameForJoin(player, spawn.getName(), true);
                 break;
             }
         }
diff --git a/src/net/slipcor/pvparena/modules/StandardLounge.java b/src/net/slipcor/pvparena/modules/StandardLounge.java
index 2dcf98c11..f6d77e668 100644
--- a/src/net/slipcor/pvparena/modules/StandardLounge.java
+++ b/src/net/slipcor/pvparena/modules/StandardLounge.java
@@ -175,13 +175,13 @@ public void commitJoin(final Player sender, final ArenaTeam team) {
         player.setLocation(new PALocation(player.get().getLocation()));
 
         // ArenaPlayer.prepareInventory(arena, ap.get());
-        player.setArena(arena);
+        player.setArena(this.arena);
         team.add(player);
 
-        if (arena.isFreeForAll()) {
-            arena.tpPlayerToCoordName(player.get(), "lounge", true);
+        if (this.arena.isFreeForAll()) {
+            this.arena.tpPlayerToCoordNameForJoin(player, "lounge", true);
         } else {
-            arena.tpPlayerToCoordName(player.get(), team.getName() + "lounge", true);
+            this.arena.tpPlayerToCoordNameForJoin(player, team.getName() + "lounge", true);
         }
 
         player.setStatus(Status.LOUNGE);
diff --git a/src/net/slipcor/pvparena/modules/StandardSpectate.java b/src/net/slipcor/pvparena/modules/StandardSpectate.java
index f7f03ffe9..746e3a73e 100644
--- a/src/net/slipcor/pvparena/modules/StandardSpectate.java
+++ b/src/net/slipcor/pvparena/modules/StandardSpectate.java
@@ -68,11 +68,11 @@ public void commitSpectate(final Player player) {
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
         aPlayer.setLocation(new PALocation(player.getLocation()));
 
-        aPlayer.setArena(arena);
+        aPlayer.setArena(this.arena);
         aPlayer.setStatus(Status.WATCH);
 
-        arena.tpPlayerToCoordName(player, "spectator", true);
-        arena.msg(player, Language.parse(arena, MSG.NOTICE_WELCOME_SPECTATOR));
+        this.arena.tpPlayerToCoordNameForJoin(aPlayer, "spectator", true);
+        this.arena.msg(player, Language.parse(this.arena, MSG.NOTICE_WELCOME_SPECTATOR));
 
         if (aPlayer.getState() == null) {
 
diff --git a/src/net/slipcor/pvparena/runnables/RespawnRunnable.java b/src/net/slipcor/pvparena/runnables/RespawnRunnable.java
index 64d01b23e..5c4fa4f19 100644
--- a/src/net/slipcor/pvparena/runnables/RespawnRunnable.java
+++ b/src/net/slipcor/pvparena/runnables/RespawnRunnable.java
@@ -55,12 +55,12 @@ public void run() {
 
             for (final PASpawn spawn : spawns) {
                 if (--pos < 0) {
-                    arena.tpPlayerToCoordName(player.get(), spawn.getName());
+                    this.arena.tpPlayerToCoordName(player, spawn.getName());
                     break;
                 }
             }
         } else {
-            arena.tpPlayerToCoordName(player.get(), coordName);
+            this.arena.tpPlayerToCoordName(player, coordName);
         }
     }
 

From 27901f2d7fe077ae92214900521cabba95e38d95 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 22 Jun 2020 14:07:24 +0200
Subject: [PATCH 060/115] v1.15 - prettify empty flag error - issue #47

---
 src/net/slipcor/pvparena/goals/GoalFlags.java | 20 ++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java
index 764dc332d..1e5f0281b 100644
--- a/src/net/slipcor/pvparena/goals/GoalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalFlags.java
@@ -20,7 +20,9 @@
 import net.slipcor.pvparena.managers.StatisticsManager.type;
 import net.slipcor.pvparena.managers.TeamManager;
 import net.slipcor.pvparena.runnables.EndRunnable;
-import org.bukkit.*;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
 import org.bukkit.block.Block;
 import org.bukkit.block.data.BlockData;
 import org.bukkit.block.data.Directional;
@@ -416,8 +418,7 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
     @Override
     public PACheck checkSetBlock(final PACheck res, final Player player, final Block block) {
 
-        if (res.getPriority() > PRIORITY
-                || !PAA_Region.activeSelections.containsKey(player.getName())) {
+        if (res.getPriority() > PRIORITY || !PAA_Region.activeSelections.containsKey(player.getName())) {
             return res;
         }
 
@@ -426,8 +427,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block
             return res;
         }
 
-        if (!PVPArena.hasAdminPerms(player)
-                && !PVPArena.hasCreatePerms(player, this.arena)) {
+        if (!PVPArena.hasAdminPerms(player) && !PVPArena.hasCreatePerms(player, this.arena)) {
             return res;
         }
         res.setPriority(this, PRIORITY); // success :)
@@ -642,10 +642,12 @@ public boolean commitSetFlag(final Player player, final Block block) {
         // command : /pa redflag1
         // location: red1flag:
 
-        SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()),
-                this.flagName);
-
-        this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, this.flagName));
+        if(this.flagName == null || this.flagName.isEmpty()) {
+            this.arena.msg(player, Language.parse(this.arena, MSG.ERROR_ERROR, "Flag you are trying to set has no name."));
+        } else {
+            SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()), this.flagName);
+            this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_FLAGS_SET, this.flagName));
+        }
 
         PAA_Region.activeSelections.remove(player.getName());
         this.flagName = "";

From 2d107c926effd6766b06ea14ba497d9acf5bb408 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 23 Jun 2020 16:41:48 +0200
Subject: [PATCH 061/115] v1.15 - refactor arena stats system - fix issue #46

---
 src/net/slipcor/pvparena/PVPArena.java        |   1 -
 .../slipcor/pvparena/arena/ArenaPlayer.java   | 121 ++++----
 .../slipcor/pvparena/classes/PAStatMap.java   |  14 +-
 .../slipcor/pvparena/commands/PAI_Stats.java  |  23 +-
 src/net/slipcor/pvparena/core/Language.java   |  18 +-
 src/net/slipcor/pvparena/goals/GoalFlags.java |   4 +-
 .../slipcor/pvparena/goals/GoalSabotage.java  |   4 +-
 .../pvparena/managers/StatisticsManager.java  | 266 ++++++------------
 8 files changed, 165 insertions(+), 286 deletions(-)

diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java
index f97708276..7817e8f47 100644
--- a/src/net/slipcor/pvparena/PVPArena.java
+++ b/src/net/slipcor/pvparena/PVPArena.java
@@ -479,7 +479,6 @@ public void onEnable() {
         Help.init(getConfig().getString("language", "en"));
 
         StatisticsManager.initialize();
-        ArenaPlayer.initiate();
 
         getServer().getPluginManager()
                 .registerEvents(new BlockListener(), this);
diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
index 8bdf1f713..056ad46aa 100644
--- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java
+++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
@@ -13,7 +13,7 @@
 import net.slipcor.pvparena.managers.ArenaManager;
 import net.slipcor.pvparena.managers.InventoryManager;
 import net.slipcor.pvparena.managers.SpawnManager;
-import net.slipcor.pvparena.managers.StatisticsManager.type;
+import net.slipcor.pvparena.managers.StatisticsManager.Type;
 import org.bukkit.*;
 import org.bukkit.configuration.file.YamlConfiguration;
 import org.bukkit.entity.*;
@@ -109,28 +109,11 @@ public static boolean has(int value, PlayerPrevention s) {
     private final PABlockLocation[] selection = new PABlockLocation[2];
 
     private ArenaPlayer(final String playerName) {
-        name = playerName;
-
-        totalPlayers.put(name, this);
-    }
-
-    private ArenaPlayer(final Player player, final Arena arena) {
-        name = player.getName();
-        this.arena = arena;
-
-        totalPlayers.put(name, this);
-    }
-
-    public static int countPlayers() {
-        return totalPlayers.size();
+        this.name = playerName;
     }
 
     public static Set getAllArenaPlayers() {
-        final Set players = new HashSet<>();
-        for (final ArenaPlayer ap : totalPlayers.values()) {
-            players.add(ap);
-        }
-        return players;
+        return new HashSet<>(totalPlayers.values());
     }
 
     public boolean getFlyState() {
@@ -214,49 +197,39 @@ public static void givePlayerFightItems(final Arena arena, final Player player)
         }
     }
 
-    public static void initiate() {
-        debug.i("creating offline arena players");
-
-        if (!PVPArena.instance.getConfig().getBoolean("stats")) {
-            return;
-        }
-
-        final YamlConfiguration cfg = new YamlConfiguration();
-        try {
-            cfg.load(PVPArena.instance.getDataFolder() + "/players.yml");
-
-            final Set arenas = cfg.getKeys(false);
-
-            for (final String arenaname : arenas) {
-
-                final Set players = cfg.getConfigurationSection(arenaname).getKeys(false);
-                for (final String player : players) {
-                    totalPlayers.put(player, ArenaPlayer.parsePlayer(player));
-                }
+    /**
+     * get an ArenaPlayer from a player name
+     *
+     * @param name the playername to use
+     * @return an ArenaPlayer instance belonging to that player
+     */
+    public static ArenaPlayer parsePlayer(final String name) {
+        synchronized (ArenaPlayer.class) {
+            Player player = Bukkit.getPlayerExact(name);
 
+            // Offline player or NPC
+            if (player == null) {
+                return new ArenaPlayer(name);
             }
 
-        } catch (final Exception e) {
-            e.printStackTrace();
+            if(!totalPlayers.containsKey(name)) {
+                ArenaPlayer ap = new ArenaPlayer(player.getName());
+                totalPlayers.putIfAbsent(name, ap);
+            }
+            return totalPlayers.get(name);
         }
     }
 
     /**
-     * get an ArenaPlayer from a player name
+     * add an ArenaPlayer (used to load statistics)
      *
      * @param name the playername to use
      * @return an ArenaPlayer instance belonging to that player
      */
-    public static ArenaPlayer parsePlayer(final String name) {
+    public static ArenaPlayer addPlayer(final String name) {
         synchronized (ArenaPlayer.class) {
-            if (totalPlayers.get(name) == null) {
-                if (Bukkit.getPlayerExact(name) == null) {
-                    totalPlayers.put(name, new ArenaPlayer(name));
-                } else {
-                    totalPlayers.put(name,
-                            new ArenaPlayer(Bukkit.getPlayerExact(name), null));
-                }
-            }
+            ArenaPlayer aPlayer = new ArenaPlayer(name);
+            totalPlayers.putIfAbsent(name, aPlayer);
             return totalPlayers.get(name);
         }
     }
@@ -362,18 +335,18 @@ public void run() {
     }
 
     public void addDeath() {
-        getStatistics(arena).incStat(type.DEATHS);
+        getStatistics(arena).incStat(Type.DEATHS);
     }
 
     public void addKill() {
-        getStatistics(arena).incStat(type.KILLS);
+        getStatistics(arena).incStat(Type.KILLS);
     }
 
     public void addLosses() {
-        getStatistics(arena).incStat(type.LOSSES);
+        getStatistics(arena).incStat(Type.LOSSES);
     }
 
-    public void addStatistic(final String arenaName, final type type,
+    public void addStatistic(final String arenaName, final Type type,
                              final int value) {
         if (!statistics.containsKey(arenaName)) {
             statistics.put(arenaName, new PAStatMap());
@@ -383,7 +356,7 @@ public void addStatistic(final String arenaName, final type type,
     }
 
     public void addWins() {
-        getStatistics(arena).incStat(type.WINS);
+        getStatistics(arena).incStat(Type.WINS);
     }
 
     private void clearDump() {
@@ -588,7 +561,7 @@ public Set getTempPermissions() {
         return tempPermissions;
     }
 
-    public int getTotalStatistics(final type statType) {
+    public int getTotalStatistics(final Type statType) {
         int sum = 0;
 
         for (final PAStatMap stat : statistics.values()) {
@@ -676,34 +649,34 @@ public void reset() {
                 if (arena != null) {
                     final String arenaName = arena.getName();
                     cfg.set(arenaName + '.' + name + ".losses", getStatistics()
-                            .getStat(type.LOSSES)
-                            + getTotalStatistics(type.LOSSES));
+                            .getStat(Type.LOSSES)
+                            + getTotalStatistics(Type.LOSSES));
                     cfg.set(arenaName + '.' + name + ".wins",
                             getStatistics()
-                                    .getStat(type.WINS)
-                                    + getTotalStatistics(type.WINS));
+                                    .getStat(Type.WINS)
+                                    + getTotalStatistics(Type.WINS));
                     cfg.set(arenaName + '.' + name + ".kills",
                             getStatistics().getStat(
-                                    type.KILLS)
-                                    + getTotalStatistics(type.KILLS));
+                                    Type.KILLS)
+                                    + getTotalStatistics(Type.KILLS));
                     cfg.set(arenaName + '.' + name + ".deaths", getStatistics()
-                            .getStat(type.DEATHS)
-                            + getTotalStatistics(type.DEATHS));
+                            .getStat(Type.DEATHS)
+                            + getTotalStatistics(Type.DEATHS));
                     cfg.set(arenaName + '.' + name + ".damage", getStatistics()
-                            .getStat(type.DAMAGE)
-                            + getTotalStatistics(type.DAMAGE));
+                            .getStat(Type.DAMAGE)
+                            + getTotalStatistics(Type.DAMAGE));
                     cfg.set(arenaName + '.' + name + ".maxdamage",
                             getStatistics().getStat(
-                                    type.MAXDAMAGE)
-                                    + getTotalStatistics(type.MAXDAMAGE));
+                                    Type.MAXDAMAGE)
+                                    + getTotalStatistics(Type.MAXDAMAGE));
                     cfg.set(arenaName + '.' + name + ".damagetake",
                             getStatistics().getStat(
-                                    type.DAMAGETAKE)
-                                    + getTotalStatistics(type.DAMAGETAKE));
+                                    Type.DAMAGETAKE)
+                                    + getTotalStatistics(Type.DAMAGETAKE));
                     cfg.set(arenaName + '.' + name + ".maxdamagetake",
                             getStatistics().getStat(
-                                    type.MAXDAMAGETAKE)
-                                    + getTotalStatistics(type.MAXDAMAGETAKE));
+                                    Type.MAXDAMAGETAKE)
+                                    + getTotalStatistics(Type.MAXDAMAGETAKE));
                 }
 
                 cfg.save(file);
@@ -833,7 +806,7 @@ public void setSelection(final Location loc, final boolean second) {
         }
     }
 
-    public void setStatistic(final String arenaName, final type type,
+    public void setStatistic(final String arenaName, final Type type,
                              final int value) {
         if (!statistics.containsKey(arenaName)) {
             statistics.put(arenaName, new PAStatMap());
diff --git a/src/net/slipcor/pvparena/classes/PAStatMap.java b/src/net/slipcor/pvparena/classes/PAStatMap.java
index 81a8b9827..070af56ae 100644
--- a/src/net/slipcor/pvparena/classes/PAStatMap.java
+++ b/src/net/slipcor/pvparena/classes/PAStatMap.java
@@ -15,29 +15,29 @@
  */
 
 public class PAStatMap {
-    private final Map map = new HashMap<>();
+    private final Map map = new HashMap<>();
 
-    public void decStat(final StatisticsManager.type type) {
+    public void decStat(final StatisticsManager.Type type) {
         decStat(type, 1);
     }
 
-    public void decStat(final StatisticsManager.type type, final int value) {
+    public void decStat(final StatisticsManager.Type type, final int value) {
         map.put(type, getStat(type) - value);
     }
 
-    public int getStat(final StatisticsManager.type type) {
+    public int getStat(final StatisticsManager.Type type) {
         return map.containsKey(type) ? map.get(type) : 0;
     }
 
-    public void incStat(final StatisticsManager.type type) {
+    public void incStat(final StatisticsManager.Type type) {
         incStat(type, 1);
     }
 
-    public void incStat(final StatisticsManager.type type, final int value) {
+    public void incStat(final StatisticsManager.Type type, final int value) {
         map.put(type, getStat(type) + value);
     }
 
-    public void setStat(final StatisticsManager.type type, final int value) {
+    public void setStat(final StatisticsManager.Type type, final int value) {
         map.put(type, value);
     }
 }
diff --git a/src/net/slipcor/pvparena/commands/PAI_Stats.java b/src/net/slipcor/pvparena/commands/PAI_Stats.java
index f2e1eab77..862e25942 100644
--- a/src/net/slipcor/pvparena/commands/PAI_Stats.java
+++ b/src/net/slipcor/pvparena/commands/PAI_Stats.java
@@ -7,11 +7,13 @@
 import net.slipcor.pvparena.core.Language.MSG;
 import net.slipcor.pvparena.core.StringParser;
 import net.slipcor.pvparena.managers.StatisticsManager;
-import net.slipcor.pvparena.managers.StatisticsManager.type;
+import net.slipcor.pvparena.managers.StatisticsManager.Type;
 import org.bukkit.command.CommandSender;
 
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 
PVP Arena STATS Command class
@@ -38,23 +40,21 @@ public void commit(final Arena arena, final CommandSender sender, final String[] return; } - final type statType = type.getByString(args[0]); + final Type statType = Type.getByString(args[0]); if (statType == null) { - Arena.pmsg(sender, Language.parse(arena, MSG.STATS_TYPENOTFOUND, StringParser.joinArray(type.values(), ", ").replace("NULL, ", ""))); + Arena.pmsg(sender, Language.parse(arena, MSG.STATS_TYPENOTFOUND, StringParser.joinArray(Type.values(), ", ").replace("NULL, ", ""))); return; } - final String[] values = StatisticsManager.read(StatisticsManager.getStats(arena, statType), statType, arena == null); - final String[] names = StatisticsManager.read(StatisticsManager.getStats(arena, statType), type.NULL, arena == null); + Map playersStats = StatisticsManager.getStats(arena, statType); int max = 10; if (args.length > 1) { try { max = Integer.parseInt(args[1]); - } catch (final Exception e) { - max = 10; + } catch (NumberFormatException ignored) { } } @@ -65,9 +65,10 @@ public void commit(final Arena arena, final CommandSender sender, final String[] Arena.pmsg(sender, s1); - for (int i = 0; i < max && i < names.length && i < values.length; i++) { - Arena.pmsg(sender, names[i] + ": " + values[i]); - } + playersStats.entrySet().stream() + .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) + .limit(max) + .forEach(stat -> Arena.pmsg(sender, stat.getKey() + " : " + stat.getValue())); } @Override @@ -93,7 +94,7 @@ public List getShort() { @Override public CommandTree getSubs(final Arena arena) { final CommandTree result = new CommandTree<>(null); - for (final type val : type.values()) { + for (final Type val : Type.values()) { result.define(new String[]{val.name()}); } return result; diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index ce7753037..ab49dedc3 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -426,15 +426,15 @@ public enum MSG { STATS_HEAD("nulang.stats.head", "Statistics TOP %1% (%2%)"), STATS_TYPENOTFOUND("nulang.stats.typenotfound", "Statistics type not found! Valid values: &e%1%&r"), - STATTYPE_DAMAGE("nulang.stattype.DAMAGE", StatisticsManager.type.DAMAGE.getName()), - STATTYPE_DAMAGETAKE("nulang.stattype.DAMAGETAKE", StatisticsManager.type.DAMAGETAKE.getName()), - STATTYPE_DEATHS("nulang.stattype.DEATHS", StatisticsManager.type.DEATHS.getName()), - STATTYPE_KILLS("nulang.stattype.KILLS", StatisticsManager.type.KILLS.getName()), - STATTYPE_LOSSES("nulang.stattype.LOSSES", StatisticsManager.type.LOSSES.getName()), - STATTYPE_MAXDAMAGE("nulang.stattype.MAXDAMAGE", StatisticsManager.type.MAXDAMAGE.getName()), - STATTYPE_MAXDAMAGETAKE("nulang.stattype.MAXDAMAGETAKE", StatisticsManager.type.MAXDAMAGETAKE.getName()), - STATTYPE_NULL("nulang.stattype.NULL", StatisticsManager.type.NULL.getName()), - STATTYPE_WINS("nulang.stattype.WINS", StatisticsManager.type.WINS.getName()), + STATTYPE_DAMAGE("nulang.stattype.DAMAGE", StatisticsManager.Type.DAMAGE.getName()), + STATTYPE_DAMAGETAKE("nulang.stattype.DAMAGETAKE", StatisticsManager.Type.DAMAGETAKE.getName()), + STATTYPE_DEATHS("nulang.stattype.DEATHS", StatisticsManager.Type.DEATHS.getName()), + STATTYPE_KILLS("nulang.stattype.KILLS", StatisticsManager.Type.KILLS.getName()), + STATTYPE_LOSSES("nulang.stattype.LOSSES", StatisticsManager.Type.LOSSES.getName()), + STATTYPE_MAXDAMAGE("nulang.stattype.MAXDAMAGE", StatisticsManager.Type.MAXDAMAGE.getName()), + STATTYPE_MAXDAMAGETAKE("nulang.stattype.MAXDAMAGETAKE", StatisticsManager.Type.MAXDAMAGETAKE.getName()), + STATTYPE_NULL("nulang.stattype.NULL", StatisticsManager.Type.NULL.getName()), + STATTYPE_WINS("nulang.stattype.WINS", StatisticsManager.Type.WINS.getName()), TEAM_HAS_WON("nulang.team.haswon", "Team %1%&r are the Champions!"), TEAM_READY("nulang.team.ready", "Team %1%&r is ready!"), diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 1e5f0281b..77f6fb580 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -17,7 +17,7 @@ import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModuleManager; import net.slipcor.pvparena.managers.SpawnManager; -import net.slipcor.pvparena.managers.StatisticsManager.type; +import net.slipcor.pvparena.managers.StatisticsManager.Type; import net.slipcor.pvparena.managers.TeamManager; import net.slipcor.pvparena.runnables.EndRunnable; import org.bukkit.Bukkit; @@ -451,7 +451,7 @@ private void commit(final Arena arena, final String sTeam, final boolean win) { } for (final ArenaPlayer ap : team.getTeamMembers()) { - ap.addStatistic(arena.getName(), type.LOSSES, 1); + ap.addStatistic(arena.getName(), Type.LOSSES, 1); /* arena.tpPlayerToCoordName(ap.get(), "spectator"); ap.setTelePass(false);*/ diff --git a/src/net/slipcor/pvparena/goals/GoalSabotage.java b/src/net/slipcor/pvparena/goals/GoalSabotage.java index e4a5b5797..e9e891f42 100644 --- a/src/net/slipcor/pvparena/goals/GoalSabotage.java +++ b/src/net/slipcor/pvparena/goals/GoalSabotage.java @@ -17,7 +17,7 @@ import net.slipcor.pvparena.loadables.ArenaGoal; import net.slipcor.pvparena.loadables.ArenaModuleManager; import net.slipcor.pvparena.managers.SpawnManager; -import net.slipcor.pvparena.managers.StatisticsManager.type; +import net.slipcor.pvparena.managers.StatisticsManager.Type; import net.slipcor.pvparena.runnables.EndRunnable; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -254,7 +254,7 @@ private void commit(final Arena arena, final String sTeam) { } for (final ArenaPlayer ap : team.getTeamMembers()) { - ap.addStatistic(arena.getName(), type.LOSSES, 1); + ap.addStatistic(arena.getName(), Type.LOSSES, 1); /* arena.tpPlayerToCoordName(ap.get(), "spectator"); ap.setTelePass(false);*/ diff --git a/src/net/slipcor/pvparena/managers/StatisticsManager.java b/src/net/slipcor/pvparena/managers/StatisticsManager.java index bd26205db..60cfdd1be 100644 --- a/src/net/slipcor/pvparena/managers/StatisticsManager.java +++ b/src/net/slipcor/pvparena/managers/StatisticsManager.java @@ -11,14 +11,16 @@ import net.slipcor.pvparena.events.PAKillEvent; import org.bukkit.Bukkit; import org.bukkit.ChatColor; -import org.bukkit.OfflinePlayer; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import java.io.File; import java.io.IOException; -import java.util.UUID; +import java.util.Map; +import java.util.stream.Collectors; + +import static java.util.Comparator.reverseOrder; /** *
Statistics Manager class
@@ -31,12 +33,12 @@ public final class StatisticsManager { private static final Debug DEBUG = new Debug(28); - private static File players; + private static File playersFile; private static YamlConfiguration config; private StatisticsManager() {} - public enum type { + public enum Type { WINS("matches won", "Wins"), LOSSES("matches lost", "Losses"), KILLS("kills", "Kills"), @@ -50,9 +52,9 @@ public enum type { private final String fullName; private final String niceDesc; - type(final String name, final String desc) { - fullName = name; - niceDesc = desc; + Type(final String name, final String desc) { + this.fullName = name; + this.niceDesc = desc; } /** @@ -61,8 +63,8 @@ public enum type { * @param tType the type * @return the next type */ - public static type next(final type tType) { - final type[] types = type.values(); + public static Type next(final Type tType) { + final Type[] types = Type.values(); final int ord = tType.ordinal(); if (ord >= types.length - 2) { return types[0]; @@ -76,8 +78,8 @@ public static type next(final type tType) { * @param tType the type * @return the previous type */ - public static type last(final type tType) { - final type[] types = type.values(); + public static Type last(final Type tType) { + final Type[] types = Type.values(); final int ord = tType.ordinal(); if (ord <= 0) { return types[types.length - 2]; @@ -89,7 +91,7 @@ public static type last(final type tType) { * return the full stat name */ public String getName() { - return fullName; + return this.fullName; } /** @@ -98,8 +100,8 @@ public String getName() { * @param string the name to find * @return the type if found, null otherwise */ - public static type getByString(final String string) { - for (final type t : type.values()) { + public static Type getByString(final String string) { + for (final Type t : Type.values()) { if (t.name().equalsIgnoreCase(string)) { return t; } @@ -108,7 +110,7 @@ public static type getByString(final String string) { } public String getNiceName() { - return niceDesc; + return this.niceDesc; } } @@ -131,87 +133,63 @@ public static void damage(final Arena arena, final Entity entity, final Player d if (arena.hasPlayer(attacker)) { arena.getDebugger().i("attacker is in the arena, adding damage!", defender); final ArenaPlayer apAttacker = ArenaPlayer.parsePlayer(attacker.getName()); - final int maxdamage = apAttacker.getStatistics(arena).getStat(type.MAXDAMAGE); - apAttacker.getStatistics(arena).incStat(type.DAMAGE, (int) dmg); + final int maxdamage = apAttacker.getStatistics(arena).getStat(Type.MAXDAMAGE); + apAttacker.getStatistics(arena).incStat(Type.DAMAGE, (int) dmg); if (dmg > maxdamage) { - apAttacker.getStatistics(arena).setStat(type.MAXDAMAGE, (int) dmg); + apAttacker.getStatistics(arena).setStat(Type.MAXDAMAGE, (int) dmg); } } } final ArenaPlayer apDefender = ArenaPlayer.parsePlayer(defender.getName()); - final int maxdamage = apDefender.getStatistics(arena).getStat(type.MAXDAMAGETAKE); - apDefender.getStatistics(arena).incStat(type.DAMAGETAKE, (int) dmg); + final int maxdamage = apDefender.getStatistics(arena).getStat(Type.MAXDAMAGETAKE); + apDefender.getStatistics(arena).incStat(Type.DAMAGETAKE, (int) dmg); if (dmg > maxdamage) { - apDefender.getStatistics(arena).setStat(type.MAXDAMAGETAKE, (int) dmg); + apDefender.getStatistics(arena).setStat(Type.MAXDAMAGETAKE, (int) dmg); } } /** - * decide if a pair has to be sorted + * get an array of stats for arena boards and with a given stats type * - * @param aps the ArenaPlayer array - * @param pos the position to check - * @param sortBy the type to sort by - * @param desc descending order? - * @param global should we read global stats instead of arena stats? - * @return true if pair has to be sorted, false otherwise + * @param arena the arena to check + * @param statType the type to sort + * @return an array of stats values */ - private static boolean decide(final ArenaPlayer[] aps, final int pos, final type sortBy, - final boolean desc, final boolean global) { + public static String[] getStatsValuesForBoard(final Arena arena, final Type statType) { + DEBUG.i("getting stats values: " + (arena == null ? "global" : arena.getName()) + " sorted by " + statType); - int iThis = aps[pos].getStatistics(aps[pos].getArena()).getStat(sortBy); - int iNext = aps[pos + 1].getStatistics(aps[pos].getArena()).getStat(sortBy); - - if (global) { - iThis = aps[pos].getTotalStatistics(sortBy); - iNext = aps[pos + 1].getTotalStatistics(sortBy); + if (arena == null) { + return ArenaPlayer.getAllArenaPlayers().stream() + .map(ap -> (statType == Type.NULL) ? ap.getName() : String.valueOf(ap.getTotalStatistics(statType))) + .sorted(reverseOrder()) + .limit(8) + .toArray(String[]::new); } - return desc ? iThis < iNext : iThis > iNext; + return arena.getFighters().stream() + .map(ap -> (statType == Type.NULL) ? ap.getName() : String.valueOf(ap.getStatistics().getStat(statType))) + .sorted(reverseOrder()) + .limit(8) + .toArray(String[]::new); } /** - * get a set of arena players sorted by type - * - * @param arena the arena to check - * @param sortBy the type to sort - * @return an array of ArenaPlayer + * Get stats map for a given stat type + * @param arena the arena to check + * @param statType the kind of stat + * @return A map with player name and stat value */ - public static ArenaPlayer[] getStats(final Arena arena, final type sortBy) { - return getStats(arena, sortBy, true); - } - - /** - * get a set of arena players sorted by type - * - * @param arena the arena to check - * @param sortBy the type to sort - * @param desc should it be sorted descending? - * @return an array of ArenaPlayer - */ - private static ArenaPlayer[] getStats(final Arena arena, final type sortBy, final boolean desc) { - DEBUG.i("getting stats: " + (arena == null ? "global" : arena.getName()) + " sorted by " + sortBy + ' ' - + (desc ? "desc" : "asc")); - - final int count = arena == null ? ArenaPlayer.countPlayers() : arena.getFighters().size(); + public static Map getStats(final Arena arena, final Type statType) { + DEBUG.i("getting stats: " + (arena == null ? "global" : arena.getName()) + " sorted by " + statType); - final ArenaPlayer[] aps = new ArenaPlayer[count]; - - int pos = 0; if (arena == null) { - for (final ArenaPlayer p : ArenaPlayer.getAllArenaPlayers()) { - aps[pos++] = p; - } - } else { - for (final ArenaPlayer p : arena.getFighters()) { - aps[pos++] = p; - } + return ArenaPlayer.getAllArenaPlayers().stream() + .collect(Collectors.toMap(ArenaPlayer::getName, ap -> ap.getTotalStatistics(statType))); } - sortBy(aps, sortBy, desc, arena == null); - - return aps; + return arena.getFighters().stream() + .collect(Collectors.toMap(ArenaPlayer::getName, ap -> ap.getStatistics().getStat(statType))); } /** @@ -220,10 +198,10 @@ private static ArenaPlayer[] getStats(final Arena arena, final type sortBy, fina * @param line the line to determine the type * @return the Statistics type */ - public static type getTypeBySignLine(final String line) { + public static Type getTypeBySignLine(final String line) { final String stripped = ChatColor.stripColor(line).replace("[PA]", "").toUpperCase(); - for (final type t : type.values()) { + for (final Type t : Type.values()) { if (t.name().equals(stripped)) { return t; } @@ -231,7 +209,7 @@ public static type getTypeBySignLine(final String line) { return t; } } - return type.NULL; + return Type.NULL; } public static void initialize() { @@ -239,10 +217,10 @@ public static void initialize() { return; } config = new YamlConfiguration(); - players = new File(PVPArena.instance.getDataFolder(), "players.yml"); - if (!players.exists()) { + playersFile = new File(PVPArena.instance.getDataFolder(), "players.yml"); + if (!playersFile.exists()) { try { - players.createNewFile(); + playersFile.createNewFile(); Arena.pmsg(Bukkit.getConsoleSender(), Language.parse(MSG.STATS_FILE_DONE)); } catch (final Exception e) { Arena.pmsg(Bukkit.getConsoleSender(), Language.parse(MSG.ERROR_STATS_FILE)); @@ -251,7 +229,7 @@ public static void initialize() { } try { - config.load(players); + config.load(playersFile); } catch (final Exception e) { Arena.pmsg(Bukkit.getConsoleSender(), Language.parse(MSG.ERROR_STATS_FILE)); e.printStackTrace(); @@ -282,79 +260,17 @@ public static void kill(final Arena arena, final Entity entity, final Player def ArenaPlayer.parsePlayer(defender.getName()).addDeath(); } - /** - * gather all type information of an array of ArenaPlayers - * - * @param players the ArenaPlayer array to check - * @param tType the type to read - * @return an Array of String - */ - public static String[] read(final ArenaPlayer[] players, final type tType, final boolean global) { - final String[] result = new String[players.length < 8 ? 8 : players.length]; - int pos = 0; - if (global) { - for (final ArenaPlayer p : players) { - if (p == null) { - continue; - } - if (tType == type.NULL) { - result[pos++] = p.getName(); - } else { - result[pos++] = String.valueOf(p.getTotalStatistics(tType)); - } - } - } else { - for (final ArenaPlayer p : players) { - if (tType == type.NULL) { - result[pos++] = p.getName(); - } else { - result[pos++] = String.valueOf(p.getStatistics(p.getArena()).getStat(tType)); - } - } - } - while (pos < 8) { - result[pos++] = ""; - } - return result; - } - public static void save() { if (config == null) { return; } try { - config.save(players); + config.save(playersFile); } catch (final IOException e) { e.printStackTrace(); } } - /** - * bubble sort an ArenaPlayer array by type - * - * @param aps the ArenaPlayer array - * @param sortBy the type to sort by - * @param desc descending order? - * @param global announce to the whole server? - */ - private static void sortBy(final ArenaPlayer[] aps, final type sortBy, final boolean desc, final boolean global) { - int pos = aps.length; - boolean doMore = true; - while (doMore) { - pos--; - doMore = false; // assume this is our last pass over the array - for (int i = 0; i < pos; i++) { - if (decide(aps, i, sortBy, desc, global)) { - // exchange elements - final ArenaPlayer temp = aps[i]; - aps[i] = aps[i + 1]; - aps[i + 1] = temp; - doMore = true; // after an exchange, must look again - } - } - } - } - public static void loadStatistics(final Arena arena) { if (!PVPArena.instance.getConfig().getBoolean("stats")) { return; @@ -371,65 +287,55 @@ public static void loadStatistics(final Arena arena) { for (final String playerID : config.getConfigurationSection(arena.getName()).getKeys(false)) { - String player = playerID; - - if (config.getConfigurationSection(arena.getName()).contains(playerID+".playerName")) { - // old broken version - final OfflinePlayer oPlayer; - try { - oPlayer = Bukkit.getOfflinePlayer(UUID.fromString(playerID)); - } catch (final NoSuchMethodError error) { - continue; - } - - player = oPlayer.getName(); - config.getConfigurationSection(arena.getName()).set(playerID+".name", player); - config.getConfigurationSection(arena.getName()).set(playerID+".playerName", null); + String playerName = null; - foundBroken = true; - } else if (config.getConfigurationSection(arena.getName()).contains(playerID+".name")) { - // new version - player = config.getConfigurationSection(arena.getName()).getString(playerID+".name"); + if (config.getConfigurationSection(arena.getName()).contains(playerID+".name")) { + playerName = config.getConfigurationSection(arena.getName()).getString(playerID+".name"); } - arena.getDebugger().i("loading stats: " + player); + arena.getDebugger().i("loading stats: " + playerName); final ArenaPlayer aPlayer; try { - aPlayer = ArenaPlayer.parsePlayer(player); + if(playerName != null) { + aPlayer = ArenaPlayer.addPlayer(playerName); + } else { + continue; + } + } catch (IllegalArgumentException e) { PVPArena.instance.getLogger().warning("invalid player ID: " + playerID); continue; } - for (final type ttt : type.values()) { + for (final Type ttt : Type.values()) { aPlayer.setStatistic(arena.getName(), ttt, 0); } final int losses = config.getInt(arena.getName() + '.' + playerID + ".losses", 0); - aPlayer.addStatistic(arena.getName(), type.LOSSES, losses); + aPlayer.addStatistic(arena.getName(), Type.LOSSES, losses); final int wins = config.getInt(arena.getName() + '.' + playerID + ".wins", 0); - aPlayer.addStatistic(arena.getName(), type.WINS, wins); + aPlayer.addStatistic(arena.getName(), Type.WINS, wins); final int kills = config.getInt(arena.getName() + '.' + playerID + ".kills", 0); - aPlayer.addStatistic(arena.getName(), type.KILLS, kills); + aPlayer.addStatistic(arena.getName(), Type.KILLS, kills); final int deaths = config.getInt(arena.getName() + '.' + playerID + ".deaths", 0); - aPlayer.addStatistic(arena.getName(), type.DEATHS, deaths); + aPlayer.addStatistic(arena.getName(), Type.DEATHS, deaths); final int damage = config.getInt(arena.getName() + '.' + playerID + ".damage", 0); - aPlayer.addStatistic(arena.getName(), type.DAMAGE, damage); + aPlayer.addStatistic(arena.getName(), Type.DAMAGE, damage); final int maxdamage = config.getInt(arena.getName() + '.' + playerID + ".maxdamage", 0); - aPlayer.addStatistic(arena.getName(), type.MAXDAMAGE, maxdamage); + aPlayer.addStatistic(arena.getName(), Type.MAXDAMAGE, maxdamage); final int damagetake = config.getInt(arena.getName() + '.' + playerID + ".damagetake", 0); - aPlayer.addStatistic(arena.getName(), type.DAMAGETAKE, damagetake); + aPlayer.addStatistic(arena.getName(), Type.DAMAGETAKE, damagetake); final int maxdamagetake = config.getInt(arena.getName() + '.' + playerID + ".maxdamagetake", 0); - aPlayer.addStatistic(arena.getName(), type.MAXDAMAGETAKE, maxdamagetake); + aPlayer.addStatistic(arena.getName(), Type.MAXDAMAGETAKE, maxdamagetake); } if (foundBroken) { save(); @@ -447,32 +353,32 @@ public static void update(final Arena arena, final ArenaPlayer aPlayer) { try { node = aPlayer.get().getUniqueId().toString(); - } catch (final Exception e) { + } catch (final Exception ignored) { } - final int losses = map.getStat(type.LOSSES); + final int losses = map.getStat(Type.LOSSES); config.set(arena.getName() + '.' + node + ".losses", losses); - final int wins = map.getStat(type.WINS); + final int wins = map.getStat(Type.WINS); config.set(arena.getName() + '.' + node + ".wins", wins); - final int kills = map.getStat(type.KILLS); + final int kills = map.getStat(Type.KILLS); config.set(arena.getName() + '.' + node + ".kills", kills); - final int deaths = map.getStat(type.DEATHS); + final int deaths = map.getStat(Type.DEATHS); config.set(arena.getName() + '.' + node + ".deaths", deaths); - final int damage = map.getStat(type.DAMAGE); + final int damage = map.getStat(Type.DAMAGE); config.set(arena.getName() + '.' + node + ".damage", damage); - final int maxdamage = map.getStat(type.MAXDAMAGE); + final int maxdamage = map.getStat(Type.MAXDAMAGE); config.set(arena.getName() + '.' + node + ".maxdamage", maxdamage); - final int damagetake = map.getStat(type.DAMAGETAKE); + final int damagetake = map.getStat(Type.DAMAGETAKE); config.set(arena.getName() + '.' + node + ".damagetake", damagetake); - final int maxdamagetake = map.getStat(type.MAXDAMAGETAKE); + final int maxdamagetake = map.getStat(Type.MAXDAMAGETAKE); config.set(arena.getName() + '.' + node + ".maxdamagetake", maxdamagetake); if (!node.equals(aPlayer.getName())) { From 262614a7a4aa71b8189f892af9f5cbc53eff6135 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 23 Jun 2020 17:37:52 +0200 Subject: [PATCH 062/115] v1.15 - fix missing death causes --- lang/lang_en.yml | 4 ++++ lang/lang_fr.yml | 4 ++++ src/net/slipcor/pvparena/arena/Arena.java | 4 ++-- src/net/slipcor/pvparena/core/Language.java | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lang/lang_en.yml b/lang/lang_en.yml index 86a69781b..d0ed6ace4 100644 --- a/lang/lang_en.yml +++ b/lang/lang_en.yml @@ -66,6 +66,10 @@ nulang: SUICIDE: self THORNS: thorns VOID: the Void + FALLING_BLOCK: a falling block + HOT_FLOOR: a magma block + CRAMMING: a collision surplus + DRAGON_BREATH: dragon breath CREEPER: a creeper SKELETON: a skeleton SPIDER: a spider diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml index c4c4c7990..8a2e93178 100644 --- a/lang/lang_fr.yml +++ b/lang/lang_fr.yml @@ -70,6 +70,10 @@ nulang: SUICIDE: lui-même THORNS: thorns VOID: le vide + FALLING_BLOCK: une chute de bloc + HOT_FLOOR: un bloc de magma + CRAMMING: un surplus de collisions + DRAGON_BREATH: le souffle d'un dragon CREEPER: un creeper SKELETON: un squelette SPIDER: une araignée diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index 6fcac2249..2cce050da 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -865,6 +865,7 @@ public String parseDeathCause(final Player player, final DamageCause cause, switch (cause) { case ENTITY_ATTACK: + case ENTITY_SWEEP_ATTACK: if (damager instanceof Player && team != null) { return team.colorizePlayer(aPlayer.get()) + ChatColor.YELLOW; } @@ -917,8 +918,7 @@ public String parseDeathCause(final Player player, final DamageCause cause, default: break; } - MSG string = MSG.getByName("DEATHCAUSE_" - + cause.toString()); + MSG string = MSG.getByName("DEATHCAUSE_" + cause.toString()); if (string == null) { PVPArena.instance.getLogger().warning("Unknown cause: " + cause.toString()); string = MSG.DEATHCAUSE_VOID; diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index ab49dedc3..d8c4bb6c8 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -86,6 +86,10 @@ public enum MSG { DEATHCAUSE_SUICIDE("nulang.deathcause.SUICIDE", "self"), DEATHCAUSE_THORNS("nulang.deathcause.THORNS", "thorns"), DEATHCAUSE_VOID("nulang.deathcause.VOID", "the Void"), + DEATHCAUSE_FALLING_BLOCK("nulang.deathcause.FALLING_BLOCK", "a falling block"), + DEATHCAUSE_HOT_FLOOR("nulang.deathcause.HOT_FLOOR", "a magma block"), + DEATHCAUSE_CRAMMING("nulang.deathcause.CRAMMING", "a collision surplus"), + DEATHCAUSE_DRAGON_BREATH("nulang.deathcause.DRAGON_BREATH", "dragon breath"), DEATHCAUSE_CREEPER("nulang.deathcause.CREEPER", "a creeper"), DEATHCAUSE_SKELETON("nulang.deathcause.SKELETON", "a skeleton"), From 7a24841c7282083878e7435a585f2a867e45cf93 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 23 Jun 2020 18:49:13 +0200 Subject: [PATCH 063/115] v1.15 - clear unused translations and configs, and improve french translation --- lang/lang_en.yml | 9 - lang/lang_es-es.yml | 9 - lang/lang_fr.yml | 268 +++++++++----------- src/net/slipcor/pvparena/core/Config.java | 15 -- src/net/slipcor/pvparena/core/Language.java | 21 -- 5 files changed, 121 insertions(+), 201 deletions(-) diff --git a/lang/lang_en.yml b/lang/lang_en.yml index d0ed6ace4..5adb41b8a 100644 --- a/lang/lang_en.yml +++ b/lang/lang_en.yml @@ -322,15 +322,6 @@ nulang: claimed: '[%1%] %2% claimed the pillar!' unclaimed: '[%1%] %2% unclaimed the pillar!' score: '%1% scored %2% points' - rescue: - flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: - %3%' - flagsave: '%1% dropped the hostage of team %2%!' - flaggrab: '%1% grabbed the hostage of team %2%!' - flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' - setflag: 'Rescue set: %1%' - tosetflag: 'Rescue to set: %1%' - typeset: 'Hostage type set to: &e%1%' help: head: '&e--- &aPVP Arena Help&e %1% &e---' admin: '&c%1% - help administrating' diff --git a/lang/lang_es-es.yml b/lang/lang_es-es.yml index 178366bfa..a0cc90fd8 100644 --- a/lang/lang_es-es.yml +++ b/lang/lang_es-es.yml @@ -268,15 +268,6 @@ nulang: claimed: ¡[%1%] %2% ha tomado el pilar! unclaimed: ¡[%1%] %2% esta siendo tomado! score: '%1% hizo %2% punto/s' - rescue: - flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: - %3%' - flagsave: '%1% dropped the hostage of team %2%!' - flaggrab: '%1% grabbed the hostage of team %2%!' - flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' - setflag: 'Rescue set: %1%' - tosetflag: 'Rescue to set: %1%' - typeset: 'Hostage type set to: &e%1%' help: head: '&e--- &aAyuda de PVP Arena&e %1% &e---' admin: '&c%1% - Ayuda de Administración' diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml index 8a2e93178..6c65dc79f 100644 --- a/lang/lang_fr.yml +++ b/lang/lang_fr.yml @@ -17,8 +17,8 @@ nulang: remove: done: L'arène &e%1%&r vient d'être supprimée setup: - disabled: 'Disabled setup mode for arena: %1%' - enabled: 'Enabled setup mode for arena: %1%' + disabled: 'Désactivation du mode configuration pour l''arène : %1%' + enabled: 'Désactivation du mode configuration pour l''arène : %1%' startingin: Il y a assez de joueurs prêts. Le combat commence dans %1% ! start: done: Combat démarré manuellement ! @@ -36,21 +36,21 @@ nulang: added: Vous avez ajouté &a%1%&r à la liste noire de &e%2%&r ! allcleared: Toutes les listes noires ont été effacées ! cleared: La liste noire &e%1%&r a été effacée ! - help: 'Utilisation: blacklist clear | blacklist [type] [clear|add|remove] [id]' + help: 'Aide : blacklist clear | blacklist [type] [clear|add|remove] [id]' removed: Vous avez supprimé &a%1%&r de la liste noire &e%2%&r ! show: 'Liste noire &e%1%&r :' check: done: Verification faite ! Aucune erreur! class: - list: 'Available classes: %1%' + list: 'Classes disponibles : %1%' preview: Vous avez un aperçu de la classe %1% removed: La classe %1% a été supprimée saved: La classe %1% a été sauvegardée selected: Vous avez choisi la classe &e%1%&e - selectedrespawn: You will switch to the &e%1%&f class on next respawn. + selectedrespawn: Vous réapparaitrez avec la classe &e%1%&f au prochain respawn. classchest: - done: Successfully set the class items of %1% to the contents of %2%. Please reload - the arena when you are done setting chests! + done: Les items de la classe %1% proviendront dorénavant du contenu du coffre %2%. Veuillez recharger + la configuration de l'arène lorsque vous aurez fini de remplir le coffre en question. deathcause: BLOCK_EXPLOSION: une explosion CONTACT: un cactus @@ -173,10 +173,9 @@ nulang: region: beingcreated: 'Une région a déja été créée: %1%' flagnotfound: 'RegionFlag &a%1%&r inconnu! Valeurs valides: %2%' - invalid: Region selection is invalid. Region will have no volume and will be - useless! + invalid: La sélection de la région est incorrecte. Celle-ci est vide et sera par conséquent inutile. notfound: Region &a%1%&r non trouvée ! - protectionnotfound: RegionProtection &a%1%&r non trouvée ! + protectionnotfound: Protection de région &a%1%&r non trouvée ! typenotfound: 'RegionType &a%1%&r inconnu ! Valeurs valides: %2%' youselect: Vous avez déjà sélectionné une région pour l'arène ! youselect2: Retapez la commande pour annuler la sélection ! @@ -184,15 +183,15 @@ nulang: regionnotbeingcreated: Aucune région n'est en cours de création ! regionnotremoved: Il n'y a pas de configuration de région. select2: Selectionnez 2 points avant de vouloir les sauvegarder. - setupmode: setup mode! + setupmode: Mode de configuration ! spawn: unknown: 'Spawn inconnu: &a%1%&r' - spawnfree: Erreur ! Arena est de type free. Utilisez 'spawnX' où X est un chiffre + spawnfree: Erreur ! Arena est de type free (ffa). Utilisez 'spawnX' où X est un chiffre ou une lettre ! statsfile: Erreur lors de la lecture du fichier stats ! teamnotfound: 'Equipe non trouvée: &a%1%&r' - uninstall: Erreur lors de la désinstallation &a%1%&r - uninstall2: PVP Arena will try to uninstall on server restart! + uninstall: Erreur lors de la désinstallation de &a%1%&r + uninstall2: PVP Arena tentera une déinstallation au redémarrage du serveur. unknownmodule: 'Module non trouvé: %1%' whitelist: disallowed: Vous ne devriez pas %1% ça ! (non whitelisté) @@ -212,54 +211,54 @@ nulang: teleport: téléporter au spawn d'une arène user: utiliser l'arène cmds: - blacklist: use the blacklist command - check: use the check command - class: use the class command - create: use the create command - debug: use the debug command - disable: use the disable command - duty: use the duty command - edit: use the edit command - enable: use the enable command - gamemode: use the gamemode command - goal: use the goal command - install: use the install command - playerclass: use the playerclass command - playerjoin: use the playerjoin command - protection: use the protection command - region: use the region command - regionflag: use the regionflag command - regions: use the regions command - regiontype: use the regiontype command - reload: use the reload command - remove: use the remove command - round: use the round command - set: use the set command - setowner: use the setowner command - setup: use the setup command - spawn: use the spawn command - start: use the start command - stop: use the stop command - teams: use the teams command - teleport: use the teleport command - template: use the template command - togglemod: use the togglemod command - uninstall: use the uninstall command - update: use the update command - whitelist: use the whitelist command - arenaclass: use the arenaclass command - chat: use the chat command - join: use the join command - leave: use the leave command - spectate: use the spectate command - arenalist: use the arenalist command - help: use the help command - info: use the info command - list: use the list command - ready: use the ready command - shutup: use the shutup command - stats: use the stats command - version: use the version command + blacklist: d'utiliser la commande blacklist + check: d'utiliser la commande check + class: d'utiliser la commande class + create: d'utiliser la commande create + debug: d'utiliser la commande debug + disable: d'utiliser la commande disable + duty: d'utiliser la commande duty + edit: d'utiliser la commande edit + enable: d'utiliser la commande enable + gamemode: d'utiliser la commande gamemode + goal: d'utiliser la commande goal + install: d'utiliser la commande install + playerclass: d'utiliser la commande playerclass + playerjoin: d'utiliser la commande playerjoin + protection: d'utiliser la commande protection + region: d'utiliser la commande region + regionflag: d'utiliser la commande regionflag + regions: d'utiliser la commande regions + regiontype: d'utiliser la commande regiontype + reload: d'utiliser la commande reload + remove: d'utiliser la commande remove + round: d'utiliser la commande round + set: d'utiliser la commande set + setowner: d'utiliser la commande setowner + setup: d'utiliser la commande setup + spawn: d'utiliser la commande spawn + start: d'utiliser la commande start + stop: d'utiliser la commande stop + teams: d'utiliser la commande teams + teleport: d'utiliser la commande teleport + template: d'utiliser la commande template + togglemod: d'utiliser la commande togglemod + uninstall: d'utiliser la commande uninstall + update: d'utiliser la commande update + whitelist: d'utiliser la commande whitelist + arenaclass: d'utiliser la commande arenaclass + chat: d'utiliser la commande chat + join: d'utiliser la commande join + leave: d'utiliser la commande leave + spectate: d'utiliser la commande spectate + arenalist: d'utiliser la commande arenalist + help: d'utiliser la commande help + info: d'utiliser la commande info + list: d'utiliser la commande list + ready: d'utiliser la commande ready + shutup: d'utiliser la commande shutup + stats: d'utiliser la commande stats + version: d'utiliser la commande version fight: begins: Que le combat commence ! draw: Match nul ! Egalité ! @@ -283,19 +282,6 @@ nulang: added: 'Objectif ajouté: &a%1%&r' installing: 'Installez des objectifs avec la commande: &a/pa install [goalname]&r' removed: 'Objectif supprimé: &a%1%&r' - beacons: - claiming: '&eTeam %1% is claiming the beacon!' - claimed: '&eTeam %1% has claimed the beacon!' - claimed_remaining: '&eTeam %1% has claimed the beacon! %2% claims remaining!' - score: '&eTeam %1% scored %2% points by holding the beacon!' - changed: '&eA new beacon has been activated!' - contesting: '&eThe beacon claimed by team %1% is being contested!' - unclaiming: '&eThe beacon claimed by team %1% is being unclaimed!' - unclaimingby: '&eThe beacon claimed by team %1% is being unclaimed by team %2%!' - set: 'Beacon set: %1%' - setdone: Beacon setting mode deactivated. - toset: Beacon setting mode activated. Hit the glass blocks, then use the command - again to save! blockdestroy: typeset: 'Blocktype configuré en: &e%1%' setflag: 'Bloc configuré: %1%' @@ -338,14 +324,14 @@ nulang: youtnt: Vous portez maintenant le matériel de sabotage !' tank: tankdown: Le tank est H.S. ! - tankmode: TANK MODE ! Tous le monde doit tuer %1%, le tank ! + tankmode: MODE TANK ! Tous le monde doit tuer %1%, le tank ! tankwon: Le tank a gagné ! Félicitations à %1% ! tdc: - denied: '%1% denied a kill!' - remaining: '%1% kills remaining for %2%.' - scored: '%1% scored a kill!' - youdenied: You denied a kill! - youscored: You scored a kill! + denied: '%1% a refusé un kill!' + remaining: '%1% kills restants pour %2%.' + scored: '%1% a enregistré un kill!' + youdenied: Vous avez refusé un kill ! + youscored: Vous avez enregistré un kill ! pillars: msg: block_broken: '[%1%] %2% a cassé un bloc !' @@ -355,15 +341,6 @@ nulang: claimed: '[%1%] %2% a réclamé la colonne !' unclaimed: '[%1%] %2% a libéré la colonne !' score: '%1% a marqué %2% points' - rescue: - flaghomeleft: '%1% brought home the hostage of team %2%! Rescues remaining: - %3%' - flagsave: '%1% dropped the hostage of team %2%!' - flaggrab: '%1% grabbed the hostage of team %2%!' - flagnotsafe: Your hostage is taken! Cannot bring back an enemy hostage!' - setflag: 'Rescue set: %1%' - tosetflag: 'Rescue to set: %1%' - typeset: 'Hostage type set to: &e%1%' help: head: '&e--- &aAide de PVP Arena&e %1% &e---' admin: '&c%1% - aide administration' @@ -404,8 +381,7 @@ nulang: trickerdisabled: Suivi du plugin désactivé. Rendez-vous bientôt ? trackingenabled: 'Suivi du plugin activé. Configurer le suivi: false dans la configuration pricipale à désactiver.' - updatedisabled: Mises à jour désactivée. Veuillez vérifier dev.bukkit pour les - mises à jour. + updatedisabled: Mises à jour désactivée. Pensez à vérifier spigot.org pour les mises à jour. updateenabled: Recherche de mise à jour... warning: '%1%' messages: @@ -438,13 +414,13 @@ nulang: playerready: '%1%&e est prêt !' player: prevented: - break: '&cYou may not break blocks!' - place: '&cYou may not place blocks!' - tnt: '&cYou may not use TNT!' - tntbreak: '&cYou may not break TNT!' - drop: '&cYou may not drop items!' - inventory: '&cYou may not access this!' - craft: '&cYou may not craft!' + break: '&cVous n''êtes pas autorisé à casser des blocs !' + place: '&cVous n''êtes pas autorisé à poser des blocs !' + tnt: '&cVous n''êtes pas autorisé à utiliser de la TNT !' + tntbreak: '&cVous n''êtes pas autorisé à casser de la TNT !' + drop: '&cVous n''êtes pas autorisé jeter vos items !' + inventory: '&cVous n''êtes pas autorisé à accéder à cela !' + craft: '&cVous n''êtes pas autorisé à crafter !' notreadyplayers: Les joueurs ne sont pas prêts players: Joueurs ready: @@ -452,9 +428,9 @@ nulang: done: Tu viens d'être enregistré comme prêt ! region: clear: - added: 'Added to region entity clearing whitelist: &a%1%&r' - list: 'Region entity clearing whitelist: &a%1%&r' - removed: 'Removed from region entity clearing whitelist: &a%1%&r' + added: 'Région ajoutée à la whitelist de nettoyage des entités: &a%1%&r' + list: 'Liste des régions appartenant à la whitelist de nettoyage des entités: &a%1%&r' + removed: 'Région retirée de la whitelist de nettoyage des entités: &a%1%&r' flag: added: 'Flag ajouté: &a%1%&r' removed: 'Flag suppimé: &a%1%&r' @@ -466,15 +442,15 @@ nulang: radius: 'Rayon de la région: &a%1%&r' removed: 'Region supprimée: %1%' saved: Region enregistrée. - saved_notice: '&6You created a &oCUSTOM&6 region. It has no function yet! To turn - it into a battlefield region, type &r/pvparena %1% !rt %2% BATTLE' + saved_notice: '&6Vous avez créé une région &oCUSTOM&6. Celle-ci n''a aucune fonction. Pour créer une région + pour combattre, tapez &r/pvparena %1% !rt %2% BATTLE' select: Selectionne deux points avec le wand item, clic gauche pour le prmier et clic droit pour le second ! setting: Paramètrage de région activé. - typeset: 'Region Type modifié en: &e%1%' + typeset: 'Type de région modifié en: &e%1%' youselect: Vous séléctionnez maintenant une région pour &a%1%&r! regions: - flags: 'Region Flags: &a%1%&r' + flags: 'Flags de région: &a%1%&r' head: '--- &aRégion de l''arène&r [&e%1%&r]---' listhead: '--- &aRégions de l''arène&r [&e%1%&r]---' listvalue: '&a%1%&r: %2%, %3%' @@ -483,15 +459,15 @@ nulang: type: 'Type de région: &a%1%&r' reloaded: Config actualisée! ymls: - reloaded: Languages reloaded! + reloaded: Fichiers de langue rechargés ! round: - display: 'Rond #%1%: %2%' - added: 'Objectif ajouté au rond: &e%1%' - removed: 'Objectif supprimé au rond: &e%1%' + display: 'Round #%1%: %2%' + added: 'Objectif ajouté au round: &e%1%' + removed: 'Objectif supprimé du round: &e%1%' roundsdisplay: Round %1% / %2% roundsdisplayseparator: '-----------' set: - items_not: Please use either hand or inventory to set an item node! + items_not: Veuillez utiliser les mots clés "hand" ou "inventory" pour définir un item dans la configuration. done: '&a%1%&r configuré à &e%2%&r!' help: utilise /pa {arenaname} set [page] pour obtenir la liste des configurations unknown: 'Config inconnue: &e%1%&r!' @@ -506,10 +482,10 @@ nulang: set: 'Spawn configuré: &a%1%&r' setdone: 'Paramètrage du spawn terminé: &a%1%&r' setstart: 'Paramètrage du spawn: &a%1%&r' - unknown: 'Spawn not found: &a%1%&r' + unknown: 'Spawn inconnu : &a%1%&r' stats: filedone: Fichier stats chargé ! - head: Statistics TOP %1% (%2%) + head: Statistiques TOP %1% (%2%) typenotfound: 'Type de statistique non trouvé! Valeurs correctes: &e%1%&r' stattype: DAMAGE: dommages totaux accordé @@ -544,8 +520,8 @@ nulang: pvpactivating: Le PVP sera activé dans %1%! walls: Les murs disparaitront dans %1%! togglemod: - notice: '&cYou activated a module that requires a BATTLE region! Type &r/pvparena - [arena] !rt [region] BATTLE' + notice: '&cVous venez d''activer un module nécessitant une région de type BATTLE ! Pour changer le type de région + Tapez &r/pvparena [arena] !rt [region] BATTLE' uninstall: done: 'supprimé: &a%1%&r' whitelist: @@ -559,7 +535,7 @@ nulang: aftermatch: aftermatch: L'aprèsmatch a commencé ! startingin: AprèsMatch dans %1%! - spawnnotset: Spawn 'après' non configuré ! + spawnnotset: Spawn 'after' non configuré ! announcements: ignoreon: Vous ignorez maintenant les annonces ! ignoreoff: Vous recevrez maintenant les annonces ! @@ -576,21 +552,20 @@ nulang: duel: accepted: '%1% &ea accepté le challenge ! Que le jeu commence !' announce: '%1% &evous a defié! Accepte le duel avec &f/pa %2% accept.' - announcemoney: '&eThey set up a fee of &c%1%&e!' - announce2: '&eCancel the duel with &r/pa %2% decline&e.' - cancelled: '&cThe duel has been cancelled!' - busy: '%1% &eis already in a fight Please try again later.' - declineds: Your opponent did decline. The duel has been cancelled. - declinedr: You cancelled the duel! - requested: You &echallenged &f%1%&e! - requestedalready: You already have challenged someone! - requestexpireds: Your opponent did not accept the request in time. The duel - has been cancelled. - requestexpiredr: You did not accept the request in time. The duel has been cancelled. + announcemoney: '&eLe prix d''entrée est de &c%1%&e!' + announce2: '&eRefusez le duel avec &r/pa %2% decline&e.' + cancelled: '&cLe duel a été annulé!' + busy: '%1% &ecombat actuellement. Veuillez réessayer plus tard.' + declineds: Votre opposant a refusé. Le duel est annulé. + declinedr: Vous avez refusé le duel ! + requested: Vous &eavez défié &f%1%&e! + requestedalready: Vous avez déjà défié quelqu'un ! + requestexpireds: Votre opposant n'a pas accepté le duel a temps. Le duel est donc annulé. + requestexpiredr: Vous n'avez pas accepté le duel a temps. Le duel est donc annulé. starting: Le duel commence ! - nodirectjoin: 'You may not join this arena directly! Use: &e/pa %1% duel [playername]' + nodirectjoin: 'Vous pouvez rejoindre directement le combat ! Utilisez: &e/pa %1% duel [nomDuJoueur]' fixinventorylos: - gamemode: Entrez en mode survie avant de rejoindre l'arène ! + gamemode: Passez en mode survie avant de rejoindre l'arène ! invenory: Videz votre inventaire avant de rejoindre l'arène ! latelounge: llannounce: L'arène %1% est ouverte ! Le joueur %2% veut commencer. Rejoint @@ -602,13 +577,13 @@ nulang: llleave: Vous venez de quitter la file d'attente de l'arène %1%. playerfinder: near: 'Joueur le plus proche: %1% blocs!' - point: La boussole pointe sur le joueur le plus proche ! + point: La boussole indique le joueur le plus proche ! powerups: invalidpowerupeffect: 'PowerupEffect invalide: %1%' puplayer: '%1% a collecté le PowerUp %2%!' puserver: PowerUp déployé! respawnrelay: - respawning: Respawning in %1%! + respawning: Réapparition dans %1%! skins: dc: Connecté à DisguiseCraft ! ld: Hooking into LibsDisguises! @@ -658,18 +633,18 @@ nulang: killreward: Vous recevez %1% pour avoir tué %2%! refunding: Remboursement %1%! walls: - fallingin: 'Walls fall in: %1%' + fallingin: 'Les murs tomberont dans : %1%' separator: '--------------------' worldedit: - created: 'Region créée: &e%1%' - list_added: Region &e%1%&f will now be specifically saved. - list_removed: Region &e%1%&f will no longer be specifically saved. - list_show: 'These regions will be saved specifically: &e%1%&f' + created: 'Région créée: &e%1%' + list_added: La région &e%1%&f sera maintenant spécifiquement sauvegardée. + list_removed: Region &e%1%&f ne sera plus spécifiquement sauvegardée. + list_show: 'Ces régions sont spécifiquement sauvegardées : &e%1%&f' loaded: 'Region chargée: &e%1%' saved: 'Region sauvegardée: &e%1%' worldguard: - created: 'Region not found: &e%1%' - saved: Region &e%2%&f saved to &e%1% + created: 'Region non trouvée : &e%1%' + saved: La région &e%2%&f a été enregistrée sous &e%1% banvote: lang: playerbanned: 'Joueur banni: %1%' @@ -685,22 +660,21 @@ nulang: clear: Classe &e%1%&r effacée ! listhead: '--- Effets de potion pour la classe &e%1%&r ---' remove: L'effet de potion &e%2%&r a été supprimé de la classe &e%1%&r! - respawncommand_remove: Respawn command removed from ArenaClass &e%1%&r! + respawncommand_remove: La commande de respawn a été supprimée de la classe &e%1%&r! classchange: - mteam: '&cYour team has exceeded the class change limit!' - mplayer: '&cYou have exceeded the class change limit!' + mteam: '&cVotre équipe a dépassé le quota de changement de classe !' + mplayer: '&cVous avez dépassé le quota de changement de classe !' bettergears: classdone: La classe &e%1%&r a dorénavant une protection de niveau &a%2% showclass: La classe &e%1%&r a une protection de niveau &a%2% showteam: L'équipe %1% a la couleur %2% teamdone: L'équipe %1% a maintenant la couleur %2% blockrestore: - clearinvdone: Inventaires effacés ! Attendez-vous à des lag au début du prochain - combat ! + clearinvdone: Inventaires (coffres) effacés ! Attendez-vous à des lag au début du prochain combat ! chestfiller: - chest: Successfully set the items to the contents of %1%. - clear: Inventories cleared! - fillchest: 'Added to the list to be filled: %1%.' + chest: Le contenu du coffre %1% a été défini avec succès. + clear: Les contenu des coffres ont été effacés ! + fillchest: 'Ajouté à la liste des coffres devant être remplis : %1%.' announce: arena: L'arène est ouverte ! Tape /pa %1% pour rejoindre le combat ! lang: @@ -727,7 +701,7 @@ lang: votenow: |- Votez votre arène! %1% left! Votez avec /pa [arenaname] vote - Available arenas: %2% + Arènes disponibles : %2% log: tagapi: connecté à TagAPI! version: 0.9.0.0 diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index a67865933..51e29ea01 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -184,16 +184,6 @@ public enum CFG { USES_WOOLHEAD("uses.woolHead", false, null), // ---------- - - GOAL_BEACONS_ANNOUNCEOFFSET("goal.beacons.spamoffset", 3, "Beacons"), - GOAL_BEACONS_BOSSBAR("goal.beacons.beacBossBar", true, "Beacons"), - GOAL_BEACONS_CHANGESECONDS("goal.beacons.changeseconds", 30, "Beacons"), - GOAL_BEACONS_CHANGEONCLAIM("goal.beacons.changeonclaim", false, "Beacons"), - GOAL_BEACONS_CLAIMRANGE("goal.beacons.claimrange", 3, "Beacons"), - GOAL_BEACONS_LIVES("goal.beacons.blives", 10, "Beacons"), - GOAL_BEACONS_TICKINTERVAL("goal.beacons.tickinterval", 60, "Beacons"), - GOAL_BEACONS_TICKREWARD("goal.beacons.tickreward", 1, "Beacons"), - GOAL_BLOCKDESTROY_BLOCKTYPE("goal.blockdestroy.blocktype", Material.IRON_BLOCK, "BlockDestroy"), GOAL_BLOCKDESTROY_LIVES("goal.blockdestroy.bdlives", 1, "BlockDestroy"), @@ -264,11 +254,6 @@ public enum CFG { GOAL_PLAYERKILLREWARD_GRADUALLYDOWN("goal.playerkillreward.graduallyDown", false, "PlayerKillReward"), GOAL_PLAYERKILLREWARD_ONLYGIVE("goal.playerkillreward.onlyGive", false, "PlayerKillReward"), - GOAL_RESCUE_RESCUETYPE("goal.rescue.flagType", "VILLAGER", "Rescue"), - GOAL_RESCUE_LIVES("goal.rescue.rlives", 1, "Rescue"), - GOAL_RESCUE_MUSTBESAFE("goal.rescue.mustBeSafe", true, "Rescue"), - GOAL_RESCUE_RESCUEEFFECT("goal.rescue.effect", "none", "Rescue"), - // ----------- MODULES_AFTERMATCH_AFTERMATCH("modules.aftermatch.aftermatch", "off", "AfterMatch"), diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index d8c4bb6c8..51d1fb8c7 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -477,18 +477,6 @@ public enum MSG { WHITELIST_REMOVED("nulang.whitelist.removed", "Removed &a%1%&r from &e%2%&r whitelist!"), WHITELIST_SHOW("nulang.whitelist.show", "Whitelist &e%1%&r:"), - GOAL_BEACONS_CLAIMING("nulang.goal.beacons.claiming", "&eTeam %1% is claiming the beacon!"), - GOAL_BEACONS_CLAIMED("nulang.goal.beacons.claimed", "&eTeam %1% has claimed the beacon!"), - GOAL_BEACONS_CLAIMED_REMAINING("nulang.goal.beacons.claimed_remaining", "&eTeam %1% has claimed the beacon! %2% claims remaining!"), - GOAL_BEACONS_SCORE("nulang.goal.beacons.score", "&eTeam %1% scored %2% points by holding the beacon!"), - GOAL_BEACONS_CHANGED("nulang.goal.beacons.changed", "&eA new beacon has been activated!"), - GOAL_BEACONS_CONTESTING("nulang.goal.beacons.contesting", "&eThe beacon claimed by team %1% is being contested!"), - GOAL_BEACONS_UNCLAIMING("nulang.goal.beacons.unclaiming", "&eThe beacon claimed by team %1% is being unclaimed!"), - GOAL_BEACONS_UNCLAIMINGBY("nulang.goal.beacons.unclaimingby", "&eThe beacon claimed by team %1% is being unclaimed by team %2%!"), - GOAL_BEACONS_SET("nulang.goal.beacons.set", "Beacon set: %1%"), - GOAL_BEACONS_SETDONE("nulang.goal.beacons.setdone", "Beacon setting mode deactivated."), - GOAL_BEACONS_TOSET("nulang.goal.beacons.toset", "Beacon setting mode activated. Hit the glass blocks, then use the command again to save!"), - GOAL_BLOCKDESTROY_TYPESET("nulang.goal.blockdestroy.typeset", "Blocktype set to: &e%1%"), GOAL_BLOCKDESTROY_SCORE("lang.goal.blockdestroy.score", "%1% destroyed the block of team %2%! Remaining destructions: %3%"), GOAL_BLOCKDESTROY_SET("nulang.goal.blockdestroy.setflag", "Block set: %1%"), @@ -569,15 +557,6 @@ public enum MSG { GOAL_PILLARS_MSG_SCORE("nulang.goal.pillars.msg.score", "%1% scored %2% points."), - - GOAL_RESCUE_BROUGHTHOME("nulang.goal.rescue.flaghomeleft", "%1% brought home the hostage of team %2%! Rescues remaining: %3%"), - GOAL_RESCUE_DROPPED("nulang.goal.rescue.flagsave", "%1% dropped the hostage of team %2%!"), - GOAL_RESCUE_GRABBED("nulang.goal.rescue.flaggrab", "%1% grabbed the hostage of team %2%!"), - GOAL_RESCUE_NOTSAFE("nulang.goal.rescue.flagnotsafe", "Your hostage is taken! Cannot bring back an enemy hostage!'"), - GOAL_RESCUE_SET("nulang.goal.rescue.setflag", "Rescue set: %1%"), - GOAL_RESCUE_TOSET("nulang.goal.rescue.tosetflag", "Rescue to set: %1%"), - GOAL_RESCUE_TYPESET("nulang.goal.rescue.typeset", "Hostage type set to: &e%1%"), - // ----------------------------------------------- MODULE_AFTERMATCH_STARTING("nulang.mod.aftermatch.aftermatch", "The aftermatch has begun!"), From 1d6af32a1164d0275d2b44a5ae718df0fd69dd03 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 23 Jun 2020 19:09:01 +0200 Subject: [PATCH 064/115] v1.15 - removing old telemetry system --- readme.md | 6 +- src/config.yml | 1 - src/net/slipcor/pvparena/PVPArena.java | 8 -- src/net/slipcor/pvparena/core/Language.java | 2 - src/net/slipcor/pvparena/core/Tracker.java | 84 --------------------- 5 files changed, 3 insertions(+), 98 deletions(-) delete mode 100644 src/net/slipcor/pvparena/core/Tracker.java diff --git a/readme.md b/readme.md index 1165b3c39..f0a3e22df 100644 --- a/readme.md +++ b/readme.md @@ -129,10 +129,10 @@ automatically download updates. *** -## Phoning home +## Telemetry -By default, the server contacts my private server for information purposes. It sends your port, IP (for proper server counting), and the plugin version. -That's it! If you want to disable that, set "tracker" to false in the config! +PVPArena uses bStats to get statistics about basic information like plugin version, java version, +kind of used Minecraft server, etc. You can disable it in the dedicated config file `plugins/bStats/config.yml` *** diff --git a/src/config.yml b/src/config.yml index 7ad58e3e9..b9c8d4cd8 100644 --- a/src/config.yml +++ b/src/config.yml @@ -1,7 +1,6 @@ debug: none server_log: false stats: true -tracker: true language: en onlyPVPinArena: false safeadmin: true diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index 7817e8f47..a7781ef19 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -407,7 +407,6 @@ public List onTabComplete(final CommandSender sender, final Command cmd, public void onDisable() { shuttingDown = true; ArenaManager.reset(true); - Tracker.stop(); Debug.destroy(); this.getUpdateChecker().runOnDisable(); Language.logInfo(MSG.LOG_PLUGIN_DISABLED, getDescription().getFullName()); @@ -506,13 +505,6 @@ public void onEnable() { updateChecker = new UpdateChecker(this.getFile()); - if (ArenaManager.count() > 0) { - if (PVPArena.instance.getConfig().getBoolean("tracker", true)) { - final Tracker trackMe = new Tracker(); - trackMe.start(); - } - } - Language.logInfo(MSG.LOG_PLUGIN_ENABLED, getDescription().getFullName()); } } diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 51d1fb8c7..398c5f6b6 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -326,8 +326,6 @@ public enum MSG { LOG_PLUGIN_DISABLED("nulang.log.plugindisabled", "disabled (version %1%)"), LOG_PLUGIN_ENABLED("nulang.log.pluginenabled", "enabled (version %1%)"), - LOG_TRACKER_DISABLED("nulang.log.trickerdisabled", "Plugin tracking disabled. See you soon?"), - LOG_TRACKER_ENABLED("nulang.log.trackingenabled", "Plugin tracking enabled. Set 'tracker: false' inside the main config to disable."), LOG_WARNING("nulang.log.warning", "%1%"), MESSAGES_TOARENA("nulang.messages.toArena", "You are now talking to the arena!"), diff --git a/src/net/slipcor/pvparena/core/Tracker.java b/src/net/slipcor/pvparena/core/Tracker.java deleted file mode 100644 index 51afaee9d..000000000 --- a/src/net/slipcor/pvparena/core/Tracker.java +++ /dev/null @@ -1,84 +0,0 @@ -package net.slipcor.pvparena.core; - -import net.slipcor.pvparena.PVPArena; -import net.slipcor.pvparena.core.Language.MSG; -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitTask; - -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLEncoder; - -/** - *
Tracker class
- *

- * phones home to www.slipcor.net, saving server IP and PVP Arena version - * - * @author slipcor - * @version v0.9.5 - */ - -public class Tracker implements Runnable { - private static BukkitTask timerTask; - private static final Debug debug = new Debug(18); - - /** - * call home to save the server/plugin state - */ - private void callHome() { - if (!PVPArena.instance.getConfig().getBoolean("tracker", true)) { - stop(); - return; - } - debug.i("calling home..."); - - String url = null; - try { - url = String - .format("http://www.slipcor.net/stats/call.php?port=%s&name=%s&version=%s", - PVPArena.instance.getServer().getPort(), - URLEncoder.encode(PVPArena.instance.getDescription().getName(), "UTF-8"), - URLEncoder.encode(PVPArena.instance.getDescription().getVersion(), "UTF-8")); - } catch (final UnsupportedEncodingException e) { - e.printStackTrace(); - } - - try { - new URL(url).openConnection().getInputStream(); - } catch (final Exception e) { - PVPArena.instance.getLogger().warning("Error while connecting to www.slipcor.net"); - return; - } - debug.i("successfully called home!"); - } - - @Override - public void run() { - callHome(); - } - - /** - * start tracking - */ - public void start() { - Language.logInfo(MSG.LOG_TRACKER_ENABLED); - - timerTask = Bukkit.getScheduler().runTaskTimerAsynchronously(PVPArena.instance, this, - 0L, 72000L); - } - - /** - * stop tracking - */ - public static void stop() { - Language.logInfo(MSG.LOG_TRACKER_DISABLED); - if (timerTask != null) { - try { - timerTask.cancel(); - timerTask = null; - } catch (Exception e) { - - } - } - } -} From cb715fabb80c1e1f745cf9fc2ac7e8d40902d1c2 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 24 Jun 2020 22:44:04 +0200 Subject: [PATCH 065/115] v1.15 - quick doc update for powerups mod --- doc/mods/powerups.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/mods/powerups.md b/doc/mods/powerups.md index ce75412b5..a3d5463fb 100644 --- a/doc/mods/powerups.md +++ b/doc/mods/powerups.md @@ -13,9 +13,10 @@ Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files f ## Setup -Sorry, but you have to add a freaking block to an arena config. An example is: +Sorry, but you have to add a freaking block to your arena config under `module.powerups.items`. Eg: -powerups: +```yaml +items: - Shield: - item: OBSIDIAN - dmg_receive: @@ -108,12 +109,13 @@ powerups: - repair: - items: helmet,chestplate,leggins,boots - factor: 0.2 +``` So the first layer defines the name, the second layer defines item and adds all the effects it has. This example features all possible ways of doing good and bad things, I hope it is clear oO ## Config settings -- dropspawn \- should the powerup spawn require defined spawns? `/pa [arena] spawn powerupX +- dropspawn \- should the powerup spawn require defined spawns? `/pa [arena] spawn powerupX` (where X is an integer) - usage \- by default it is "off", so please set this to either every X kills ("death:X") or every X seconds ("time:X") ## Commands From 6d858e3e318c08f5747c665ee92fb3f862c968b7 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 25 Jun 2020 13:19:14 +0200 Subject: [PATCH 066/115] v1.15 - replace bukkit by spigot dependency --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index af3846444..ad8f4de22 100644 --- a/pom.xml +++ b/pom.xml @@ -26,8 +26,8 @@ - org.bukkit - bukkit + org.spigotmc + spigot-api 1.13.2-R0.1-SNAPSHOT jar provided From 05be1b732c86c3c83ecbd17fbabfd23cfd1c9e19 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 25 Jun 2020 18:56:28 +0200 Subject: [PATCH 067/115] v1.15 - allow usage of "/pa arenaclass" command when player is in lounge --- src/net/slipcor/pvparena/commands/PAG_Arenaclass.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java b/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java index 6b5a0e5d9..8922c380d 100644 --- a/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java +++ b/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java @@ -22,6 +22,8 @@ import java.util.Set; import java.util.TreeSet; +import static net.slipcor.pvparena.arena.ArenaPlayer.Status.LOUNGE; + /** *

PVP Arena JOIN Command class
*

@@ -38,7 +40,7 @@ public PAG_Arenaclass() { @Override public void commit(final Arena arena, final CommandSender sender, final String[] args) { - if (!hasPerms(sender, arena) || !arena.getArenaConfig().getBoolean(CFG.USES_INGAMECLASSSWITCH)) { + if (!hasPerms(sender, arena)) { return; } @@ -65,6 +67,11 @@ public void commit(final Arena arena, final CommandSender sender, final String[] final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(sender.getName()); + // Player can change arena class only in lounge or with ingameClassSwith parameter set to true + if(aPlayer.getStatus() != LOUNGE && !arena.getArenaConfig().getBoolean(CFG.USES_INGAMECLASSSWITCH)) { + return; + } + final ArenaClass aClass = arena.getClass(args[0]); if (aClass == null) { From e5c0e58e4c2af31c1f880de08a912ff4a1474213 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 25 Jun 2020 19:52:31 +0200 Subject: [PATCH 068/115] v1.15 - fix players joining arenas on wrong command syntax --- src/net/slipcor/pvparena/PVPArena.java | 14 ++++---------- src/net/slipcor/pvparena/arena/Arena.java | 2 +- src/net/slipcor/pvparena/classes/PACheck.java | 14 +++++--------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index a7781ef19..d929bd324 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -367,20 +367,14 @@ public boolean onCommand(final CommandSender sender, final Command cmd, break; } } - if (paacmd == null - && PACheck.handleCommand(tempArena, sender, newArgs)) { + if (paacmd == null && PACheck.handleCommand(tempArena, sender, newArgs)) { return true; } - if (paacmd == null - && tempArena.getArenaConfig().getBoolean(CFG.CMDS_DEFAULTJOIN)) { + if (paacmd == null && tempArena.getArenaConfig().getBoolean(CFG.CMDS_DEFAULTJOIN) && args.length == 1) { paacmd = new PAG_Join(); - if (newArgs.length > 1) { - newArgs = StringParser.shiftArrayBy(newArgs, 1); - } - tempArena.getDebugger() - .i("committing: " + paacmd.getName(), sender); - paacmd.commit(tempArena, sender, newArgs); + tempArena.getDebugger().i("committing: " + paacmd.getName(), sender); + paacmd.commit(tempArena, sender, new String[0]); return true; } diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index 2cce050da..fb7b9a24d 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -794,7 +794,7 @@ public boolean isFightInProgress() { } public boolean isFreeForAll() { - return free; + return this.free; } public boolean isLocked() { diff --git a/src/net/slipcor/pvparena/classes/PACheck.java b/src/net/slipcor/pvparena/classes/PACheck.java index e3f2d5969..2cba17dd8 100644 --- a/src/net/slipcor/pvparena/classes/PACheck.java +++ b/src/net/slipcor/pvparena/classes/PACheck.java @@ -333,19 +333,20 @@ public static boolean handleJoin(final Arena arena, final ArenaTeam team; - if (args.length < 1 || arena.getTeam(args[0]) == null) { + if (args.length < 1) { // usage: /pa {arenaname} join | join an arena team = arena.getTeam(TeamManager.calcFreeTeam(arena)); + } else if(arena.getTeam(args[0]) == null) { + arena.msg(sender, Language.parse(arena, MSG.ERROR_TEAMNOTFOUND, args[0])); + return false; } else { ArenaTeam aTeam = arena.getTeam(args[0]); int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS); int maxTeamPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXTEAMPLAYERS); - if (aTeam == null) { - team = aTeam; - } else if (maxPlayers > 0 && arena.getFighters().size() > maxPlayers) { + if (maxPlayers > 0 && arena.getFighters().size() > maxPlayers) { arena.msg(sender, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL)); return false; } else if (maxTeamPlayers > 0 && aTeam.getTeamMembers().size() > maxTeamPlayers) { @@ -356,11 +357,6 @@ public static boolean handleJoin(final Arena arena, } } - if (team == null && args.length > 0) { - arena.msg(sender, - Language.parse(arena, MSG.ERROR_TEAMNOTFOUND, args[0])); - return false; - } if (team == null) { arena.msg(sender, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL)); return false; From d0f218003ae28514867ef5b1f9651d817bad8e54 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Mon, 29 Jun 2020 18:18:04 +0200 Subject: [PATCH 069/115] v1.15 - finalize tab completion system --- src/net/slipcor/pvparena/PVPArena.java | 13 ++++++--- .../pvparena/goals/GoalBlockDestroy.java | 7 ++--- src/net/slipcor/pvparena/goals/GoalFlags.java | 4 ++- src/net/slipcor/pvparena/goals/GoalFood.java | 2 +- .../pvparena/goals/GoalLiberation.java | 6 ++-- .../pvparena/goals/GoalPhysicalFlags.java | 4 ++- .../slipcor/pvparena/goals/GoalSabotage.java | 2 +- .../pvparena/managers/ArenaManager.java | 22 ++++++++++---- .../slipcor/pvparena/managers/TabManager.java | 29 +++++++++++-------- 9 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index d929bd324..06898e6b8 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -6,15 +6,22 @@ import net.slipcor.pvparena.classes.PACheck; import net.slipcor.pvparena.commands.*; import net.slipcor.pvparena.core.Config.CFG; -import net.slipcor.pvparena.core.*; +import net.slipcor.pvparena.core.Debug; +import net.slipcor.pvparena.core.Help; +import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; +import net.slipcor.pvparena.core.StringParser; import net.slipcor.pvparena.listeners.BlockListener; import net.slipcor.pvparena.listeners.EntityListener; import net.slipcor.pvparena.listeners.InventoryListener; import net.slipcor.pvparena.listeners.PlayerListener; -import net.slipcor.pvparena.loadables.*; +import net.slipcor.pvparena.loadables.ArenaGoalManager; +import net.slipcor.pvparena.loadables.ArenaModule; +import net.slipcor.pvparena.loadables.ArenaModuleManager; +import net.slipcor.pvparena.loadables.ArenaRegionShapeManager; import net.slipcor.pvparena.managers.ArenaManager; import net.slipcor.pvparena.managers.StatisticsManager; +import net.slipcor.pvparena.managers.TabManager; import net.slipcor.pvparena.updater.UpdateChecker; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -390,12 +397,10 @@ public boolean onCommand(final CommandSender sender, final Command cmd, return false; } - /* @Override public List onTabComplete(final CommandSender sender, final Command cmd, final String alias, final String[] args) { return TabManager.getMatches(sender, arenaCommands, globalCommands, args); } - */ @Override public void onDisable() { diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java index 596513ec7..33da732e5 100644 --- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java +++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java @@ -93,11 +93,10 @@ public PACheck checkCommand(final PACheck res, final String string) { @Override public List getMain() { - List result = Collections.singletonList("blocktype"); - if (arena != null) { - result = new ArrayList<>(); + List result = new ArrayList<>(); + if (this.arena != null) { result.add("blocktype"); - for (final ArenaTeam team : arena.getTeams()) { + for (final ArenaTeam team : this.arena.getTeams()) { final String sTeam = team.getName(); result.add(sTeam + "block"); } diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index 77f6fb580..d6f106994 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -42,6 +42,8 @@ import org.bukkit.util.Vector; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** *

@@ -99,7 +101,7 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList("flagtype", "flageffect", TOUCHDOWN);
+        final List result = Stream.of("flagtype", "flageffect", TOUCHDOWN).collect(Collectors.toList());
         if (this.arena != null) {
             for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
diff --git a/src/net/slipcor/pvparena/goals/GoalFood.java b/src/net/slipcor/pvparena/goals/GoalFood.java
index 1e12466e6..fc2e2c1ac 100644
--- a/src/net/slipcor/pvparena/goals/GoalFood.java
+++ b/src/net/slipcor/pvparena/goals/GoalFood.java
@@ -103,7 +103,7 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList(new String[0]);
+        final List result = new ArrayList<>();
         if (arena != null) {
             for (final ArenaTeam team : arena.getTeams()) {
                 final String sTeam = team.getName();
diff --git a/src/net/slipcor/pvparena/goals/GoalLiberation.java b/src/net/slipcor/pvparena/goals/GoalLiberation.java
index af4608dc7..09d751046 100644
--- a/src/net/slipcor/pvparena/goals/GoalLiberation.java
+++ b/src/net/slipcor/pvparena/goals/GoalLiberation.java
@@ -80,9 +80,9 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList(new String[0]);
-        if (arena != null) {
-            for (final ArenaTeam team : arena.getTeams()) {
+        final List result = new ArrayList<>();
+        if (this.arena != null) {
+            for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
                 result.add(sTeam + "button");
             }
diff --git a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
index 8415fb1c2..a70793568 100644
--- a/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
+++ b/src/net/slipcor/pvparena/goals/GoalPhysicalFlags.java
@@ -40,6 +40,8 @@
 import org.bukkit.util.Vector;
 
 import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static java.util.Optional.ofNullable;
 
@@ -100,7 +102,7 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList("flagtype", "flageffect", TOUCHDOWN);
+        final List result = Stream.of("flagtype", "flageffect", TOUCHDOWN).collect(Collectors.toList());
         if (this.arena != null) {
             for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
diff --git a/src/net/slipcor/pvparena/goals/GoalSabotage.java b/src/net/slipcor/pvparena/goals/GoalSabotage.java
index e9e891f42..81e09ee96 100644
--- a/src/net/slipcor/pvparena/goals/GoalSabotage.java
+++ b/src/net/slipcor/pvparena/goals/GoalSabotage.java
@@ -89,7 +89,7 @@ public PACheck checkCommand(final PACheck res, final String string) {
 
     @Override
     public List getMain() {
-        final List result = Arrays.asList(new String[0]);
+        final List result = new ArrayList<>();
         if (arena != null) {
             for (final ArenaTeam team : arena.getTeams()) {
                 final String sTeam = team.getName();
diff --git a/src/net/slipcor/pvparena/managers/ArenaManager.java b/src/net/slipcor/pvparena/managers/ArenaManager.java
index 5fb4c3059..cbfa8a2ae 100644
--- a/src/net/slipcor/pvparena/managers/ArenaManager.java
+++ b/src/net/slipcor/pvparena/managers/ArenaManager.java
@@ -185,6 +185,22 @@ public static Arena getArenaByName(final String name) {
         return null;
     }
 
+    public static Arena getArenaByExactName(final String name) {
+        if (name == null || name.isEmpty()) {
+            return null;
+        }
+        final String sName = name.toLowerCase();
+        final Arena arena = ARENAS.get(sName);
+        if (arena != null) {
+            return arena;
+        }
+        return ARENAS.entrySet().stream()
+                .filter(e -> name.equalsIgnoreCase(e.getKey()))
+                .findFirst()
+                .map(Map.Entry::getValue)
+                .orElse(null);
+    }
+
     /**
      * search the arenas by location
      *
@@ -243,11 +259,7 @@ public static Set getArenasByRegionLocation(
      * @return a Set of Arena
      */
     public static Set getArenas() {
-        final Set arenas = new HashSet<>();
-        for (final Arena a : ARENAS.values()) {
-            arenas.add(a);
-        }
-        return arenas;
+        return new HashSet<>(ARENAS.values());
     }
 
     /**
diff --git a/src/net/slipcor/pvparena/managers/TabManager.java b/src/net/slipcor/pvparena/managers/TabManager.java
index 32df6c243..ae18f7e0b 100644
--- a/src/net/slipcor/pvparena/managers/TabManager.java
+++ b/src/net/slipcor/pvparena/managers/TabManager.java
@@ -18,6 +18,9 @@
 import org.bukkit.potion.PotionEffectType;
 
 import java.util.*;
+import java.util.stream.Collectors;
+
+import static org.bukkit.util.StringUtil.startsWithIgnoreCase;
 
 public final class TabManager {
     private TabManager() {}
@@ -38,7 +41,7 @@ public static List getMatches(final CommandSender sender, final List getMatches(final CommandSender sender, final List(matches);
                 }
-                for (final Arena a : ArenaManager.getArenas()) {
-                    matches.add(a.getName());
-                }
-                return new ArrayList<>(matches);
+
+                final String search = args[0];
+                return ArenaManager.getArenas().stream()
+                        .filter(a -> startsWithIgnoreCase(a.getName(), search))
+                        .map(Arena::getName)
+                        .collect(Collectors.toList());
             }
         }
 
@@ -118,12 +123,12 @@ private static void addCommandsStartingWithPrefix(final Set matches, fin
         for (final IArenaCommandHandler ach : list) {
             if (ach.hasPerms(sender, arena)) {
                 for (final String value : ach.getMain()) {
-                    if (value.startsWith(prefix)) {
+                    if (startsWithIgnoreCase(value, prefix)) {
                         matches.add(value);
                     }
                 }
                 for (final String value : ach.getShort()) {
-                    if (value.startsWith(prefix)) {
+                    if (startsWithIgnoreCase(value, prefix)) {
                         matches.add(value);
                     }
                 }
@@ -140,7 +145,7 @@ private static void addCommandsStartingWithPrefix(final Set matches, fin
      */
     private static void addEnumMatchesToList(final List result, final String key, final List list) {
         for (final Enum e : list) {
-            if (e.name().startsWith(key)) {
+            if (startsWithIgnoreCase(e.name(), key)) {
                 result.add(e.name());
             }
         }
@@ -220,7 +225,7 @@ private static void addTreesMatchingValueInHandlerList(final List getKeyMatchesInsideDefinition(final String key, final String definition) {
         final List result = new ArrayList<>();
-        if (key != null && !key.isEmpty() && definition.startsWith(key) || key != null && key.isEmpty() && !definition.startsWith("{")) {
+        if (key != null && (!key.isEmpty() && startsWithIgnoreCase(definition, key) || key.isEmpty() && !definition.startsWith("{"))) {
             result.add(definition);
         }
         if (definition.startsWith("{")) {
@@ -235,7 +240,7 @@ private static List getKeyMatchesInsideDefinition(final String key, fina
                     }
                 } else if (key != null) {
                     for (final Player val : players) {
-                        if (val.getName().startsWith(key)) {
+                        if (startsWithIgnoreCase(val.getName(), key)) {
                             result.add(val.getName());
                         }
                     }
@@ -257,7 +262,7 @@ private static List getKeyMatchesInsideDefinition(final String key, fina
                     result.addAll(values);
                 } else if (key != null) {
                     for (final String val : values) {
-                        if (val.startsWith(key)) {
+                        if (startsWithIgnoreCase(val, key)) {
                             result.add(val);
                         }
                     }
@@ -270,7 +275,7 @@ private static List getKeyMatchesInsideDefinition(final String key, fina
                     }
                 } else if (key != null) {
                     for (final PotionEffectType val : pet) {
-                        if (val.getName().startsWith(key)) {
+                        if (startsWithIgnoreCase(val.getName(), key)) {
                             result.add(val.getName());
                         }
                     }

From 7ea197c7b2d5bb292b0ff1b5bef2c066d2b326c0 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 30 Jun 2020 13:26:08 +0200
Subject: [PATCH 070/115] v1.15 - fix disabling region selector

---
 src/net/slipcor/pvparena/commands/PAA_Region.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/net/slipcor/pvparena/commands/PAA_Region.java b/src/net/slipcor/pvparena/commands/PAA_Region.java
index a0812ee69..39d2f297a 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Region.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Region.java
@@ -64,6 +64,7 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
                 if (sender.getName().equals(selector)) {
                     arena.msg(sender, Language.parse(arena, MSG.ERROR_REGION_YOUSELECTEXIT));
                     selector = null;
+                    activeSelections.remove(sender.getName());
                 } else {
                     arena.msg(sender, Language.parse(arena, MSG.ERROR_REGION_YOUSELECT, arena.getName()));
                     arena.msg(sender, Language.parse(arena, MSG.ERROR_REGION_YOUSELECT2));

From 10fe613a5426b9d9668bee100a857bcc0b3889df Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 30 Jun 2020 22:27:40 +0200
Subject: [PATCH 071/115] v1.15 - centralize all mods management in one command

---
 lang/lang_en.yml                              |   8 +
 src/net/slipcor/pvparena/PVPArena.java        |   8 +-
 .../pvparena/commands/PAA_Install.java        | 173 -----------
 .../pvparena/commands/PAA_Modules.java        | 291 ++++++++++++++++++
 .../pvparena/commands/PAA_Uninstall.java      | 138 ---------
 .../slipcor/pvparena/commands/PAA_Update.java |  97 ------
 src/net/slipcor/pvparena/core/Language.java   |   5 +-
 .../pvparena/updater/ModulesUpdater.java      |  31 +-
 .../pvparena/updater/PluginUpdater.java       |   4 +-
 9 files changed, 336 insertions(+), 419 deletions(-)
 delete mode 100644 src/net/slipcor/pvparena/commands/PAA_Install.java
 create mode 100644 src/net/slipcor/pvparena/commands/PAA_Modules.java
 delete mode 100644 src/net/slipcor/pvparena/commands/PAA_Uninstall.java
 delete mode 100644 src/net/slipcor/pvparena/commands/PAA_Update.java

diff --git a/lang/lang_en.yml b/lang/lang_en.yml
index 5adb41b8a..df896e5df 100644
--- a/lang/lang_en.yml
+++ b/lang/lang_en.yml
@@ -627,6 +627,14 @@ nulang:
     clear: Inventories cleared!
   announce:
     arena: Arena is starting! Type /pa %1% to join!
+  updater:
+    plugin: PVP Arena
+    modules: PVP Arena modules pack
+    announce: '%1% %2% is now available ! Your version: %3%'
+    success: '%1% has been updated to %2%.'
+    restart: Restart your server to apply update.
+    downloading: 'Downloading %1%...'
+    downloaderror: 'Error while downloading %1%'
 lang:
   goal:
     blockdestroy:
diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java
index 06898e6b8..abe7b95da 100644
--- a/src/net/slipcor/pvparena/PVPArena.java
+++ b/src/net/slipcor/pvparena/PVPArena.java
@@ -213,9 +213,7 @@ private void loadGlobalCommands() {
         globalCommands.add(new PAA_Debug());
         globalCommands.add(new PAA_Duty());
         globalCommands.add(new PAI_Help());
-        globalCommands.add(new PAA_Install());
-        globalCommands.add(new PAA_Uninstall());
-        globalCommands.add(new PAA_Update());
+        globalCommands.add(new PAA_Modules());
         globalCommands.add(new PAI_ArenaList());
         globalCommands.add(new PAI_Version());
     }
@@ -458,9 +456,9 @@ public void onEnable() {
 
         FileConfiguration cfg = getConfig();
         List toDelete = cfg.getStringList("todelete");
-        if (toDelete != null){
+        if (!toDelete.isEmpty()){
             for (String jar : toDelete) {
-                PAA_Uninstall.remove(jar);
+                PAA_Modules.remove(jar);
             }
             cfg.set("todelete", null);
             saveConfig();
diff --git a/src/net/slipcor/pvparena/commands/PAA_Install.java b/src/net/slipcor/pvparena/commands/PAA_Install.java
deleted file mode 100644
index 046539135..000000000
--- a/src/net/slipcor/pvparena/commands/PAA_Install.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package net.slipcor.pvparena.commands;
-
-import net.slipcor.pvparena.PVPArena;
-import net.slipcor.pvparena.arena.Arena;
-import net.slipcor.pvparena.core.Help;
-import net.slipcor.pvparena.core.Help.HELP;
-import net.slipcor.pvparena.core.Language;
-import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.loadables.ArenaModule;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.command.CommandSender;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * 
- * PVP Arena INSTALL Command class
- * 
- *

- * A command to install modules - * - * @author slipcor - * @version v0.10.0 - */ - -public class PAA_Install extends AbstractGlobalCommand { - - public PAA_Install() { - super(new String[]{"pvparena.cmds.install"}); - } - - private static final File FILES_DIR = new File(PVPArena.instance.getDataFolder(),"/files/"); - - @Override - public void commit(final CommandSender sender, final String[] args) { - if (!hasPerms(sender)) { - return; - } - - if (!argCountValid(sender, args, new Integer[]{0, 1})) { - return; - } - - // pa install - // pa install ctf - - if (args.length == 0) { - listInstalled(sender); - return; - } - - Set modList = getModList(); - if (modList.size() == 0 || modList.contains(args[0].toLowerCase())) { - String modName = args[0].toLowerCase(); - if (download("pa_m_" + modName + ".jar")) { - PVPArena.instance.getAmm().reload(); - Arena.pmsg(sender, Language.parse(MSG.INSTALL_DONE, modName)); - } else { - Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, modName)); - } - } - } - - public static Set listInstalled(final CommandSender sender) { - Arena.pmsg(sender, "--- PVP Arena Version Update information ---"); - Arena.pmsg(sender, "[" + ChatColor.GRAY + "uninstalled" + ChatColor.RESET + " | " + ChatColor.YELLOW + "installed" + ChatColor.RESET + "]"); - Arena.pmsg(sender, ChatColor.GREEN + "--- Installed Arena Mods ---->"); - Set modList = new HashSet<>(); - - for (final String modName : getModList()) { - final ArenaModule mod = PVPArena.instance.getAmm().getModByName(modName); - Arena.pmsg(sender, (mod != null ? ChatColor.YELLOW : ChatColor.GRAY) + modName + ChatColor.RESET); - } - return modList; - } - - private static Set getModList() { - Set modList = new HashSet<>(); - for (final File file : FILES_DIR.listFiles()) { - final String fileName = file.getName(); - if (fileName.startsWith("pa_m_") && fileName.endsWith(".jar")) { - String modName = fileName.substring(5, fileName.length() - 4); - modList.add(modName); - } - } - return modList; - } - - private boolean download(final String file) { - return download(file, false); - } - - private boolean download(final String file, final boolean silent) { - - final File source = new File(FILES_DIR, file); - - if (!source.exists()) { - if (!silent) { - Arena.pmsg( - Bukkit.getConsoleSender(), - ChatColor.COLOR_CHAR + "cFile '" + ChatColor.COLOR_CHAR + 'r' - + file - + ChatColor.COLOR_CHAR + "c' not found. Please extract the file to /files before trying to install!"); - } - return false; - } - - String folder = "/mods/"; - - try { - final File destination = new File(PVPArena.instance.getDataFolder() - .getPath() + folder + '/' + file); - final FileInputStream stream = new FileInputStream(source); - - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = stream.read(buffer)) > 0) { - baos.write(buffer, 0, bytesRead); - } - - final FileOutputStream fos = new FileOutputStream(destination); - fos.write(baos.toByteArray()); - fos.close(); - - PVPArena.instance.getLogger().info("Installed module " + file); - stream.close(); - return true; - } catch (final Exception e) { - e.printStackTrace(); - } - return false; - } - - @Override - public String getName() { - return getClass().getName(); - } - - @Override - public void displayHelp(final CommandSender sender) { - Arena.pmsg(sender, Help.parse(HELP.INSTALL)); - } - - @Override - public List getMain() { - return Collections.singletonList("install"); - } - - @Override - public List getShort() { - return Collections.singletonList("!i"); - } - - @Override - public CommandTree getSubs(final Arena nothing) { - final CommandTree result = new CommandTree<>(null); - - Set modList = getModList(); - for (final String key : modList) { - result.define(new String[]{key}); - } - return result; - } -} diff --git a/src/net/slipcor/pvparena/commands/PAA_Modules.java b/src/net/slipcor/pvparena/commands/PAA_Modules.java new file mode 100644 index 000000000..f2b742a63 --- /dev/null +++ b/src/net/slipcor/pvparena/commands/PAA_Modules.java @@ -0,0 +1,291 @@ +package net.slipcor.pvparena.commands; + +import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.arena.Arena; +import net.slipcor.pvparena.core.Help; +import net.slipcor.pvparena.core.Help.HELP; +import net.slipcor.pvparena.core.Language; +import net.slipcor.pvparena.core.Language.MSG; +import net.slipcor.pvparena.loadables.ArenaModule; +import net.slipcor.pvparena.ncloader.NCBLoadable; +import net.slipcor.pvparena.updater.ModulesUpdater; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.*; + +/** + *

+ * PVP Arena MODULES Command class
+ * 
+ *

+ * A command to manage modules (list, install, uninstall, update, download and upgrade) + * + * @author Eredrim + * @version v1.15 + */ + +public class PAA_Modules extends AbstractGlobalCommand { + + public PAA_Modules() { + super(new String[]{"pvparena.cmds.modules"}); + } + + private static final File FILES_DIR = new File(PVPArena.instance.getDataFolder(),"/files/"); + private static final File MODS_DIR = new File(PVPArena.instance.getDataFolder(),"/mods/"); + + @Override + public void commit(final CommandSender sender, final String[] args) { + if (!this.hasPerms(sender)) { + return; + } + + if (!argCountValid(sender, args, new Integer[]{0, 1, 2})) { + return; + } + + // pa modules + if (args.length == 0) { + listModules(sender); + } else if (args.length == 1) { + switch (args[0]) { + case "list": + listModules(sender); + break; + case "update": + updateModules(sender); + break; + case "download": + ModulesUpdater.downloadModulePack(sender); + break; + case "upgrade": + ModulesUpdater.downloadModulePack(sender); + updateModules(sender); + break; + case "install": + case "uninstall": + Arena.pmsg(sender, Language.parse(MSG.ERROR_INVALID_ARGUMENT_COUNT, "1", "2")); + break; + default: + // Show specific help + } + } else { // 2 args only (if more args, caught above) + if("install".equalsIgnoreCase(args[0])) { + installModule(sender, args[1]); + } else if ("uninstall".equalsIgnoreCase(args[0])) { + uninstallModule(sender, args[1]); + } else { + Arena.pmsg(sender, Language.parse(MSG.ERROR_INVALID_ARGUMENT_COUNT, "2", "1")); + } + } + } + + /** + * List all modules status to sender + * @param sender User who typed the command + */ + private static void listModules(final CommandSender sender) { + Arena.pmsg(sender, "--- PVP Arena Version Update information ---"); + Arena.pmsg(sender, "[" + ChatColor.GRAY + "uninstalled" + ChatColor.RESET + " | " + ChatColor.YELLOW + "installed" + ChatColor.RESET + "]"); + Arena.pmsg(sender, ChatColor.GREEN + "--- Installed Arena Mods ---->"); + + for (final String modName : getModInFilesFolder()) { + final ArenaModule mod = PVPArena.instance.getAmm().getModByName(modName); + Arena.pmsg(sender, (mod != null ? ChatColor.YELLOW : ChatColor.GRAY) + modName + ChatColor.RESET); + } + } + + /** + * Install a module (copying from /files to /mods) + * @param sender User who typed the command + * @param name Module named typed by user + */ + private static void installModule(CommandSender sender, String name) { + Set modList = getModInFilesFolder(); + String modName = name.toLowerCase(); + if (modList.size() != 0 && modList.contains(modName)) { + + if (copyFile("pa_m_" + modName + ".jar")) { + PVPArena.instance.getAmm().reload(); + Arena.pmsg(sender, Language.parse(MSG.INSTALL_DONE, modName)); + } else { + Arena.pmsg(sender, Language.parse(MSG.ERROR_INSTALL, modName)); + } + } else { + Arena.pmsg(sender, Language.parse(MSG.ERROR_UNKNOWN_MODULE, name)); + } + } + + /** + * Uninstall a module + * Unload it and remove it from /mods directory + * @param sender User who typed the command + * @param name Module named typed by user + */ + private static void uninstallModule(CommandSender sender, String name) { + final ArenaModule mod = PVPArena.instance.getAmm().getModByName(name); + if (mod != null) { + String modName = mod.getName(); + String jarName = "pa_m_" + modName.toLowerCase() + ".jar"; + if (remove(jarName)) { + PVPArena.instance.getAmm().reload(); + Arena.pmsg(sender, Language.parse(MSG.UNINSTALL_DONE, modName)); + } else { + Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL, modName)); + FileConfiguration cfg = PVPArena.instance.getConfig(); + List toDelete = cfg.getStringList("todelete"); + toDelete.add(jarName); + cfg.set("todelete", toDelete); + PVPArena.instance.saveConfig(); + Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL2)); + } + } + } + + /** + * Replace all modules of /mods directory by ones of /files directory + * @param sender User who typed the command + */ + private static void updateModules(CommandSender sender) { + final Set modules = new HashSet<>(PVPArena.instance.getAmm().getAllMods()); + + modules.stream() + .filter(mod -> !mod.isInternal()) + .forEach(mod -> { + final File jarFile = new File(FILES_DIR, "pa_m_" + mod.getName().toLowerCase() + ".jar"); + + if (jarFile.exists()) { + uninstallModule(sender, mod.getName()); + installModule(sender, mod.getName()); + } + }); + } + + /** + * List all mods in /files folder + * @return List of mod names + */ + private static Set getModInFilesFolder() { + Set modList = new HashSet<>(); + for (final File file : FILES_DIR.listFiles()) { + final String fileName = file.getName(); + if (fileName.startsWith("pa_m_") && fileName.endsWith(".jar")) { + String modName = fileName.substring(5, fileName.length() - 4); + modList.add(modName); + } + } + return modList; + } + + /** + * Copy a file from /files folder to /mod folder + * @param file file name + * @return true if install was successful + */ + private static boolean copyFile(final String file) { + + final File source = new File(FILES_DIR, file); + + if (!source.exists()) { + Arena.pmsg( + Bukkit.getConsoleSender(), + String.format("%sFile '%s%s%s' not found. Please extract the file to /files before trying to install!", ChatColor.RED, ChatColor.RESET, file, ChatColor.RED)); + return false; + } + + try { + final File destination = new File(MODS_DIR, file); + final FileInputStream stream = new FileInputStream(source); + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = stream.read(buffer)) > 0) { + baos.write(buffer, 0, bytesRead); + } + + final FileOutputStream fos = new FileOutputStream(destination); + fos.write(baos.toByteArray()); + fos.close(); + + PVPArena.instance.getLogger().info("Installed module " + file); + stream.close(); + return true; + } catch (final Exception e) { + e.printStackTrace(); + } + return false; + } + + /** + * Remove a mod from /mods folder + * @param file module file name + * @return true if deletion was successful + */ + public static boolean remove(final String file) { + if (!MODS_DIR.exists()) { + PVPArena.instance.getLogger().severe("unable to fetch file: " + file); + return false; + } + + final File destFile = new File(MODS_DIR, file); + + boolean exists = destFile.exists(); + boolean deleted = false; + if (exists) { + deleted = destFile.delete(); + if (!deleted) { + PVPArena.instance.getLogger().severe("could not delete file: " + file); + } + } else { + PVPArena.instance.getLogger().warning("file does not exist: " + file); + } + + return exists && deleted; + } + + @Override + public String getName() { + return this.getClass().getName(); + } + + @Override + public void displayHelp(final CommandSender sender) { + Arena.pmsg(sender, Help.parse(HELP.INSTALL)); + } + + @Override + public List getMain() { + return Collections.singletonList("modules"); + } + + @Override + public List getShort() { + return Collections.singletonList("!m"); + } + + @Override + public CommandTree getSubs(final Arena nothing) { + final CommandTree result = new CommandTree<>(null); + + result.define(new String[]{"download"}); + result.define(new String[]{"list"}); + result.define(new String[]{"update"}); + result.define(new String[]{"upgrade"}); + + getModInFilesFolder().forEach(modName -> result.define(new String[]{"install", modName})); + + PVPArena.instance.getAmm().getAllMods().stream() + .filter(mod -> !mod.isInternal()) + .map(ArenaModule::getName) + .forEach(modName -> result.define(new String[]{"uninstall", modName})); + + return result; + } +} diff --git a/src/net/slipcor/pvparena/commands/PAA_Uninstall.java b/src/net/slipcor/pvparena/commands/PAA_Uninstall.java deleted file mode 100644 index 63389963f..000000000 --- a/src/net/slipcor/pvparena/commands/PAA_Uninstall.java +++ /dev/null @@ -1,138 +0,0 @@ -package net.slipcor.pvparena.commands; - -import net.slipcor.pvparena.PVPArena; -import net.slipcor.pvparena.arena.Arena; -import net.slipcor.pvparena.core.Help; -import net.slipcor.pvparena.core.Help.HELP; -import net.slipcor.pvparena.core.Language; -import net.slipcor.pvparena.core.Language.MSG; -import net.slipcor.pvparena.loadables.ArenaModule; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - *

PVP Arena UNINSTALL Command class
- *

- * A command to uninstall modules - * - * @author slipcor - * @version v0.10.0 - */ - -public class PAA_Uninstall extends AbstractGlobalCommand { - - public PAA_Uninstall() { - super(new String[]{"pvparena.cmds.uninstall"}); - } - - @Override - public void commit(final CommandSender sender, final String[] args) { - if (!hasPerms(sender)) { - return; - } - - if (!argCountValid(sender, args, - new Integer[]{0, 1})) { - return; - } - - // pa install - // pa install ctf - - final YamlConfiguration config = new YamlConfiguration(); - try { - config.load(PVPArena.instance.getDataFolder().getPath() + "/install.yml"); - } catch (final Exception e) { - } - - if (args.length == 0 || config.get(args[0]) != null) { - PAA_Install.listInstalled(sender); - return; - } - - final String name = args[0].toLowerCase(); - final ArenaModule mod = PVPArena.instance.getAmm().getModByName(name); - if (mod != null) { - if (remove("pa_m_" + mod.getName().toLowerCase() + ".jar")) { - PVPArena.instance.getAmm().reload(); - Arena.pmsg(sender, Language.parse(MSG.UNINSTALL_DONE, mod.getName())); - return; - } - Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL, mod.getName())); - FileConfiguration cfg = PVPArena.instance.getConfig(); - List toDelete = cfg.getStringList("todelete"); - if (toDelete == null){ - toDelete = new ArrayList<>(); - } - toDelete.add("pa_m_" + mod.getName().toLowerCase() + ".jar"); - cfg.set("todelete", toDelete); - PVPArena.instance.saveConfig(); - Arena.pmsg(sender, Language.parse(MSG.ERROR_UNINSTALL2)); - } - } - - @Override - public String getName() { - return getClass().getName(); - } - - public static boolean remove(final String file) { - String folder = null; - if (file.startsWith("pa_g")) { - folder = "/goals/"; - } else if (file.startsWith("pa_m")) { - folder = "/mods/"; - } - if (folder == null) { - PVPArena.instance.getLogger().severe("unable to fetch file: " + file); - return false; - } - final File destination = new File(PVPArena.instance.getDataFolder().getPath() - + folder); - - final File destFile = new File(destination, file); - - boolean exists = destFile.exists(); - boolean deleted = false; - if (exists) { - deleted = destFile.delete(); - if (!deleted) { - PVPArena.instance.getLogger().severe("could not delete file: " + file); - } - } else { - PVPArena.instance.getLogger().warning("file does not exist: " + file); - } - - return exists && deleted; - } - - @Override - public void displayHelp(final CommandSender sender) { - Arena.pmsg(sender, Help.parse(HELP.UNINSTALL)); - } - - @Override - public List getMain() { - return Collections.singletonList("uninstall"); - } - - @Override - public List getShort() { - return Collections.singletonList("!ui"); - } - - @Override - public CommandTree getSubs(final Arena nothing) { - final CommandTree result = new CommandTree<>(null); - for (final ArenaModule mod : PVPArena.instance.getAmm().getAllMods()) { - result.define(new String[]{mod.getName()}); - } - return result; - } -} diff --git a/src/net/slipcor/pvparena/commands/PAA_Update.java b/src/net/slipcor/pvparena/commands/PAA_Update.java deleted file mode 100644 index 690a3ffdc..000000000 --- a/src/net/slipcor/pvparena/commands/PAA_Update.java +++ /dev/null @@ -1,97 +0,0 @@ -package net.slipcor.pvparena.commands; - -import net.slipcor.pvparena.PVPArena; -import net.slipcor.pvparena.arena.Arena; -import net.slipcor.pvparena.core.Help; -import net.slipcor.pvparena.core.Help.HELP; -import net.slipcor.pvparena.loadables.ArenaModule; -import net.slipcor.pvparena.ncloader.NCBLoadable; -import org.bukkit.command.CommandSender; - -import java.io.File; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - *

PVP Arena UPDATE Command class
- *

- * A command to update modules - * - * @author slipcor - * @version v0.10.0 - */ - -public class PAA_Update extends AbstractGlobalCommand { - - public PAA_Update() { - super(new String[]{"pvparena.cmds.update"}); - } - - @Override - public void commit(final CommandSender sender, final String[] args) { - if (!hasPerms(sender)) { - return; - } - - final Set modules = new HashSet(PVPArena.instance.getAmm().getAllMods()); - - if (!modules.isEmpty()) { - for (final NCBLoadable mod : modules) { - if (mod.isInternal()) { - continue; - } - - final File destination = new File(PVPArena.instance.getDataFolder().getPath() - + "/files/"); - final File destFileM = new File(destination, "pa_m_" + mod.getName().toLowerCase() + ".jar"); - - if (!destFileM.exists()) { - continue; - } - - final PAA_Uninstall uninstall = new PAA_Uninstall(); - if (!uninstall.hasPerms(sender)) { - return; - } - uninstall.commit(sender, new String[]{mod.getName()}); - final PAA_Install install = new PAA_Install(); - if (!install.hasPerms(sender)) { - return; - } - install.commit(sender, new String[]{mod.getName()}); - } - } - } - - - @Override - public String getName() { - return getClass().getName(); - } - - @Override - public void displayHelp(final CommandSender sender) { - Arena.pmsg(sender, Help.parse(HELP.UPDATE)); - } - - @Override - public List getMain() { - return Collections.singletonList("update"); - } - - @Override - public List getShort() { - return Collections.singletonList("!u"); - } - - @Override - public CommandTree getSubs(final Arena nothing) { - final CommandTree result = new CommandTree<>(null); - for (final ArenaModule mod : PVPArena.instance.getAmm().getAllMods()) { - result.define(new String[]{mod.getName()}); - } - return result; - } -} diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 398c5f6b6..721b575af 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -466,7 +466,10 @@ public enum MSG { UPDATER_PLUGIN("nulang.updater.plugin", "PVP Arena"), UPDATER_MODULES("nulang.updater.modules", "PVP Arena modules pack"), UPDATER_ANNOUNCE("nulang.updater.announce", "%1% %2% is now available ! Your version: %3%"), - UPDATER_SUCCESS("nulang.updater.success", "%1% has been updated to %2%. Restart your server to apply update."), + UPDATER_SUCCESS("nulang.updater.success", "%1% has been updated to %2%."), + UPDATER_RESTART("nulang.updater.restart", "Restart your server to apply update."), + UPDATER_DOWNLOADING("nulang.updater.downloading", "Downloading %1%..."), + UPDATER_DOWNLOAD_ERROR("nulang.updater.downloaderror", "Error while downloading %1%"), WHITELIST_ADDED("nulang.whitelist.added", "Added &a%1%&r to &e%2%&r whitelist!"), WHITELIST_ALLCLEARED("nulang.whitelist.allcleared", "All whitelists cleared!"), diff --git a/src/net/slipcor/pvparena/updater/ModulesUpdater.java b/src/net/slipcor/pvparena/updater/ModulesUpdater.java index 0a036898e..18c61dc84 100644 --- a/src/net/slipcor/pvparena/updater/ModulesUpdater.java +++ b/src/net/slipcor/pvparena/updater/ModulesUpdater.java @@ -2,6 +2,9 @@ import com.google.gson.JsonObject; import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.arena.Arena; +import net.slipcor.pvparena.core.Language; +import org.bukkit.command.CommandSender; import java.io.File; import java.io.FileOutputStream; @@ -54,7 +57,7 @@ protected void runUpdater() throws IOException { String filename = getFilenameFromJson(versionJson); LOG.info("Downloading modules update..."); try { - this.downloadAndUnpackModules(getDownloadUrlFromJson(versionJson), filename); + downloadAndUnpackModules(getDownloadUrlFromJson(versionJson), filename); String updateSuccess = getSuccessMessage(MSG.UPDATER_MODULES.toString(), onlineVersion); LOG.info(updateSuccess); this.updateMsgList.add(updateSuccess); @@ -66,6 +69,26 @@ protected void runUpdater() throws IOException { } } + public static void downloadModulePack(CommandSender sender) { + try { + URL githubApi = new URL(API_URL); + URLConnection connection = githubApi.openConnection(); + JsonObject versionJson = getVersionJson(connection.getInputStream()); + String onlineVersion = getOnlineVersionFromJson(versionJson); + String filename = getFilenameFromJson(versionJson); + + Arena.pmsg(sender, Language.parse(MSG.UPDATER_DOWNLOADING, Language.parse(MSG.UPDATER_MODULES))); + downloadAndUnpackModules(getDownloadUrlFromJson(versionJson), filename); + String updateSuccess = getSuccessMessage(MSG.UPDATER_MODULES.toString(), onlineVersion); + LOG.info(updateSuccess); + } catch (IOException e) { + String errorMsg = Language.parse(MSG.UPDATER_DOWNLOAD_ERROR, Language.parse(MSG.UPDATER_MODULES)); + Arena.pmsg(sender, errorMsg); + LOG.warning(errorMsg); + e.printStackTrace(); + } + } + /** * Get current modules version based on version.lock * @return version string (x.x.x format) @@ -89,7 +112,7 @@ private String getModulesVersion() { * @param filename Packge file name * @throws IOException */ - private void downloadAndUnpackModules(String downloadUrlStr, String filename) throws IOException { + private static void downloadAndUnpackModules(String downloadUrlStr, String filename) throws IOException { URL downloadUrl = new URL(downloadUrlStr); File dataFolder = PVPArena.instance.getDataFolder(); File zipFile = new File(dataFolder, filename); @@ -100,7 +123,7 @@ private void downloadAndUnpackModules(String downloadUrlStr, String filename) th FileOutputStream outputStream = new FileOutputStream(zipFile); outputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); outputStream.close(); - deleteDirectory(this.getFilesFolder()); + deleteDirectory(getFilesFolder()); ZipUtil.unzip(zipFile, dataFolder); zipFile.delete(); } @@ -109,7 +132,7 @@ private void downloadAndUnpackModules(String downloadUrlStr, String filename) th * Returns PVP Arena "files" folder * @return "files" folder */ - private File getFilesFolder() { + private static File getFilesFolder() { return new File(PVPArena.instance.getDataFolder().getPath() + "/files"); } diff --git a/src/net/slipcor/pvparena/updater/PluginUpdater.java b/src/net/slipcor/pvparena/updater/PluginUpdater.java index d4f250ba0..515998886 100644 --- a/src/net/slipcor/pvparena/updater/PluginUpdater.java +++ b/src/net/slipcor/pvparena/updater/PluginUpdater.java @@ -2,6 +2,7 @@ import com.google.gson.JsonObject; import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.core.Language; import org.bukkit.Bukkit; import java.io.File; @@ -56,7 +57,8 @@ protected void runUpdater() throws IOException { LOG.info("Downloading update..."); try { downloadPlugin(getDownloadUrlFromJson(versionJson), filename); - String updateSuccess = getSuccessMessage(MSG.UPDATER_PLUGIN.toString(), onlineVersion); + String updateSuccess = getSuccessMessage(MSG.UPDATER_PLUGIN.toString(), onlineVersion) + " " + + Language.parse(MSG.UPDATER_RESTART); LOG.info(updateSuccess); this.updateMsgList.add(updateSuccess); this.planPluginRenaming(filename); From 4f6bf89951041f12dfb6bd03177ab0101b2f9750 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 2 Jul 2020 22:33:54 +0200 Subject: [PATCH 072/115] v1.15 - fix several issues with tab command completion --- lang/lang_en.yml | 4 +- lang/lang_fr.yml | 4 +- src/net/slipcor/pvparena/PVPArena.java | 60 ++---------- .../commands/AbstractGlobalCommand.java | 8 ++ .../pvparena/commands/PAA_ReloadAll.java | 96 +++++++++++++++++++ .../pvparena/commands/PAI_ArenaList.java | 5 + .../pvparena/commands/PAI_GlobalStats.java | 73 ++++++++++++++ src/net/slipcor/pvparena/core/Language.java | 4 +- .../slipcor/pvparena/managers/TabManager.java | 86 ++++++++--------- 9 files changed, 235 insertions(+), 105 deletions(-) create mode 100644 src/net/slipcor/pvparena/commands/PAA_ReloadAll.java create mode 100644 src/net/slipcor/pvparena/commands/PAI_GlobalStats.java diff --git a/lang/lang_en.yml b/lang/lang_en.yml index df896e5df..e65ae4662 100644 --- a/lang/lang_en.yml +++ b/lang/lang_en.yml @@ -210,7 +210,6 @@ nulang: enable: use the enable command gamemode: use the gamemode command goal: use the goal command - install: use the install command playerclass: use the playerclass command playerjoin: use the playerjoin command protection: use the protection command @@ -231,8 +230,7 @@ nulang: teleport: use the teleport command template: use the template command togglemod: use the togglemod command - uninstall: use the uninstall command - update: use the update command + modules: use the modules command whitelist: use the whitelist command arenaclass: use the arenaclass command chat: use the chat command diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml index 6c65dc79f..dbe002ee7 100644 --- a/lang/lang_fr.yml +++ b/lang/lang_fr.yml @@ -222,7 +222,6 @@ nulang: enable: d'utiliser la commande enable gamemode: d'utiliser la commande gamemode goal: d'utiliser la commande goal - install: d'utiliser la commande install playerclass: d'utiliser la commande playerclass playerjoin: d'utiliser la commande playerjoin protection: d'utiliser la commande protection @@ -243,8 +242,7 @@ nulang: teleport: d'utiliser la commande teleport template: d'utiliser la commande template togglemod: d'utiliser la commande togglemod - uninstall: d'utiliser la commande uninstall - update: d'utiliser la commande update + modules: d'utiliser la commande modules whitelist: d'utiliser la commande whitelist arenaclass: d'utiliser la commande arenaclass chat: d'utiliser la commande chat diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index abe7b95da..1ea210cde 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -50,7 +50,7 @@ public class PVPArena extends JavaPlugin { public static PVPArena instance; - private static Debug DEBUG; + private static Debug debugger; private ArenaGoalManager agm; private ArenaModuleManager amm; @@ -206,15 +206,18 @@ private void loadArenaCommands() { arenaCommands.add(new PAI_Shutup()); arenaCommands.add(new PAG_Arenaclass()); arenaCommands.add(new PAI_Info()); + arenaCommands.add(new PAI_Stats()); } private void loadGlobalCommands() { globalCommands.add(new PAA_Create()); globalCommands.add(new PAA_Debug()); globalCommands.add(new PAA_Duty()); - globalCommands.add(new PAI_Help()); globalCommands.add(new PAA_Modules()); + globalCommands.add(new PAA_ReloadAll()); globalCommands.add(new PAI_ArenaList()); + globalCommands.add(new PAI_GlobalStats()); + globalCommands.add(new PAI_Help()); globalCommands.add(new PAI_Version()); } @@ -259,59 +262,12 @@ public boolean onCommand(final CommandSender sender, final Command cmd, } } final ArenaPlayer player = ArenaPlayer.parsePlayer(sender.getName()); - if (pacmd != null - && !(player.getArena() != null && pacmd.getName() - .contains("PAI_ArenaList"))) { - DEBUG.i("committing: " + pacmd.getName(), sender); + if (pacmd != null && !(player.getArena() != null && pacmd.hasVersionForArena())) { + debugger.i("committing: " + pacmd.getName(), sender); pacmd.commit(sender, StringParser.shiftArrayBy(args, 1)); return true; } - if ("-s".equalsIgnoreCase(args[0]) || "stats".equalsIgnoreCase(args[0])) { - final PAI_Stats scmd = new PAI_Stats(); - DEBUG.i("committing: " + scmd.getName(), sender); - scmd.commit(null, sender, StringParser.shiftArrayBy(args, 1)); - return true; - } - if (args.length > 1 - && (args[1].equalsIgnoreCase("-s") || args[1] - .equalsIgnoreCase("stats"))) { - final PAI_Stats scmd = new PAI_Stats(); - DEBUG.i("committing: " + scmd.getName(), sender); - scmd.commit(ArenaManager.getIndirectArenaByName(sender, args[0]), sender, - StringParser.shiftArrayBy(args, 2)); - return true; - } - if (args[0].equalsIgnoreCase("!rl") - || args[0].toLowerCase().contains("reload")) { - final PAA_Reload scmd = new PAA_Reload(); - DEBUG.i("committing: " + scmd.getName(), sender); - - this.reloadConfig(); - - Language.init(getConfig().getString("language", "en")); - Help.init(getConfig().getString("language", "en")); - - if (args.length > 1 && args[1].equalsIgnoreCase("ymls")) { - Arena.pmsg(sender, Language.parse(MSG.RELOAD_YMLS_DONE)); - return true; - } - - final String[] emptyArray = new String[0]; - - for (Arena a : ArenaManager.getArenas()) { - scmd.commit(a, sender, emptyArray); - } - - ArenaManager.load_arenas(); - if (getConfig().getBoolean("use_shortcuts") || - getConfig().getBoolean("only_shortcuts")) { - ArenaManager.readShortcuts(getConfig().getConfigurationSection("shortcuts")); - } - - return true; - } - Arena tempArena = "l".equalsIgnoreCase(args[0])?player.getArena():ArenaManager.getIndirectArenaByName(sender, args[0]); final String name = args[0]; @@ -413,7 +369,7 @@ public void onDisable() { public void onEnable() { shuttingDown = false; instance = this; - DEBUG = new Debug(1); + debugger = new Debug(1); //Enable bStats Metrics metrics = new Metrics(this); diff --git a/src/net/slipcor/pvparena/commands/AbstractGlobalCommand.java b/src/net/slipcor/pvparena/commands/AbstractGlobalCommand.java index b3bd5e20b..259359d43 100644 --- a/src/net/slipcor/pvparena/commands/AbstractGlobalCommand.java +++ b/src/net/slipcor/pvparena/commands/AbstractGlobalCommand.java @@ -47,6 +47,14 @@ static boolean argCountValid(final CommandSender sender, final String[] args, public abstract String getName(); + /** + * Check if the global command also exists in arena context + * @return true if there is the same command for arena context + */ + public boolean hasVersionForArena() { + return false; + } + @Override public boolean hasPerms(final CommandSender sender, final Arena arena) { // tabComplete check diff --git a/src/net/slipcor/pvparena/commands/PAA_ReloadAll.java b/src/net/slipcor/pvparena/commands/PAA_ReloadAll.java new file mode 100644 index 000000000..3e751d230 --- /dev/null +++ b/src/net/slipcor/pvparena/commands/PAA_ReloadAll.java @@ -0,0 +1,96 @@ +package net.slipcor.pvparena.commands; + +import net.slipcor.pvparena.PVPArena; +import net.slipcor.pvparena.arena.Arena; +import net.slipcor.pvparena.core.Help; +import net.slipcor.pvparena.core.Help.HELP; +import net.slipcor.pvparena.core.Language; +import net.slipcor.pvparena.managers.ArenaManager; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.Collections; +import java.util.List; + +/** + *

PVP Arena DEBUG Command class
+ *

+ * A command to toggle debugging + * + * @author slipcor + * @version v0.10.0 + */ + +public class PAA_ReloadAll extends AbstractGlobalCommand { + + public PAA_ReloadAll() { + super(new String[]{"pvparena.cmds.reload"}); + } + + @Override + public void commit(final CommandSender sender, final String[] args) { + if (!hasPerms(sender)) { + return; + } + + if (!argCountValid(sender, args, new Integer[]{0, 1})) { + return; + } + + final PAA_Reload scmd = new PAA_Reload(); + + PVPArena.instance.reloadConfig(); + + final FileConfiguration config = PVPArena.instance.getConfig(); + Language.init(config.getString("language", "en")); + Help.init(config.getString("language", "en")); + + if (args.length > 1 && args[1].equalsIgnoreCase("ymls")) { + Arena.pmsg(sender, Language.parse(Language.MSG.RELOAD_YMLS_DONE)); + return; + } + + final String[] emptyArray = new String[0]; + + for (Arena a : ArenaManager.getArenas()) { + scmd.commit(a, sender, emptyArray); + } + + ArenaManager.load_arenas(); + if (config.getBoolean("use_shortcuts") || config.getBoolean("only_shortcuts")) { + ArenaManager.readShortcuts(config.getConfigurationSection("shortcuts")); + } + } + + @Override + public boolean hasVersionForArena() { + return true; + } + + @Override + public String getName() { + return getClass().getName(); + } + + @Override + public void displayHelp(final CommandSender sender) { + Arena.pmsg(sender, Help.parse(HELP.DEBUG)); + } + + @Override + public List getMain() { + return Collections.singletonList("reload"); + } + + @Override + public List getShort() { + return Collections.singletonList("!rl"); + } + + @Override + public CommandTree getSubs(final Arena nothing) { + final CommandTree result = new CommandTree<>(null); + result.define(new String[]{"ymls"}); + return result; + } +} diff --git a/src/net/slipcor/pvparena/commands/PAI_ArenaList.java b/src/net/slipcor/pvparena/commands/PAI_ArenaList.java index 2655405ac..fcdd5b628 100644 --- a/src/net/slipcor/pvparena/commands/PAI_ArenaList.java +++ b/src/net/slipcor/pvparena/commands/PAI_ArenaList.java @@ -52,6 +52,11 @@ public void commit(final CommandSender sender, final String[] args) { Arena.pmsg(sender, Language.parse(MSG.ARENA_LIST, StringParser.joinList(names, ", "))); } + @Override + public boolean hasVersionForArena() { + return true; + } + @Override public String getName() { return getClass().getName(); diff --git a/src/net/slipcor/pvparena/commands/PAI_GlobalStats.java b/src/net/slipcor/pvparena/commands/PAI_GlobalStats.java new file mode 100644 index 000000000..f42826180 --- /dev/null +++ b/src/net/slipcor/pvparena/commands/PAI_GlobalStats.java @@ -0,0 +1,73 @@ +package net.slipcor.pvparena.commands; + +import net.slipcor.pvparena.arena.Arena; +import net.slipcor.pvparena.core.Help; +import net.slipcor.pvparena.core.Help.HELP; +import net.slipcor.pvparena.managers.StatisticsManager.Type; +import org.bukkit.command.CommandSender; + +import java.util.Collections; +import java.util.List; + +/** + *

PVP Arena STATS Command class
+ *

+ * A command to display the player statistics + * + * @author slipcor + * @version v0.10.0 + */ + +public class PAI_GlobalStats extends AbstractGlobalCommand { + + public PAI_GlobalStats() { + super(new String[]{"pvparena.user", "pvparena.cmds.stats"}); + } + + @Override + public void commit(final CommandSender sender, final String[] args) { + if (!hasPerms(sender)) { + return; + } + + if (!argCountValid(sender, args, new Integer[]{1})) { + return; + } + + new PAI_Stats().commit(null, sender, args); + } + + @Override + public boolean hasVersionForArena() { + return true; + } + + @Override + public String getName() { + return getClass().getName(); + } + + @Override + public void displayHelp(final CommandSender sender) { + Arena.pmsg(sender, Help.parse(HELP.STATS)); + } + + @Override + public List getMain() { + return Collections.singletonList("stats"); + } + + @Override + public List getShort() { + return Collections.singletonList("-s"); + } + + @Override + public CommandTree getSubs(final Arena arena) { + final CommandTree result = new CommandTree<>(null); + for (final Type val : Type.values()) { + result.define(new String[]{val.name()}); + } + return result; + } +} diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java index 721b575af..09fbccf22 100644 --- a/src/net/slipcor/pvparena/core/Language.java +++ b/src/net/slipcor/pvparena/core/Language.java @@ -184,7 +184,6 @@ public enum MSG { ERROR_NOPERM_C_ENABLE("nulang.nopermto.cmds.enable", "use the enable command"), ERROR_NOPERM_C_GAMEMODE("nulang.nopermto.cmds.gamemode", "use the gamemode command"), ERROR_NOPERM_C_GOAL("nulang.nopermto.cmds.goal", "use the goal command"), - ERROR_NOPERM_C_INSTALL("nulang.nopermto.cmds.install", "use the install command"), ERROR_NOPERM_C_PLAYERCLASS("nulang.nopermto.cmds.playerclass", "use the playerclass command"), ERROR_NOPERM_C_PLAYERJOIN("nulang.nopermto.cmds.playerjoin", "use the playerjoin command"), ERROR_NOPERM_C_PROTECTION("nulang.nopermto.cmds.protection", "use the protection command"), @@ -205,8 +204,7 @@ public enum MSG { ERROR_NOPERM_C_TELEPORT("nulang.nopermto.cmds.teleport", "use the teleport command"), ERROR_NOPERM_C_TEMPLATE("nulang.nopermto.cmds.template", "use the template command"), ERROR_NOPERM_C_TOGGLEMOD("nulang.nopermto.cmds.togglemod", "use the togglemod command"), - ERROR_NOPERM_C_UNINSTALL("nulang.nopermto.cmds.uninstall", "use the uninstall command"), - ERROR_NOPERM_C_UPDATE("nulang.nopermto.cmds.update", "use the update command"), + ERROR_NOPERM_C_MODULES("nulang.nopermto.cmds.uninstall", "use the modules command"), ERROR_NOPERM_C_WHITELIST("nulang.nopermto.cmds.whitelist", "use the whitelist command"), ERROR_NOPERM_C_ARENACLASS("nulang.nopermto.cmds.arenaclass", "use the arenaclass command"), ERROR_NOPERM_C_CHAT("nulang.nopermto.cmds.chat", "use the chat command"), diff --git a/src/net/slipcor/pvparena/managers/TabManager.java b/src/net/slipcor/pvparena/managers/TabManager.java index ae18f7e0b..b2d7dd7be 100644 --- a/src/net/slipcor/pvparena/managers/TabManager.java +++ b/src/net/slipcor/pvparena/managers/TabManager.java @@ -7,7 +7,6 @@ import net.slipcor.pvparena.commands.AbstractArenaCommand; import net.slipcor.pvparena.commands.AbstractGlobalCommand; import net.slipcor.pvparena.commands.CommandTree; -import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.StringParser; import net.slipcor.pvparena.loadables.ArenaRegion; import org.bukkit.Bukkit; @@ -20,6 +19,8 @@ import java.util.*; import java.util.stream.Collectors; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; import static org.bukkit.util.StringUtil.startsWithIgnoreCase; public final class TabManager { @@ -27,23 +28,20 @@ private TabManager() {} public static List getMatches(final CommandSender sender, final List arenaCommands, final List globalCommands, String[] args) { final Set matches = new LinkedHashSet<>(); + final String firstArg = args[0]; Arena arena = null; if (sender instanceof Player) { arena = ArenaPlayer.parsePlayer(sender.getName()).getArena(); } - if (args.length < 1) { - for (final Arena a : ArenaManager.getArenas()) { - matches.add(a.getName()); - } - return new ArrayList<>(matches); - } - if (arena == null) { - // no proper arena yet - arena = ArenaManager.getArenaByExactName(args[0]); + // player is not inside an arena or in edit mode + + arena = ArenaManager.getArenaByExactName(firstArg); + if (arena == null && ArenaManager.getArenas().size() == 1) { - // still no arena, get the only arena! + // still no arena, get the only arena + arena = ArenaManager.getFirst(); // continue with one arg less args = Arrays.copyOfRange(args, 1, args.length); @@ -51,39 +49,36 @@ public static List getMatches(final CommandSender sender, final List turn to catchall args = new String[]{""}; } + } else if (arena != null) { - // arena has been found + // first argument matches with an arena + if (args.length < 2) { // return the exact arena name - matches.add(arena.getName()); - return new ArrayList<>(matches); + return singletonList(arena.getName()); } else { - // we have more args! + // if more args, we remove the first one (arena name) args = Arrays.copyOfRange(args, 1, args.length); if (args.length < 1) { // empty -> turn to catchall args = new String[]{""}; } } - } else { - // arena has still not been found - if (args.length > 1) { - // the sender has already entered the next thing without a valid arena - sender.sendMessage(Language.parse(Language.MSG.ERROR_ARENA_NOTFOUND, args[0])); - return new ArrayList<>(matches); - } + } else if(args.length == 1) { + // else, if only one arg, suggest arena names and global commands - final String search = args[0]; - return ArenaManager.getArenas().stream() - .filter(a -> startsWithIgnoreCase(a.getName(), search)) + matches.addAll(ArenaManager.getArenas().stream() + .filter(a -> startsWithIgnoreCase(a.getName(), firstArg)) .map(Arena::getName) - .collect(Collectors.toList()); + .collect(Collectors.toList())); + + addCommandsStartingWithPrefix(matches, sender, arena, globalCommands, firstArg); + return new ArrayList<>(matches); } } if (args.length == 1) { addCommandsStartingWithPrefix(matches, sender, arena, arenaCommands, args[0]); - addCommandsStartingWithPrefix(matches, sender, arena, globalCommands, args[0]); if (arena == null) { addCommandsStartingWithPrefix(matches, sender, null, PVPArena.instance.getAgm().getAllGoals(), args[0]); @@ -122,14 +117,17 @@ public static List getMatches(final CommandSender sender, final List matches, final CommandSender sender, final Arena arena, final List list, final String prefix) { for (final IArenaCommandHandler ach : list) { if (ach.hasPerms(sender, arena)) { - for (final String value : ach.getMain()) { - if (startsWithIgnoreCase(value, prefix)) { - matches.add(value); + if(prefix.startsWith("!") || prefix.startsWith("-")) { + for (final String value : ach.getShort()) { + if (startsWithIgnoreCase(value, prefix)) { + matches.add(value); + } } - } - for (final String value : ach.getShort()) { - if (startsWithIgnoreCase(value, prefix)) { - matches.add(value); + } else { + for (final String value : ach.getMain()) { + if (startsWithIgnoreCase(value, prefix)) { + matches.add(value); + } } } } @@ -231,7 +229,7 @@ private static List getKeyMatchesInsideDefinition(final String key, fina if (definition.startsWith("{")) { if ("{Material}".equals(definition)) { final Material[] mats = Material.values(); - addEnumMatchesToList(result, key, Arrays.asList(mats)); + addEnumMatchesToList(result, key, asList(mats)); } else if ("{Player}".equals(definition)) { final Collection players = Bukkit.getOnlinePlayers(); if (key != null && key.isEmpty()) { @@ -247,13 +245,13 @@ private static List getKeyMatchesInsideDefinition(final String key, fina } } else if ("{RegionProtection}".equals(definition)) { final ArenaRegion.RegionProtection[] protections = ArenaRegion.RegionProtection.values(); - addEnumMatchesToList(result, key, Arrays.asList(protections)); + addEnumMatchesToList(result, key, asList(protections)); } else if ("{RegionFlag}".equals(definition)) { final ArenaRegion.RegionFlag[] flags = ArenaRegion.RegionFlag.values(); - addEnumMatchesToList(result, key, Arrays.asList(flags)); + addEnumMatchesToList(result, key, asList(flags)); } else if ("{RegionType}".equals(definition)) { final ArenaRegion.RegionType[] types = ArenaRegion.RegionType.values(); - addEnumMatchesToList(result, key, Arrays.asList(types)); + addEnumMatchesToList(result, key, asList(types)); } else if ("{Boolean}".equals(definition)) { final List values = new ArrayList<>(); values.addAll(StringParser.negative); @@ -282,7 +280,7 @@ private static List getKeyMatchesInsideDefinition(final String key, fina } } else if ("{EntityType}".equals(definition)) { final EntityType[] entityTypes = EntityType.values(); - addEnumMatchesToList(result, key, Arrays.asList(entityTypes)); + addEnumMatchesToList(result, key, asList(entityTypes)); } } return result; @@ -299,7 +297,7 @@ private static String getOverrideFromDefinition(final String key, final String d if (definition.startsWith("{")) { if ("{Material}".equals(definition)) { final Material[] mats = Material.values(); - return getOverrideKey(key, definition, Arrays.asList(mats)); + return getOverrideKey(key, definition, asList(mats)); } else if ("{String}".equals(definition)) { return definition; } else if ("{Player}".equals(definition)) { @@ -312,13 +310,13 @@ private static String getOverrideFromDefinition(final String key, final String d return key; } else if ("{RegionProtection}".equals(definition)) { final ArenaRegion.RegionProtection[] protections = ArenaRegion.RegionProtection.values(); - return getOverrideKey(key, definition, Arrays.asList(protections)); + return getOverrideKey(key, definition, asList(protections)); } else if ("{RegionFlag}".equals(definition)) { final ArenaRegion.RegionFlag[] flags = ArenaRegion.RegionFlag.values(); - return getOverrideKey(key, definition, Arrays.asList(flags)); + return getOverrideKey(key, definition, asList(flags)); } else if ("{RegionType}".equals(definition)) { final ArenaRegion.RegionType[] types = ArenaRegion.RegionType.values(); - return getOverrideKey(key, definition, Arrays.asList(types)); + return getOverrideKey(key, definition, asList(types)); } else if ("{Boolean}".equals(definition)) { final List values = new ArrayList<>(); values.addAll(StringParser.negative); @@ -347,7 +345,7 @@ private static String getOverrideFromDefinition(final String key, final String d return key; } else if ("{EntityType}".equals(definition)) { final EntityType[] entityTypes = EntityType.values(); - return getOverrideKey(key, definition, Arrays.asList(entityTypes)); + return getOverrideKey(key, definition, asList(entityTypes)); } } return key; From 932293e62c01b8b2d03f49f8dc9bf09334b6bb0d Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 9 Jul 2020 22:28:17 +0200 Subject: [PATCH 073/115] v1.15 - kick players if going out of lounge regions - issue #48 --- src/net/slipcor/pvparena/arena/Arena.java | 2 +- .../pvparena/loadables/ArenaRegion.java | 26 +++++++++---------- .../pvparena/runnables/RegionRunnable.java | 9 ++++--- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java index fb7b9a24d..b039047a5 100644 --- a/src/net/slipcor/pvparena/arena/Arena.java +++ b/src/net/slipcor/pvparena/arena/Arena.java @@ -225,7 +225,7 @@ public void addRegion(final ArenaRegion region) { if (cfg.getBoolean(CFG.JOIN_FORCE)) { region.initTimer(); } - } else if (region.getType() == RegionType.WATCH) { + } else if (region.getType() == RegionType.WATCH || region.getType() == RegionType.LOUNGE) { region.initTimer(); } } diff --git a/src/net/slipcor/pvparena/loadables/ArenaRegion.java b/src/net/slipcor/pvparena/loadables/ArenaRegion.java index aa62de5aa..8aa4a4812 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaRegion.java +++ b/src/net/slipcor/pvparena/loadables/ArenaRegion.java @@ -29,9 +29,12 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.scheduler.BukkitTask; import java.util.*; +import static java.util.Arrays.asList; + public class ArenaRegion { private static final Debug debug = new Debug(34); @@ -39,7 +42,7 @@ public class ArenaRegion { private Arena arena; private String name; private RegionType type; - private int tickID = -1; + private BukkitTask runningTask; private final Set flags = new HashSet<>(); private final Set protections = new HashSet<>(); private final Map playerLocations = new HashMap<>(); @@ -367,19 +370,15 @@ public String getWorldName() { public void initTimer() { - if (tickID != -1) { - if (type == RegionType.JOIN || type == RegionType.WATCH) { - return; + if (this.runningTask != null && !this.runningTask.isCancelled()) { + if (!asList(RegionType.JOIN, RegionType.WATCH, RegionType.LOUNGE).contains(this.type)) { + this.runningTask.cancel(); } - - Bukkit.getScheduler().cancelTask(tickID); } final RegionRunnable regionRunner = new RegionRunnable(this); - tickID = Bukkit.getScheduler().scheduleSyncRepeatingTask( - PVPArena.instance, regionRunner, - (long) arena.getArenaConfig().getInt(CFG.TIME_REGIONTIMER), - (long) arena.getArenaConfig().getInt(CFG.TIME_REGIONTIMER)); + final int timer = this.arena.getArenaConfig().getInt(CFG.TIME_REGIONTIMER); + this.runningTask = regionRunner.runTaskTimer(PVPArena.instance, timer, timer); } public boolean isInNoWoolSet(final Block block) { @@ -446,7 +445,7 @@ public void reset() { } public void removeEntities() { - if (getWorld() == null || getWorld().getEntities() == null) { + if (getWorld() == null || getWorld().getEntities().isEmpty()) { return; } @@ -473,8 +472,9 @@ public void removeEntities() { return; } - Bukkit.getScheduler().cancelTask(tickID); - tickID = -1; + if(this.runningTask != null && !this.runningTask.isCancelled()) { + this.runningTask.cancel(); + } } public void saveToConfig() { diff --git a/src/net/slipcor/pvparena/runnables/RegionRunnable.java b/src/net/slipcor/pvparena/runnables/RegionRunnable.java index 974ab5b87..bfa68603d 100644 --- a/src/net/slipcor/pvparena/runnables/RegionRunnable.java +++ b/src/net/slipcor/pvparena/runnables/RegionRunnable.java @@ -3,6 +3,9 @@ import net.slipcor.pvparena.PVPArena; import net.slipcor.pvparena.loadables.ArenaRegion; import net.slipcor.pvparena.loadables.ArenaRegion.RegionType; +import org.bukkit.scheduler.BukkitRunnable; + +import static java.util.Arrays.asList; /** *

@@ -15,7 +18,7 @@
  * @version v0.9.9
  */
 
-public class RegionRunnable implements Runnable {
+public class RegionRunnable extends BukkitRunnable {
     private final ArenaRegion region;
 //	private final static Debug DEBUG = new Debug(49);
 //	private int iID;
@@ -74,8 +77,8 @@ public void run() {
                 region.getArena().getDebugger().i("tick 2: " + region.getRegionName());
                 region.tick();
             }
-        } else if (region.getType() == RegionType.WATCH) {
-            // always tick for WATCH regions!
+        } else if (asList(RegionType.WATCH, RegionType.LOUNGE).contains(region.getType())) {
+            // always tick for WATCH & LOUNGE regions!
             region.getArena().getDebugger().i("tick 3: " + region.getRegionName());
             region.tick();
         } else if (region.getArena().isFightInProgress()) {

From f06901fca6cce90e546da50df9c680350b82ec22 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 20 Jul 2020 21:14:05 +0200
Subject: [PATCH 074/115] v1.15 - fix NPE caused by spectators of infected
 arenas - issue #51

---
 .../slipcor/pvparena/goals/GoalInfect.java    | 300 +++++++++---------
 1 file changed, 145 insertions(+), 155 deletions(-)

diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java
index 1479994d4..8284f4d8f 100644
--- a/src/net/slipcor/pvparena/goals/GoalInfect.java
+++ b/src/net/slipcor/pvparena/goals/GoalInfect.java
@@ -52,7 +52,7 @@
 public class GoalInfect extends ArenaGoal {
     public GoalInfect() {
         super("Infect");
-        debug = new Debug(108);
+        this.debug = new Debug(108);
     }
 // BREAK, PLACE, TNT, TNTBREAK, DROP, INVENTORY, PICKUP, CRAFT;
     private EndRunnable endRunner;
@@ -70,10 +70,10 @@ public PACheck checkEnd(final PACheck res) {
             return res;
         }
 
-        final int count = getLifeMap().size();
+        final int count = this.getLifeMap().size();
 
         if (count <= 1
-                || anyTeamEmpty()) {
+                || this.anyTeamEmpty()) {
             res.setPriority(this, PRIORITY); // yep. only one player left. go!
         }
         if (count == 0) {
@@ -84,17 +84,18 @@ public PACheck checkEnd(final PACheck res) {
     }
 
     private boolean anyTeamEmpty() {
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             boolean bbreak = false;
             for (final ArenaPlayer player : team.getTeamMembers()) {
                 if (player.getStatus() == Status.FIGHT) {
                     bbreak = true;
+                    break;
                 }
             }
             if (bbreak) {
                 continue;
             }
-            arena.getDebugger().i("team empty: " + team.getName());
+            this.arena.getDebugger().i("team empty: " + team.getName());
             return true;
         }
         return false;
@@ -102,7 +103,7 @@ private boolean anyTeamEmpty() {
 
     @Override
     public String checkForMissingSpawns(final Set list) {
-        if (!arena.isFreeForAll()) {
+        if (!this.arena.isFreeForAll()) {
             return null; // teams are handled somewhere else
         }
 
@@ -139,7 +140,7 @@ public PACheck checkCommand(final PACheck res, final String string) {
     @Override
     public PACheck checkBreak(PACheck result, Arena arena, BlockBreakEvent event) {
         ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getPlayer().getName());
-        if (arena.equals(ap.getArena())) {
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.BREAK
@@ -163,13 +164,13 @@ public PACheck checkBreak(PACheck result, Arena arena, BlockBreakEvent event) {
     @Override
     public PACheck checkCraft(PACheck result, Arena arena, CraftItemEvent event) {
         ArenaPlayer ap = ArenaPlayer.parsePlayer(((Player) event.getInventory().getHolder()).getName());
-        if (arena.equals(ap.getArena())) {
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.CRAFT
                 )) {
                     event.setCancelled(true);
-                    arena.msg((Player) event.getWhoClicked(), Language.parse(arena, MSG.PLAYER_PREVENTED_CRAFT));
+                    arena.msg(event.getWhoClicked(), Language.parse(arena, MSG.PLAYER_PREVENTED_CRAFT));
                     result.setError(this, "CRAFT not allowed");
                 }
             }
@@ -180,7 +181,7 @@ public PACheck checkCraft(PACheck result, Arena arena, CraftItemEvent event) {
     @Override
     public PACheck checkDrop(PACheck result, Arena arena, PlayerDropItemEvent event) {
         ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getPlayer().getName());
-        if (arena.equals(ap.getArena())) {
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.DROP
@@ -196,15 +197,15 @@ public PACheck checkDrop(PACheck result, Arena arena, PlayerDropItemEvent event)
 
     @Override
     public PACheck checkInventory(PACheck result, Arena arena, InventoryClickEvent event) {
-        ArenaPlayer ap = ArenaPlayer.parsePlayer(((Player) event.getWhoClicked()).getName());
-        if (arena.equals(ap.getArena())) {
+        ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getWhoClicked().getName());
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.INVENTORY
                 )) {
                     event.setCancelled(true);
                     event.getWhoClicked().closeInventory();
-                    arena.msg((Player) event.getWhoClicked(), Language.parse(arena, MSG.PLAYER_PREVENTED_INVENTORY));
+                    arena.msg(event.getWhoClicked(), Language.parse(arena, MSG.PLAYER_PREVENTED_INVENTORY));
                     result.setError(this, "INVENTORY not allowed");
                 }
             }
@@ -215,7 +216,7 @@ public PACheck checkInventory(PACheck result, Arena arena, InventoryClickEvent e
     @Override
     public PACheck checkPickup(PACheck result, Arena arena, EntityPickupItemEvent event) {
         ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getEntity().getName());
-        if (arena.equals(ap.getArena())) {
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.PICKUP
@@ -231,7 +232,7 @@ public PACheck checkPickup(PACheck result, Arena arena, EntityPickupItemEvent ev
     @Override
     public PACheck checkPlace(PACheck result, Arena arena, BlockPlaceEvent event) {
         ArenaPlayer ap = ArenaPlayer.parsePlayer(event.getPlayer().getName());
-        if (arena.equals(ap.getArena())) {
+        if (arena.equals(ap.getArena()) && ap.getStatus() == Status.FIGHT) {
             if ("infected".equals(ap.getArenaTeam().getName())) {
                 if (ArenaPlayer.PlayerPrevention.has(
                         arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS), ArenaPlayer.PlayerPrevention.PLACE
@@ -258,12 +259,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
-        final int maxTeamPlayers = arena.getArenaConfig().getInt(
+        final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
+        final int maxTeamPlayers = this.arena.getArenaConfig().getInt(
                 CFG.READY_MAXTEAMPLAYERS);
 
-        if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) {
-            res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL));
+        if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) {
+            res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL));
             return res;
         }
 
@@ -271,12 +272,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        if (!arena.isFreeForAll()) {
-            final ArenaTeam team = arena.getTeam(args[0]);
+        if (!this.arena.isFreeForAll()) {
+            final ArenaTeam team = this.arena.getTeam(args[0]);
 
             if (team != null && maxTeamPlayers > 0
                     && team.getTeamMembers().size() >= maxTeamPlayers) {
-                res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
+                res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
                 return res;
             }
         }
@@ -290,11 +291,11 @@ public PACheck checkPlayerDeath(final PACheck res, final Player player) {
         if (res.getPriority() <= PRIORITY) {
             res.setPriority(this, PRIORITY);
 
-            if (!getLifeMap().containsKey(player.getName())) {
+            if (!this.getLifeMap().containsKey(player.getName())) {
                 return res;
             }
-            final int iLives = getLifeMap().get(player.getName());
-            arena.getDebugger().i("lives before death: " + iLives, player);
+            final int iLives = this.getLifeMap().get(player.getName());
+            this.arena.getDebugger().i("lives before death: " + iLives, player);
             if (iLives <= 1 && "infected".equals(ArenaPlayer.parsePlayer(player.getName()).getArenaTeam().getName())) {
                 res.setError(this, "0");
             }
@@ -314,7 +315,7 @@ public PACheck checkStart(final PACheck res) {
     @Override
     public void commitCommand(final CommandSender sender, final String[] args) {
 
-        int value = arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS);
+        int value = this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_PPROTECTS);
 
         if ("getprotect".equalsIgnoreCase(args[0])) {
             List values = new ArrayList<>();
@@ -327,14 +328,14 @@ public void commitCommand(final CommandSender sender, final String[] args) {
                 values.add((ArenaPlayer.PlayerPrevention.has(value, pp) ?
                         ChatColor.GREEN.toString() : ChatColor.RED.toString()) + pp.name());
             }
-            arena.msg(sender, Language.parse(arena, MSG.GOAL_INFECTED_IPROTECT, StringParser.joinList(values, (ChatColor.WHITE + ", "))));
+            this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_INFECTED_IPROTECT, StringParser.joinList(values, (ChatColor.WHITE + ", "))));
 
         } else if ("setprotect".equalsIgnoreCase(args[0])) {
             // setprotect [value] {true|false}
             if (args.length < 2) {
-                arena.msg(
+                this.arena.msg(
                         sender,
-                        Language.parse(arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
+                        Language.parse(this.arena, MSG.ERROR_INVALID_ARGUMENT_COUNT,
                                 String.valueOf(args.length), "2|3"));
                 return;
             }
@@ -343,9 +344,9 @@ public void commitCommand(final CommandSender sender, final String[] args) {
                 final ArenaPlayer.PlayerPrevention pp = ArenaPlayer.PlayerPrevention.valueOf(args[1].toUpperCase());
                 final boolean has = ArenaPlayer.PlayerPrevention.has(value, pp);
 
-                arena.getDebugger().i("plain value: " + value);
-                arena.getDebugger().i("checked: " + pp.name());
-                arena.getDebugger().i("has: " + String.valueOf(has));
+                this.arena.getDebugger().i("plain value: " + value);
+                this.arena.getDebugger().i("checked: " + pp.name());
+                this.arena.getDebugger().i("has: " + has);
 
                 boolean future = !has;
 
@@ -359,18 +360,18 @@ public void commitCommand(final CommandSender sender, final String[] args) {
 
                 if (future) {
                     value = value | (int) Math.pow(2, pp.ordinal());
-                    arena.msg(
+                    this.arena.msg(
                             sender,
-                            Language.parse(arena, MSG.GOAL_INFECTED_IPROTECT_SET,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_IPROTECT_SET,
                                     pp.name(), ChatColor.GREEN + "true") + ChatColor.YELLOW);
                 } else {
                     value = value ^ (int) Math.pow(2, pp.ordinal());
-                    arena.msg(
+                    this.arena.msg(
                             sender,
-                            Language.parse(arena, MSG.GOAL_INFECTED_IPROTECT_SET,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_IPROTECT_SET,
                                     pp.name(), ChatColor.RED + "false") + ChatColor.YELLOW);
                 }
-                arena.getArenaConfig().set(CFG.GOAL_INFECTED_PPROTECTS, value);
+                this.arena.getArenaConfig().set(CFG.GOAL_INFECTED_PPROTECTS, value);
             } catch (final Exception e) {
                 List values = new ArrayList<>();
 
@@ -378,159 +379,157 @@ public void commitCommand(final CommandSender sender, final String[] args) {
                 for (ArenaPlayer.PlayerPrevention pp : ArenaPlayer.PlayerPrevention.values()) {
                     values.add(pp.name());
                 }
-                arena.msg(sender,
-                        Language.parse(arena, MSG.ERROR_ARGUMENT, args[1], StringParser.joinList(values, ", ")));
+                this.arena.msg(sender,
+                        Language.parse(this.arena, MSG.ERROR_ARGUMENT, args[1], StringParser.joinList(values, ", ")));
                 return;
             }
-            arena.getArenaConfig().save();
+            this.arena.getArenaConfig().save();
 
         }
     }
 
     @Override
     public void commitEnd(final boolean force) {
-        if (endRunner != null) {
+        if (this.endRunner != null) {
             return;
         }
-        if (arena.realEndRunner != null) {
-            arena.getDebugger().i("[INFECT] already ending");
+        if (this.arena.realEndRunner != null) {
+            this.arena.getDebugger().i("[INFECT] already ending");
             return;
         }
-        final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "");
+        final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "");
         Bukkit.getPluginManager().callEvent(gEvent);
 
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             for (final ArenaPlayer ap : team.getTeamMembers()) {
                 if (ap.getStatus() != Status.FIGHT) {
                     continue;
                 }
                 if ("infected".equals(ap.getArenaTeam().getName())) {
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.GOAL_INFECTED_WON), "END");
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_WON), "END");
 
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.GOAL_INFECTED_WON), "WINNER");
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_WON), "WINNER");
 
-                    arena.broadcast(Language.parse(arena, MSG.GOAL_INFECTED_WON));
+                    this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_INFECTED_WON));
                     break;
                 } else {
 
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.GOAL_INFECTED_LOST), "END");
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_LOST), "END");
                     // String tank = tanks.get(arena);
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.GOAL_INFECTED_LOST), "LOSER");
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.GOAL_INFECTED_LOST), "LOSER");
 
-                    arena.broadcast(Language.parse(arena, MSG.GOAL_INFECTED_LOST));
+                    this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_INFECTED_LOST));
                     break;
                 }
             }
 
-            if (ArenaModuleManager.commitEnd(arena, team)) {
+            if (ArenaModuleManager.commitEnd(this.arena, team)) {
                 return;
             }
         }
 
-        endRunner = new EndRunnable(arena, arena.getArenaConfig().getInt(
+        this.endRunner = new EndRunnable(this.arena, this.arena.getArenaConfig().getInt(
                 CFG.TIME_ENDCOUNTDOWN));
     }
 
     @Override
     public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                                   final String error, final PlayerDeathEvent event) {
-        if (!getLifeMap().containsKey(player.getName())) {
+        if (!this.getLifeMap().containsKey(player.getName())) {
             return;
         }
-        int iLives = getLifeMap().get(player.getName());
-        arena.getDebugger().i("lives before death: " + iLives, player);
-        if (iLives <= 1 || "infected".equals(ArenaPlayer.parsePlayer(player.getName()).getArenaTeam().getName())) {
-            if (iLives <= 1 && "infected".equals(ArenaPlayer.parsePlayer(player.getName()).getArenaTeam().getName())) {
+        int iLives = this.getLifeMap().get(player.getName());
+        this.arena.getDebugger().i("lives before death: " + iLives, player);
+        ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
+        if (iLives <= 1 || "infected".equals(aPlayer.getArenaTeam().getName())) {
+            if (iLives <= 1 && "infected".equals(aPlayer.getArenaTeam().getName())) {
 
-                final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "infected", "playerDeath:" + player.getName());
+                final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "infected", "playerDeath:" + player.getName());
                 Bukkit.getPluginManager().callEvent(gEvent);
-                ArenaPlayer.parsePlayer(player.getName()).setStatus(Status.LOST);
+                aPlayer.setStatus(Status.LOST);
                 // kill, remove!
-                getLifeMap().remove(player.getName());
-                if (arena.getArenaConfig().getBoolean(CFG.PLAYER_PREVENTDEATH)) {
-                    arena.getDebugger().i("faking player death", player);
-                    PlayerListener.finallyKillPlayer(arena, player, event);
+                this.getLifeMap().remove(player.getName());
+                if (this.arena.getArenaConfig().getBoolean(CFG.PLAYER_PREVENTDEATH)) {
+                    this.arena.getDebugger().i("faking player death", player);
+                    PlayerListener.finallyKillPlayer(this.arena, player, event);
                 }
                 return;
             }
             if (iLives <= 1) {
-                PAGoalEvent gEvent = new PAGoalEvent(arena, this, "playerDeath:" + player.getName());
+                PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "playerDeath:" + player.getName());
                 Bukkit.getPluginManager().callEvent(gEvent);
                 // dying player -> infected
-                getLifeMap().put(player.getName(), arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
-                arena.msg(player, Language.parse(arena, MSG.GOAL_INFECTED_YOU));
-                arena.broadcast(Language.parse(arena, MSG.GOAL_INFECTED_PLAYER, player.getName()));
-
-                ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
+                this.getLifeMap().put(player.getName(), this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
+                this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_INFECTED_YOU));
+                this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_INFECTED_PLAYER, player.getName()));
 
                 final ArenaTeam oldTeam = aPlayer.getArenaTeam();
-                final ArenaTeam respawnTeam = arena.getTeam("infected");
+                final ArenaTeam respawnTeam = this.arena.getTeam("infected");
 
-                PATeamChangeEvent tcEvent = new PATeamChangeEvent(arena, player, oldTeam, respawnTeam);
+                PATeamChangeEvent tcEvent = new PATeamChangeEvent(this.arena, player, oldTeam, respawnTeam);
                 Bukkit.getPluginManager().callEvent(tcEvent);
-                arena.updateScoreboardTeam(player, oldTeam, respawnTeam);
+                this.arena.updateScoreboardTeam(player, oldTeam, respawnTeam);
 
                 oldTeam.remove(aPlayer);
 
                 respawnTeam.add(aPlayer);
 
-                final ArenaClass infectedClass = arena.getClass("%infected%");
+                final ArenaClass infectedClass = this.arena.getClass("%infected%");
                 if (infectedClass != null) {
                     aPlayer.setArenaClass(infectedClass);
                 }
 
-                if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                    arena.broadcast(Language.parse(arena,
+                if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                    this.arena.broadcast(Language.parse(this.arena,
                             MSG.FIGHT_KILLED_BY,
                             respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                            arena.parseDeathCause(player, event.getEntity()
+                            this.arena.parseDeathCause(player, event.getEntity()
                                             .getLastDamageCause().getCause(),
                                     player.getKiller()), String.valueOf(iLives)));
                 }
 
                 final List returned;
 
-                if (arena.getArenaConfig().getBoolean(
+                if (this.arena.getArenaConfig().getBoolean(
                         CFG.PLAYER_DROPSINVENTORY)) {
                     returned = InventoryManager.drop(player);
                     event.getDrops().clear();
                 } else {
-                    returned = new ArrayList<>();
-                    returned.addAll(event.getDrops());
+                    returned = new ArrayList<>(event.getDrops());
                 }
 
-                PACheck.handleRespawn(arena,
-                        ArenaPlayer.parsePlayer(player.getName()), returned);
+                PACheck.handleRespawn(this.arena,
+                        aPlayer, returned);
 
-                if (anyTeamEmpty()) {
-                    PACheck.handleEnd(arena, false);
+                if (this.anyTeamEmpty()) {
+                    PACheck.handleEnd(this.arena, false);
                 }
                 return;
             }
             // dying infected player, has lives remaining
-            PAGoalEvent gEvent = new PAGoalEvent(arena, this, "infected", "doesRespawn", "playerDeath:" + player.getName());
+            PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "infected", "doesRespawn", "playerDeath:" + player.getName());
             Bukkit.getPluginManager().callEvent(gEvent);
             iLives--;
-            getLifeMap().put(player.getName(), iLives);
+            this.getLifeMap().put(player.getName(), iLives);
 
-            final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
+            final ArenaTeam respawnTeam = aPlayer
                     .getArenaTeam();
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                arena.broadcast(Language.parse(arena,
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                this.arena.broadcast(Language.parse(this.arena,
                         MSG.FIGHT_KILLED_BY_REMAINING,
                         respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, event.getEntity()
+                        this.arena.parseDeathCause(player, event.getEntity()
                                         .getLastDamageCause().getCause(),
                                 player.getKiller()), String.valueOf(iLives)));
             }
 
             final List returned;
 
-            if (arena.getArenaConfig().getBoolean(
+            if (this.arena.getArenaConfig().getBoolean(
                     CFG.PLAYER_DROPSINVENTORY)) {
                 returned = InventoryManager.drop(player);
                 event.getDrops().clear();
@@ -539,57 +538,56 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                 returned.addAll(event.getDrops());
             }
 
-            PACheck.handleRespawn(arena,
-                    ArenaPlayer.parsePlayer(player.getName()), returned);
+            PACheck.handleRespawn(this.arena,
+                    aPlayer, returned);
 
 
             // player died => commit death!
-            PACheck.handleEnd(arena, false);
+            PACheck.handleEnd(this.arena, false);
         } else {
             iLives--;
-            getLifeMap().put(player.getName(), iLives);
+            this.getLifeMap().put(player.getName(), iLives);
 
-            final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
+            final ArenaTeam respawnTeam = aPlayer
                     .getArenaTeam();
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                arena.broadcast(Language.parse(arena,
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                this.arena.broadcast(Language.parse(this.arena,
                         MSG.FIGHT_KILLED_BY_REMAINING,
                         respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, event.getEntity()
+                        this.arena.parseDeathCause(player, event.getEntity()
                                         .getLastDamageCause().getCause(),
                                 player.getKiller()), String.valueOf(iLives)));
             }
 
             final List returned;
 
-            if (arena.getArenaConfig().getBoolean(
+            if (this.arena.getArenaConfig().getBoolean(
                     CFG.PLAYER_DROPSINVENTORY)) {
                 returned = InventoryManager.drop(player);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
-            PACheck.handleRespawn(arena,
-                    ArenaPlayer.parsePlayer(player.getName()), returned);
+            PACheck.handleRespawn(this.arena,
+                    aPlayer, returned);
         }
     }
 
     @Override
     public void commitStart() {
-        parseStart(); // hack the team in before spawning, derp!
-        for (final ArenaTeam team : arena.getTeams()) {
-            SpawnManager.distribute(arena, team);
+        this.parseStart(); // hack the team in before spawning, derp!
+        for (final ArenaTeam team : this.arena.getTeams()) {
+            SpawnManager.distribute(this.arena, team);
         }
     }
 
     @Override
     public void displayInfo(final CommandSender sender) {
         sender.sendMessage("normal lives: "
-                + arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES) + " || " +
+                + this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES) + " || " +
                 "infected lives: "
-                + arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
+                + this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
     }
 
     @Override
@@ -602,7 +600,7 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
         if (res.getPriority() <= PRIORITY + 1000) {
             res.setError(
                     this,
-                    String.valueOf(getLifeMap().getOrDefault(aPlayer.getName(), 0))
+                    String.valueOf(this.getLifeMap().getOrDefault(aPlayer.getName(), 0))
             );
         }
         return res;
@@ -612,8 +610,8 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
     public boolean hasSpawn(final String string) {
 
 
-        if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-            for (final ArenaClass aClass : arena.getClasses()) {
+        if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+            for (final ArenaClass aClass : this.arena.getClasses()) {
                 if (string.toLowerCase().startsWith(
                         aClass.getName().toLowerCase() + "spawn")) {
                     return true;
@@ -621,13 +619,13 @@ public boolean hasSpawn(final String string) {
             }
         }
 
-        return arena.isFreeForAll() && string.toLowerCase()
+        return this.arena.isFreeForAll() && string.toLowerCase()
                 .startsWith("spawn") || string.toLowerCase().startsWith("infected");
     }
 
     @Override
     public void initate(final Player player) {
-        updateLives(player, arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES));
+        this.updateLives(player, this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES));
     }
 
     @Override
@@ -639,63 +637,60 @@ public boolean isInternal() {
     public void parseLeave(final Player player) {
         if (player == null) {
             PVPArena.instance.getLogger().warning(
-                    getName() + ": player NULL");
+                    this.getName() + ": player NULL");
             return;
         }
-        if (getLifeMap().containsKey(player.getName())) {
-            getLifeMap().remove(player.getName());
-        }
+        this.getLifeMap().remove(player.getName());
     }
 
     @Override
     public void parseStart() {
-        if (arena.getTeam("infected") != null) {
+        if (this.arena.getTeam("infected") != null) {
             return;
         }
         ArenaPlayer infected = null;
         final Random random = new Random();
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             int pos = random.nextInt(team.getTeamMembers().size());
-            arena.getDebugger().i("team " + team.getName() + " random " + pos);
+            this.arena.getDebugger().i("team " + team.getName() + " random " + pos);
             for (final ArenaPlayer ap : team.getTeamMembers()) {
-                arena.getDebugger().i("#" + pos + ": " + ap, ap.getName());
-                getLifeMap().put(ap.getName(),
-                        arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES));
+                this.arena.getDebugger().i("#" + pos + ": " + ap, ap.getName());
+                this.getLifeMap().put(ap.getName(),
+                        this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_NLIVES));
                 if (pos-- == 0) {
                     infected = ap;
-                    getLifeMap().put(ap.getName(),
-                            arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
+                    this.getLifeMap().put(ap.getName(),
+                            this.arena.getArenaConfig().getInt(CFG.GOAL_INFECTED_ILIVES));
                 }
                 //break;
             }
         }
         final ArenaTeam infectedTeam = new ArenaTeam("infected", "PINK");
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             if (team.getTeamMembers().contains(infected)) {
-                final PATeamChangeEvent tcEvent = new PATeamChangeEvent(arena, infected.get(), team, infectedTeam);
+                final PATeamChangeEvent tcEvent = new PATeamChangeEvent(this.arena, infected.get(), team, infectedTeam);
                 Bukkit.getPluginManager().callEvent(tcEvent);
-                arena.updateScoreboardTeam(infected.get(), team, infectedTeam);
+                this.arena.updateScoreboardTeam(infected.get(), team, infectedTeam);
                 team.remove(infected);
             }
         }
         infectedTeam.add(infected);
 
-        final ArenaClass infectedClass = arena.getClass("%infected%");
+        final ArenaClass infectedClass = this.arena.getClass("%infected%");
         if (infectedClass != null) {
             infected.setArenaClass(infectedClass);
             InventoryManager.clearInventory(infected.get());
             infectedClass.equip(infected.get());
-            for (final ArenaModule mod : arena.getMods()) {
+            for (final ArenaModule mod : this.arena.getMods()) {
                 mod.parseRespawn(infected.get(), infectedTeam, DamageCause.CUSTOM,
                         infected.get());
             }
         }
 
-        arena.msg(infected.get(), Language.parse(arena, MSG.GOAL_INFECTED_YOU, infected.getName()));
-        arena.broadcast(Language.parse(arena, MSG.GOAL_INFECTED_PLAYER, infected.getName()));
+        this.arena.msg(infected.get(), Language.parse(this.arena, MSG.GOAL_INFECTED_YOU, infected.getName()));
+        this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_INFECTED_PLAYER, infected.getName()));
 
-        final Set spawns = new HashSet<>();
-        spawns.addAll(SpawnManager.getPASpawnsStartingWith(arena, "infected"));
+        final Set spawns = new HashSet<>(SpawnManager.getPASpawnsStartingWith(this.arena, "infected"));
 
         int pos = spawns.size();
 
@@ -705,42 +700,37 @@ public void parseStart() {
                 break;
             }
         }
-        arena.getTeams().add(infectedTeam);
+        this.arena.getTeams().add(infectedTeam);
     }
 
     @Override
     public void reset(final boolean force) {
-        endRunner = null;
-        getLifeMap().clear();
-        arena.getTeams().remove(arena.getTeam("infected"));
+        this.endRunner = null;
+        this.getLifeMap().clear();
+        this.arena.getTeams().remove(this.arena.getTeam("infected"));
     }
 
     @Override
     public void setPlayerLives(final int value) {
-        final Set plrs = new HashSet<>();
-
-        for (final String name : getLifeMap().keySet()) {
-            plrs.add(name);
-        }
+        final Set plrs = new HashSet<>(this.getLifeMap().keySet());
 
         for (final String s : plrs) {
-            getLifeMap().put(s, value);
+            this.getLifeMap().put(s, value);
         }
     }
 
     @Override
     public void setPlayerLives(final ArenaPlayer aPlayer, final int value) {
-        getLifeMap().put(aPlayer.getName(), value);
+        this.getLifeMap().put(aPlayer.getName(), value);
     }
 
     @Override
     public Map timedEnd(final Map scores) {
 
-        for (final ArenaPlayer ap : arena.getFighters()) {
-            double score = getLifeMap().containsKey(ap.getName()) ? getLifeMap().get(ap.getName())
-                    : 0;
+        for (final ArenaPlayer ap : this.arena.getFighters()) {
+            double score = this.getLifeMap().getOrDefault(ap.getName(), 0);
             if (ap.getArenaTeam() != null && "infected".equals(ap.getArenaTeam().getName())) {
-                score *= arena.getFighters().size();
+                score *= this.arena.getFighters().size();
             }
             if (scores.containsKey(ap.getName())) {
                 scores.put(ap.getName(), scores.get(ap.getName()) + score);
@@ -754,6 +744,6 @@ public Map timedEnd(final Map scores) {
 
     @Override
     public void unload(final Player player) {
-        getLifeMap().remove(player.getName());
+        this.getLifeMap().remove(player.getName());
     }
 }

From 8178961d6749c6da610d7c27756ab15901128d0e Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 20 Jul 2020 22:28:03 +0200
Subject: [PATCH 075/115] v1.15 - fix missing scoreboard color for Infected and
 Tank goals - issue #52

---
 src/net/slipcor/pvparena/arena/Arena.java | 39 ++++++++++++++---------
 1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index b039047a5..53de2f5ed 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -2343,10 +2343,11 @@ public void updateScoreboards() {
                     }
                 } else {
                     for (ArenaTeam team : this.getTeams()) {
-                        ArenaPlayer randomTeamPlayer = team.getTeamMembers().iterator().next();
-                        currentScoreboard.getObjective("lives")
+                        team.getTeamMembers().stream().findFirst().ifPresent(randomTeamPlayer ->
+                            currentScoreboard.getObjective("lives")
                                 .getScore(team.getName())
-                                .setScore(PACheck.handleGetLives(this, randomTeamPlayer));
+                                .setScore(PACheck.handleGetLives(this, randomTeamPlayer))
+                        );
                     }
                     for (ArenaPlayer ap : this.getEveryone()) {
                         Player player = ap.get();
@@ -2382,27 +2383,35 @@ public void updateScoreboardTeam(final Player player, final ArenaTeam oldTeam, f
             Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> {
                 board.getTeam(oldTeam.getName()).removeEntry(player.getName());
 
-                for (final Team sTeam : board.getTeams()) {
-                    if (sTeam.getName().equals(newTeam.getName())) {
-                        sTeam.addEntry(player.getName());
-                        return;
-                    }
-                }
+                Team sTeam = board.getTeams().stream()
+                        .filter(t -> t.getName().equals(newTeam.getName()))
+                        .findFirst()
+                        .orElseGet(() -> this.addNewTeam(board, newTeam));
+                sTeam.addEntry(player.getName());
+
                 this.updateScoreboard(player);
             }, 1L);
         } else {
             Scoreboard board = this.getStandardScoreboard();
             board.getTeam(oldTeam.getName()).removeEntry(player.getName());
 
-            for (final Team sTeam : board.getTeams()) {
-                if (sTeam.getName().equals(newTeam.getName())) {
-                    sTeam.addEntry(player.getName());
-                    return;
-                }
-            }
+            Team sTeam = board.getTeams().stream()
+                    .filter(t -> t.getName().equals(newTeam.getName()))
+                    .findFirst()
+                    .orElseGet(() -> this.addNewTeam(board, newTeam));
+            sTeam.addEntry(player.getName());
         }
     }
 
+    private Team addNewTeam(Scoreboard board, ArenaTeam newTeam) {
+        final Team sTeam = board.registerNewTeam(newTeam.getName());
+        sTeam.setPrefix(newTeam.getColor().toString());
+        sTeam.setSuffix(ChatColor.RESET.toString());
+        sTeam.setColor(newTeam.getColor());
+        sTeam.setCanSeeFriendlyInvisibles(!this.isFreeForAll());
+        return sTeam;
+    }
+
     public YamlConfiguration getLanguage() {
         return language;
     }

From a733c08fd993d8396e1d7c590196e914b26d44c1 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 31 Jul 2020 18:36:18 +0200
Subject: [PATCH 076/115] v1.15 - fix color management and autocompletion for
 teams command

---
 src/net/slipcor/pvparena/commands/PAA_Teams.java | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/net/slipcor/pvparena/commands/PAA_Teams.java b/src/net/slipcor/pvparena/commands/PAA_Teams.java
index fd8ece169..627f1043a 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Teams.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Teams.java
@@ -8,9 +8,9 @@
 import net.slipcor.pvparena.core.Language.MSG;
 import net.slipcor.pvparena.core.StringParser;
 import org.bukkit.ChatColor;
-import org.bukkit.DyeColor;
 import org.bukkit.command.CommandSender;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
@@ -71,10 +71,10 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
         } else if ("add".equals(args[0])) {
             try {
 
-                final DyeColor dColor = DyeColor.valueOf(args[2].toUpperCase());
-                final ArenaTeam newTeam = new ArenaTeam(args[1], dColor.name());
+                final ChatColor color = ChatColor.valueOf(args[2].toUpperCase());
+                final ArenaTeam newTeam = new ArenaTeam(args[1], color.name());
                 arena.getTeams().add(newTeam);
-                arena.getArenaConfig().setManually("teams." + newTeam.getName(), dColor.name());
+                arena.getArenaConfig().setManually("teams." + newTeam.getName(), color.name());
                 arena.getArenaConfig().save();
 
                 arena.msg(sender, Language.parse(arena, MSG.TEAMS_ADD, newTeam.getColoredName()));
@@ -128,7 +128,9 @@ public CommandTree getSubs(final Arena arena) {
         }
         for (final String team : arena.getTeamNames()) {
             result.define(new String[]{"remove", team});
-            result.define(new String[]{"set", team});
+            Arrays.stream(ChatColor.values()).forEach(color ->
+                    result.define(new String[]{"set", team, color.name()})
+            );
         }
         return result;
     }

From 4ada2826654755285d4f163b1c71efb762624445 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 7 Aug 2020 18:03:00 +0200
Subject: [PATCH 077/115] v1.15 - fix order of region remove command

---
 src/net/slipcor/pvparena/commands/PAA_Region.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/commands/PAA_Region.java b/src/net/slipcor/pvparena/commands/PAA_Region.java
index 39d2f297a..3903cfc4b 100644
--- a/src/net/slipcor/pvparena/commands/PAA_Region.java
+++ b/src/net/slipcor/pvparena/commands/PAA_Region.java
@@ -89,7 +89,7 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
             region.getShape().showBorder((Player) sender);
             return;
         }
-        if (args.length == 2 && args[0].equalsIgnoreCase("remove")) {
+        if (args.length == 2 && args[1].equalsIgnoreCase("remove")) {
             // usage: /pa {arenaname} region remove [regionname] | remove a region
             final ArenaRegion region = arena.getRegion(args[1]);
 

From 5e9588d95d911dc2e20278b3f629a1852b5690cf Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 10 Aug 2020 22:16:04 +0200
Subject: [PATCH 078/115] v1.15 - fix PlayerKillRewards graduallyDown option
 and equipping error

---
 .../slipcor/pvparena/arena/ArenaClass.java    |  22 +-
 .../pvparena/goals/GoalPlayerKillReward.java  | 261 +++++++++---------
 2 files changed, 152 insertions(+), 131 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java
index b35cdfcb1..89e6ff9fd 100644
--- a/src/net/slipcor/pvparena/arena/ArenaClass.java
+++ b/src/net/slipcor/pvparena/arena/ArenaClass.java
@@ -6,6 +6,7 @@
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.block.Chest;
+import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.configuration.file.YamlConfiguration;
 import org.bukkit.entity.EntityType;
 import org.bukkit.entity.Player;
@@ -127,12 +128,10 @@ public static void addGlobalClasses() {
             ItemStack[] armors;
 
             try {
-                items = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className)
-                        .getList("items"));
-                offHand = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className)
-                        .getList("items"))[0];
-                armors = getItemStacksFromConfig(cfg.getConfigurationSection("classes").getConfigurationSection(className)
-                        .getList("items"));
+                ConfigurationSection classesCfg = cfg.getConfigurationSection("classes").getConfigurationSection(className);
+                items = getItemStacksFromConfig(classesCfg.getList("items"));
+                offHand = getItemStacksFromConfig(classesCfg.getList("items"))[0];
+                armors = getItemStacksFromConfig(classesCfg.getList("items"));
             } catch (final Exception e) {
                 Bukkit.getLogger().severe(
                         "[PVP Arena] Error while parsing class, skipping: "
@@ -195,8 +194,15 @@ public void run() {
     }
 
     public static void equip(final Player player, final ItemStack[][] itemArray) {
-        player.getInventory().setItemInOffHand(itemArray[1][0]);
-        player.getInventory().setArmorContents(itemArray[2]);
+        try {
+            player.getInventory().setItemInOffHand(itemArray[1][0]);
+        } catch(ArrayIndexOutOfBoundsException e) {
+            player.getInventory().setItemInOffHand(new ItemStack(Material.AIR));
+        }
+
+        for(ItemStack itemStack : itemArray[2]) {
+            equipArmor(itemStack, player.getInventory());
+        }
 
         for (final ItemStack item : itemArray[0]) {
             if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) {
diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java b/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java
index e2dd3a2d8..09d910d05 100644
--- a/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java
+++ b/src/net/slipcor/pvparena/goals/GoalPlayerKillReward.java
@@ -13,7 +13,6 @@
 import net.slipcor.pvparena.core.Debug;
 import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.core.Language.MSG;
-import net.slipcor.pvparena.core.StringParser;
 import net.slipcor.pvparena.events.PAGoalEvent;
 import net.slipcor.pvparena.loadables.ArenaGoal;
 import net.slipcor.pvparena.loadables.ArenaModuleManager;
@@ -33,6 +32,8 @@
 
 import java.util.*;
 
+import static net.slipcor.pvparena.core.Utils.getSerializableItemStacks;
+
 /**
  * 
  * Arena Goal class "PlayerKillreward"
@@ -48,7 +49,7 @@
 public class GoalPlayerKillReward extends ArenaGoal {
     public GoalPlayerKillReward() {
         super("PlayerKillReward");
-        debug = new Debug(102);
+        this.debug = new Debug(102);
     }
 
     private Map itemMapCubed;
@@ -64,7 +65,7 @@ public String version() {
 
     @Override
     public boolean allowsJoinInBattle() {
-        return arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
+        return this.arena.getArenaConfig().getBoolean(CFG.PERMS_JOININBATTLE);
     }
 
     @Override
@@ -100,8 +101,8 @@ public PACheck checkEnd(final PACheck res) {
             return res;
         }
 
-        if (!arena.isFreeForAll()) {
-            final int count = TeamManager.countActiveTeams(arena);
+        if (!this.arena.isFreeForAll()) {
+            final int count = TeamManager.countActiveTeams(this.arena);
 
             if (count <= 1) {
                 res.setPriority(this, PRIORITY); // yep. only one team left. go!
@@ -109,7 +110,7 @@ public PACheck checkEnd(final PACheck res) {
             return res;
         }
 
-        final int count = getLifeMap().size();
+        final int count = this.getLifeMap().size();
 
         if (count <= 1) {
             res.setPriority(this, PRIORITY); // yep. only one player left. go!
@@ -123,11 +124,11 @@ public PACheck checkEnd(final PACheck res) {
 
     @Override
     public String checkForMissingSpawns(final Set list) {
-        if (!arena.isFreeForAll()) {
-            return checkForMissingTeamSpawn(list);
+        if (!this.arena.isFreeForAll()) {
+            return this.checkForMissingTeamSpawn(list);
         }
 
-        return checkForMissingSpawn(list);
+        return this.checkForMissingSpawn(list);
     }
 
     @Override
@@ -136,12 +137,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
-        final int maxTeamPlayers = arena.getArenaConfig().getInt(
+        final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
+        final int maxTeamPlayers = this.arena.getArenaConfig().getInt(
                 CFG.READY_MAXTEAMPLAYERS);
 
-        if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) {
-            res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL));
+        if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) {
+            res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL));
             return res;
         }
 
@@ -149,12 +150,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        if (!arena.isFreeForAll()) {
-            final ArenaTeam team = arena.getTeam(args[0]);
+        if (!this.arena.isFreeForAll()) {
+            final ArenaTeam team = this.arena.getTeam(args[0]);
 
             if (team != null && maxTeamPlayers > 0
                     && team.getTeamMembers().size() >= maxTeamPlayers) {
-                res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
+                res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
                 return res;
             }
         }
@@ -165,7 +166,7 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
 
     @Override
     public void commitCommand(final CommandSender sender, final String[] args) {
-        if (!AbstractArenaCommand.argCountValid(sender, arena, args, new Integer[]{2,
+        if (!AbstractArenaCommand.argCountValid(sender, this.arena, args, new Integer[]{2,
                 3})) {
             return;
         }
@@ -177,16 +178,16 @@ public void commitCommand(final CommandSender sender, final String[] args) {
         try {
             value = Integer.parseInt(args[1]);
         } catch (final Exception e) {
-            arena.msg(sender, Language.parse(arena, MSG.ERROR_NOT_NUMERIC, args[1]));
+            this.arena.msg(sender, Language.parse(this.arena, MSG.ERROR_NOT_NUMERIC, args[1]));
             return;
         }
         if (args.length > 2) {
-            getItemMap().remove(value);
-            arena.msg(sender,
-                    Language.parse(arena, MSG.GOAL_KILLREWARD_REMOVED, args[1]));
+            this.getItemMap().remove(value);
+            this.arena.msg(sender,
+                    Language.parse(this.arena, MSG.GOAL_KILLREWARD_REMOVED, args[1]));
         } else {
             if (!(sender instanceof Player)) {
-                Arena.pmsg(sender, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS));
+                Arena.pmsg(sender, Language.parse(this.arena, MSG.ERROR_ONLY_PLAYERS));
                 return;
             }
             final Player player = (Player) sender;
@@ -197,80 +198,76 @@ public void commitCommand(final CommandSender sender, final String[] args) {
                     player.getInventory().getArmorContents()
             };
 
-            getItemMap().put(value, content);
-            arena.msg(sender, Language.parse(arena, MSG.GOAL_KILLREWARD_ADDED,
+            this.getItemMap().put(value, content);
+            this.arena.msg(sender, Language.parse(this.arena, MSG.GOAL_KILLREWARD_ADDED,
                     args[1]));
 
         }
 
-        saveItems();
+        this.saveItems();
     }
 
     @Override
     public void commitEnd(final boolean force) {
-        if (endRunner != null) {
+        if (this.endRunner != null) {
             return;
         }
-        if (arena.realEndRunner != null) {
-            arena.getDebugger().i("[PKW] already ending");
+        if (this.arena.realEndRunner != null) {
+            this.arena.getDebugger().i("[PKW] already ending");
             return;
         }
-        final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "");
+        final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "");
         Bukkit.getPluginManager().callEvent(gEvent);
 
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             for (final ArenaPlayer ap : team.getTeamMembers()) {
                 if (ap.getStatus() != Status.FIGHT) {
                     continue;
                 }
 
-                if (arena.isFreeForAll()) {
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.PLAYER_HAS_WON, ap.getName()),
+                if (this.arena.isFreeForAll()) {
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.PLAYER_HAS_WON, ap.getName()),
                             "END");
 
-                    ArenaModuleManager.announce(arena,
-                            Language.parse(arena, MSG.PLAYER_HAS_WON, ap.getName()),
+                    ArenaModuleManager.announce(this.arena,
+                            Language.parse(this.arena, MSG.PLAYER_HAS_WON, ap.getName()),
                             "WINNER");
 
-                    arena.broadcast(Language.parse(arena, MSG.PLAYER_HAS_WON,
+                    this.arena.broadcast(Language.parse(this.arena, MSG.PLAYER_HAS_WON,
                             ap.getName()));
                 } else {
                     ArenaModuleManager.announce(
-                            arena,
-                            Language.parse(arena, MSG.TEAM_HAS_WON,
+                            this.arena,
+                            Language.parse(this.arena, MSG.TEAM_HAS_WON,
                                     team.getColoredName()), "END");
 
                     ArenaModuleManager.announce(
-                            arena,
-                            Language.parse(arena, MSG.TEAM_HAS_WON,
+                            this.arena,
+                            Language.parse(this.arena, MSG.TEAM_HAS_WON,
                                     team.getColoredName()), "WINNER");
 
-                    arena.broadcast(Language.parse(arena, MSG.TEAM_HAS_WON,
+                    this.arena.broadcast(Language.parse(this.arena, MSG.TEAM_HAS_WON,
                             team.getColoredName()));
                     break;
                 }
             }
 
-            if (ArenaModuleManager.commitEnd(arena, team)) {
+            if (ArenaModuleManager.commitEnd(this.arena, team)) {
                 return;
             }
         }
-        endRunner = new EndRunnable(arena, arena.getArenaConfig().getInt(
+        this.endRunner = new EndRunnable(this.arena, this.arena.getArenaConfig().getInt(
                 CFG.TIME_ENDCOUNTDOWN));
     }
 
     @Override
     public void parsePlayerDeath(final Player player, final EntityDamageEvent event) {
-        if (!getLifeMap().containsKey(player.getName())) {
+        if (!this.getLifeMap().containsKey(player.getName())) {
             return;
         }
-        if (arena.getArenaConfig().getBoolean(CFG.GOAL_PLAYERKILLREWARD_GRADUALLYDOWN)) {
-            int lives = getLifeMap().get(player.getName());
-            lives++;
-            getLifeMap().put(player.getName(), lives);
-        } else {
-            getLifeMap().put(player.getName(), getMaxInt());
+        if (!this.arena.getArenaConfig().getBoolean(CFG.GOAL_PLAYERKILLREWARD_GRADUALLYDOWN)) {
+            this.getLifeMap().put(player.getName(), this.getDefaultRemainingKills());
         }
 
 
@@ -279,7 +276,7 @@ class ResetRunnable implements Runnable {
 
             @Override
             public void run() {
-                reset(player);
+                this.reset(this.player);
             }
 
             ResetRunnable(final Player player) {
@@ -287,19 +284,19 @@ public void run() {
             }
 
             private void reset(final Player player) {
-                if (!getLifeMap().containsKey(player.getName())) {
+                if (!GoalPlayerKillReward.this.getLifeMap().containsKey(player.getName())) {
                     return;
                 }
 
-                final int iLives = getLifeMap().get(player.getName());
+                final int iLives = GoalPlayerKillReward.this.getLifeMap().get(player.getName());
                 if (ArenaPlayer.parsePlayer(player.getName()).getStatus() != Status.FIGHT) {
                     return;
                 }
-                if (!arena.getArenaConfig().getBoolean(CFG.GOAL_PLAYERKILLREWARD_ONLYGIVE)) {
+                if (!GoalPlayerKillReward.this.arena.getArenaConfig().getBoolean(CFG.GOAL_PLAYERKILLREWARD_ONLYGIVE)) {
                     InventoryManager.clearInventory(player);
                 }
-                if (getItemMap().containsKey(iLives)) {
-                    ArenaClass.equip(player, getItemMap().get(iLives));
+                if (GoalPlayerKillReward.this.getItemMap().containsKey(iLives)) {
+                    ArenaClass.equip(player, GoalPlayerKillReward.this.getItemMap().get(iLives));
                 } else {
                     ArenaPlayer.parsePlayer(player.getName()).getArenaClass()
                             .equip(player);
@@ -315,21 +312,21 @@ private void reset(final Player player) {
             return;
         }
 
-        int iLives = getLifeMap().get(killer.getName());
-        arena.getDebugger().i("kills to go for " + killer.getName() + ": " + iLives, killer);
+        int iLives = this.getLifeMap().get(killer.getName());
+        this.arena.getDebugger().i("kills to go for " + killer.getName() + ": " + iLives, killer);
         if (iLives <= 1) {
             // player has won!
-            final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "trigger:" + killer.getName(), "playerKill:" + killer.getName() + ':' + player.getName(), "playerDeath:" + player.getName());
+            final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "trigger:" + killer.getName(), "playerKill:" + killer.getName() + ':' + player.getName(), "playerDeath:" + player.getName());
             Bukkit.getPluginManager().callEvent(gEvent);
             final Set plrs = new HashSet<>();
-            for (final ArenaPlayer ap : arena.getFighters()) {
+            for (final ArenaPlayer ap : this.arena.getFighters()) {
                 if (ap.getName().equals(killer.getName())) {
                     continue;
                 }
                 plrs.add(ap);
             }
             for (final ArenaPlayer ap : plrs) {
-                getLifeMap().remove(ap.getName());
+                this.getLifeMap().remove(ap.getName());
 				/*
 				arena.getDebugger().i("faking player death", ap.get());
 				arena.removePlayer(ap.get(), CFG.TP_LOSE.toString(), true,
@@ -341,33 +338,33 @@ private void reset(final Player player) {
                 //PlayerState.fullReset(arena, ap.get());
             }
 
-            if (ArenaManager.checkAndCommit(arena, false)) {
+            if (ArenaManager.checkAndCommit(this.arena, false)) {
                 return;
             }
-            PACheck.handleEnd(arena, false);
+            PACheck.handleEnd(this.arena, false);
         } else {
-            final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "playerKill:" + killer.getName() + ':' + player.getName(), "playerDeath:" + player.getName());
+            final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "playerKill:" + killer.getName() + ':' + player.getName(), "playerDeath:" + player.getName());
             Bukkit.getPluginManager().callEvent(gEvent);
             iLives--;
-            getLifeMap().put(killer.getName(), iLives);
+            this.getLifeMap().put(killer.getName(), iLives);
             Bukkit.getScheduler().runTaskLater(PVPArena.instance,
                     new ResetRunnable(killer), 4L);
         }
     }
 
     private Map getItemMap() {
-        if (itemMapCubed == null) {
-            itemMapCubed = new HashMap<>();
+        if (this.itemMapCubed == null) {
+            this.itemMapCubed = new HashMap<>();
         }
-        return itemMapCubed;
+        return this.itemMapCubed;
     }
 
     @Override
     public boolean hasSpawn(final String string) {
-        if (arena.isFreeForAll()) {
+        if (this.arena.isFreeForAll()) {
 
-            if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-                for (final ArenaClass aClass : arena.getClasses()) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+                for (final ArenaClass aClass : this.arena.getClasses()) {
                     if (string.toLowerCase().startsWith(
                             aClass.getName().toLowerCase() + "spawn")) {
                         return true;
@@ -376,14 +373,14 @@ public boolean hasSpawn(final String string) {
             }
             return string.toLowerCase().startsWith("spawn");
         }
-        for (final String teamName : arena.getTeamNames()) {
+        for (final String teamName : this.arena.getTeamNames()) {
             if (string.toLowerCase().startsWith(
                     teamName.toLowerCase() + "spawn")) {
                 return true;
             }
 
-            if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-                for (final ArenaClass aClass : arena.getClasses()) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+                for (final ArenaClass aClass : this.arena.getClasses()) {
                     if (string.toLowerCase().startsWith(teamName.toLowerCase() +
                             aClass.getName().toLowerCase() + "spawn")) {
                         return true;
@@ -396,12 +393,12 @@ public boolean hasSpawn(final String string) {
 
     @Override
     public void initate(final Player player) {
-        getLifeMap().put(player.getName(), getMaxInt());
+        this.getLifeMap().put(player.getName(), this.getDefaultRemainingKills());
     }
 
-    private int getMaxInt() {
+    private int getDefaultRemainingKills() {
         int max = 0;
-        for (final int i : getItemMap().keySet()) {
+        for (final int i : this.getItemMap().keySet()) {
             max = Math.max(max, i);
         }
         return max + 1;
@@ -416,43 +413,41 @@ public boolean isInternal() {
     public void parseLeave(final Player player) {
         if (player == null) {
             PVPArena.instance.getLogger().warning(
-                    getName() + ": player NULL");
+                    this.getName() + ": player NULL");
             return;
         }
-        if (getLifeMap().containsKey(player.getName())) {
-            getLifeMap().remove(player.getName());
-        }
+        this.getLifeMap().remove(player.getName());
     }
 
     @Override
     public void parseStart() {
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             for (final ArenaPlayer ap : team.getTeamMembers()) {
-                getLifeMap().put(ap.getName(), getMaxInt());
+                this.getLifeMap().put(ap.getName(), this.getDefaultRemainingKills());
             }
         }
     }
 
     @Override
     public void reset(final boolean force) {
-        endRunner = null;
-        getLifeMap().clear();
+        this.endRunner = null;
+        this.getLifeMap().clear();
     }
 
     @Override
     public void setDefaults(final YamlConfiguration config) {
-        if (!arena.isFreeForAll()) {
+        if (!this.arena.isFreeForAll()) {
             if (config.get("teams.free") != null) {
                 config.set("teams", null);
             }
             if (config.get("teams") == null) {
-                arena.getDebugger().i("no teams defined, adding custom red and blue!");
+                this.arena.getDebugger().i("no teams defined, adding custom red and blue!");
                 config.addDefault("teams.red", ChatColor.RED.name());
                 config.addDefault("teams.blue", ChatColor.BLUE.name());
             }
-            if (arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)
+            if (this.arena.getArenaConfig().getBoolean(CFG.GOAL_FLAGS_WOOLFLAGHEAD)
                     && config.get("flagColors") == null) {
-                arena.getDebugger().i("no flagheads defined, adding white and black!");
+                this.arena.getDebugger().i("no flagheads defined, adding white and black!");
                 config.addDefault("flagColors.red", "WHITE");
                 config.addDefault("flagColors.blue", "BLACK");
             }
@@ -465,98 +460,91 @@ public void setDefaults(final YamlConfiguration config) {
         if (cs != null) {
             for (final String line : cs.getKeys(false)) {
                 try {
-                    getItemMap().put(Integer.parseInt(line.substring(2)),
+                    this.getItemMap().put(Integer.parseInt(line.substring(2)),
                         new ItemStack[][] {
                             cs.getList(line + ".items").toArray(new ItemStack[0]),
                             cs.getList(line + ".offhand").toArray(new ItemStack[]{new ItemStack(Material.AIR, 1)}),
                             cs.getList(line + ".armor").toArray(new ItemStack[0])
                         });
-                } catch (final Exception e) {
+                } catch (final Exception ignored) {
                 }
             }
         }
 
-        if (getItemMap().size() < 1) {
+        if (this.getItemMap().size() < 1) {
 
-            getItemMap().put(5, new ItemStack[][]{
-                        new ItemStack[]{},
-                        new ItemStack[]{},
+            this.getItemMap().put(5, new ItemStack[][]{
+                        new ItemStack[]{new ItemStack(Material.WOODEN_SWORD, 1)},
+                        new ItemStack[]{new ItemStack(Material.AIR, 1)},
                         new ItemStack[]{
                                 new ItemStack(Material.LEATHER_HELMET, 1),
                                 new ItemStack(Material.LEATHER_CHESTPLATE, 1),
                                 new ItemStack(Material.LEATHER_LEGGINGS, 1),
                                 new ItemStack(Material.LEATHER_BOOTS, 1),
-                                new ItemStack(Material.WOODEN_SWORD, 1)
                         },
                     });
-            getItemMap().put(4, new ItemStack[][]{
-                    new ItemStack[]{},
+            this.getItemMap().put(4, new ItemStack[][]{
+                    new ItemStack[]{new ItemStack(Material.STONE_SWORD, 1)},
                     new ItemStack[]{new ItemStack(Material.AIR, 1)},
                     new ItemStack[]{
                             new ItemStack(Material.CHAINMAIL_HELMET, 1),
                             new ItemStack(Material.CHAINMAIL_CHESTPLATE, 1),
                             new ItemStack(Material.CHAINMAIL_LEGGINGS, 1),
                             new ItemStack(Material.CHAINMAIL_BOOTS, 1),
-                            new ItemStack(Material.STONE_SWORD, 1)
                     },
             });
-            getItemMap().put(3, new ItemStack[][]{
-                    new ItemStack[]{},
+            this.getItemMap().put(3, new ItemStack[][]{
+                    new ItemStack[]{new ItemStack(Material.IRON_SWORD, 1)},
                     new ItemStack[]{new ItemStack(Material.AIR, 1)},
                     new ItemStack[]{
                             new ItemStack(Material.GOLDEN_HELMET, 1),
                             new ItemStack(Material.GOLDEN_CHESTPLATE, 1),
                             new ItemStack(Material.GOLDEN_LEGGINGS, 1),
                             new ItemStack(Material.GOLDEN_BOOTS, 1),
-                            new ItemStack(Material.IRON_SWORD, 1)
                     },
             });
-            getItemMap().put(2, new ItemStack[][]{
-                    new ItemStack[]{},
+            this.getItemMap().put(2, new ItemStack[][]{
+                    new ItemStack[]{new ItemStack(Material.DIAMOND_SWORD, 1)},
                     new ItemStack[]{new ItemStack(Material.AIR, 1)},
                     new ItemStack[]{
                             new ItemStack(Material.IRON_HELMET, 1),
                             new ItemStack(Material.IRON_CHESTPLATE, 1),
                             new ItemStack(Material.IRON_LEGGINGS, 1),
                             new ItemStack(Material.IRON_BOOTS, 1),
-                            new ItemStack(Material.DIAMOND_SWORD, 1)
                     },
             });
-            getItemMap().put(1, new ItemStack[][]{
-                    new ItemStack[]{},
+            this.getItemMap().put(1, new ItemStack[][]{
+                    new ItemStack[]{new ItemStack(Material.DIAMOND_SWORD, 1)},
                     new ItemStack[]{new ItemStack(Material.AIR, 1)},
                     new ItemStack[]{
                             new ItemStack(Material.DIAMOND_HELMET, 1),
                             new ItemStack(Material.DIAMOND_CHESTPLATE, 1),
                             new ItemStack(Material.DIAMOND_LEGGINGS, 1),
                             new ItemStack(Material.DIAMOND_BOOTS, 1),
-                            new ItemStack(Material.DIAMOND_SWORD, 1)
                     },
             });
 
-            saveItems();
+            this.saveItems();
         }
     }
 
     private void saveItems() {
-        for (final int i : getItemMap().keySet()) {
-            arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".items",
-                    getItemMap().get(i)[0]);
-            arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".offhand",
-                    getItemMap().get(i)[1]);
-            arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".armor",
-                    getItemMap().get(i)[2]);
-        }
-        arena.getArenaConfig().save();
+        for (final int i : this.getItemMap().keySet()) {
+            this.arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".items",
+                    getSerializableItemStacks(this.getItemMap().get(i)[0]));
+            this.arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".offhand",
+                    getSerializableItemStacks(this.getItemMap().get(i)[1]));
+            this.arena.getArenaConfig().setManually("goal.playerkillrewards.kr" + i+".armor",
+                    getSerializableItemStacks(this.getItemMap().get(i)[2]));
+        }
+        this.arena.getArenaConfig().save();
     }
 
     @Override
     public Map timedEnd(final Map scores) {
 
-        for (final ArenaPlayer ap : arena.getFighters()) {
-            double score = getMaxInt()
-                    - (getLifeMap().containsKey(ap.getName()) ? getLifeMap()
-                    .get(ap.getName()) : 0);
+        for (final ArenaPlayer ap : this.arena.getFighters()) {
+            double score = this.getDefaultRemainingKills() - (this.getLifeMap().getOrDefault(ap.getName(), 0));
             if (scores.containsKey(ap.getName())) {
                 scores.put(ap.getName(), scores.get(ap.getName()) + score);
             } else {
@@ -567,8 +555,35 @@ public Map timedEnd(final Map scores) {
         return scores;
     }
 
+    @Override
+    public PACheck getLives(PACheck res, ArenaPlayer player) {
+        if (res.getPriority() <= PRIORITY + 1000) {
+            if (this.arena.isFreeForAll()) {
+                res.setError(
+                        this, String.valueOf(this.getLifeMap().getOrDefault(player.getName(), 0))
+                );
+            } else {
+                if (this.getLifeMap().containsKey(player.getArenaTeam().getName())) {
+                    res.setError(this, String.valueOf(this.getLifeMap().get(player.getName())));
+                } else {
+
+                    int sum = 0;
+
+                    for (final ArenaPlayer ap : player.getArenaTeam().getTeamMembers()) {
+                        if (this.getLifeMap().containsKey(ap.getName())) {
+                            sum += this.getLifeMap().get(ap.getName());
+                        }
+                    }
+
+                    res.setError(this, String.valueOf(sum));
+                }
+            }
+        }
+        return res;
+    }
+
     @Override
     public void unload(final Player player) {
-        getLifeMap().remove(player.getName());
+        this.getLifeMap().remove(player.getName());
     }
 }

From 788f8fe618ef966e0bb704dc8e8fe9737f3b1062 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 25 Jun 2020 18:35:08 +0200
Subject: [PATCH 079/115] creating getting started documentation

---
 doc/commands/gamemode.md |   8 +--
 doc/creation.md          |  61 --------------------
 doc/getting-started.md   | 120 +++++++++++++++++++++++++++++++++++++++
 doc/goals.md             |  26 +++++++++
 doc/modules.md           |  69 ++++++++++++++++++++++
 doc/update-version.md    |  46 +++++++++++++++
 readme.md                | 118 ++++++++++++++------------------------
 7 files changed, 305 insertions(+), 143 deletions(-)
 delete mode 100644 doc/creation.md
 create mode 100644 doc/getting-started.md
 create mode 100644 doc/goals.md
 create mode 100644 doc/modules.md

diff --git a/doc/commands/gamemode.md b/doc/commands/gamemode.md
index 7bc7e9bac..8462fd2fb 100644
--- a/doc/commands/gamemode.md
+++ b/doc/commands/gamemode.md
@@ -7,12 +7,8 @@ The gamemode defines the general play mode. Free For All or Team Play ?
 ## Usage Examples
 Command |  Definition
 ------------- | -------------
-/pa ctf gamemode ctf | set the gamemode of arena "ctf" to "team"
-/pa free !gm free    | set the gamemode of arena "free" to "free"
-
-## Hazards
-
-Messing up here results in strange game logic interpretations, because several things are based on the decision if we have teams or not.
+/pa ctf gamemode team | set the gamemode of arena "ctf" to "team"
+/pa ffa !gm free    | set the gamemode of arena "ffa" to "free"
 
 ## Details
 
diff --git a/doc/creation.md b/doc/creation.md
deleted file mode 100644
index 8f502fb2e..000000000
--- a/doc/creation.md
+++ /dev/null
@@ -1,61 +0,0 @@
-
-## Basic creation
-
-_\[Required] (Optional) Arena name is optional if you are inside an arena or in edit mode, but if you have more than one arena it is required._
-
-### 1. Create the arena.
-
-`/pa create [Arena Name] (Legacy Type)`
-
-Valid types are: 
-- team 
-- teamdm 
-- dm 
-- free 
-- ctf 
-- ctp 
-- spleef 
-- tank
-- sabotage
-
-### 2. Set spawns for the arena.
-
-/pa (Arena Name) spawn [spawntype]
-Types are: [team]spawn / [team]lounge / spectator / spawn[x] (ffa only)
-
-By default you need: 2 spawns (red & blue) / 2 lounges (red & blue) / spectator zone.
-
-### 3. Create the battle region.
-
-`/pa (Arena Name) region`
-
-The default region setting tool is a stick. Set your region with left and right click. 
-
-Then:
-
-`/pa (Arena Name) region [Region Name] (Region Shape)`
-
-Valid shape types: 
-
-- cuboid 
-- spheric 
-- cylindric
-
-### 4. Place required items in the lounge
-
-Simply place the signs and on the first line put the class names.
-
-Default classes are: Swordsman / Tank / Pyro / Ranger
-
-Add more classes with the [class command](commands/class.md)
-
-Place the signs in each lobby, and an iron block (configurable). The iron block is the default ready block, and you push it when your ready to start the match.
-
-:triangular_flag_on_post: Tip : You can set a default class using the config parameter `autoClass`.
-
-### 5. Join the arena!
-
-`/pa [Arena Name] (join) (teamname)`
-
-
-See the [video tutorial](https://www.youtube.com/watch?v=yyPJ6vlv09s)
\ No newline at end of file
diff --git a/doc/getting-started.md b/doc/getting-started.md
new file mode 100644
index 000000000..629dd43ac
--- /dev/null
+++ b/doc/getting-started.md
@@ -0,0 +1,120 @@
+
+## Getting Started
+
+
+ +> **🚩 Syntax tip:** +> [required] indicates a required parameter +> (optional) indicates an optional parameter +> + + +### Foreword: what's an arena? + +Before creating your first arena, you have to understand what's. +Arena is immaterial, it's a game configuration you create with goals, teams, classes, etc. It references your arena +config file created at `/plugins/pvparena/yourArenaName/config.yml`. So your arena defines how your game takes place. + +In this arena, only two things are bind to locations: spawn point and regions. So if you need to move your arena in +another place, don't destroy it, just redefine your spawn points and your regions. + +
+ +### 1. Create the arena + +Just type this command to create your arena: + +`/pa create [newArenaName] (free)` + +By default your arena will work with a team system. If you add the `free` option, your arena will work on a *Free for +all* (FFA) game mode. + +> **🚩 Tip:** This parameter can be changed using [/pa gamemode](commands/gamemode.md) command or in your config file by +> setting `general.type` parameter to `free` or `none`. + +
+ +### 2. Set goals for the arena + +By default, your arena will use [TeamLives](goals/teamlives.md) goal if your arena is in team mode and +[PlayerLives](goals/playerlives.md) goal otherwise. If you're ok with this, go to the next point, otherwise please +continue reading. + +You can choose a custom goal [in the list](goals.md) and set it for your arena with the command: +`/pa [arenaName] goal [goalName]` + +You will find more information about this command [on this link](commands/goal.md). + +
+ +### 3. Set spawn points + +Now you have to create game spawn points by using this command: +`/pa [arenaName] spawn [spawnType]` + +##### Team arenas +For team arenas, spawn types are: `[team]spawn`, `[team]lounge`, `spectator`, `exit`. +So by default you need: 2 spawns (red & blue) / 2 lounges (red & blue) / 1 spectator zone / 1 exit. + +##### Free arenas +For **free** (FFA) arenas, spawn types are: `spawn[x]`, `lounge`, `spectator`, `exit`. +By default you need: 4 spawns (spawn1, spawn2, spawn3, spawn4) / 1 lounge / 1 spectator zone / 1 exit. + +
+ +> **🚩 Tips:** +>- In free arenas, you can create as many spawn points as you want. +>- You can use `/pa spawn` command again to move a spawn point + +
+ +### 4. Create the battle region + +> *This step is optional but really useful in mostly configurations* + +Now create the battle region with this command: + +`/pa [arenaName] region` + +It enables selection mode. Equip your hand with a **stick** and set your region with left and right click. + +Then type : + +`/pa [arenaName] region [yourNewRegionName]` + +Finally, specify your region type : + +`/pa [arenaName] regionType [regionName] BATTLE` + +> **🚩 Tips:** +> - By default your region is protected from block destruction and placing +> - Get a look to [the region documentation page](regions.md) to improve your arena regions + +
+ +### 5. Place required items in the lounge + +By default, four classes already exist : Swordsman, Tank, Pyro and Ranger. +You can chose to keep these classes or create new ones with the the [class command](commands/class.md). + +Then simply place signs near your **lounge** spawn point(s) and write the class names on the first line. + +Place the signs in each lobby, and an iron block (configurable). +The iron block is the default ready block that players can click on when they are ready. The match begins +when all players +are ready. + +> **🚩 Tips:** +> - Players can can choose their class with `/pa arenaclass [className]` command +> - You can set a default class using the config parameter `autoClass` +> - Players can also be ready typing `/pa ready`, that's why ready block is not mandatory + +
+ +### 6. Join the arena! + +Your first arena was created! Join the game with: + +`/pa [arenaName] (join) (teamName)` + +> **🚩 Tip:** If you just type `/pa [arenaName]` your team will be randomly selected. \ No newline at end of file diff --git a/doc/goals.md b/doc/goals.md new file mode 100644 index 000000000..6a1667489 --- /dev/null +++ b/doc/goals.md @@ -0,0 +1,26 @@ +## PVP Arena Goals + +Create ways to win the game or lose the game! + +Goal | Description +------------- | ------------- +[Beacons](goals/beacons.md) | Stand near beacons and claim them to win! +[BlockDestroy](goals/blockdestroy.md) | Destroy blocks (pre-installed) +[CheckPoints](goals/checkpoints.md) | Reach checkpoints in order to win (pre-installed) +[Domination](goals/domination.md) | Dominate flag positions (pre-installed) +[Flags](goals/flags.md) | Capture flags and bring 'em home (pre-installed) +[Food](goals/food.md) | Cook food and bring it home (pre-installed) +[Infect](goals/infect.md) | Infect people to win / kill infected players (pre-installed) +[Liberation](goals/liberation.md) | Jail dead players, possibility to unjail! (pre-installed) +[PhysicalFlags](goals/physicalflags.md) | Capture flags physically and bring 'em home (pre-installed) +[Pillars](goals/pillars.md) | Capture pillars by clicking/destroying! +[PlayerDeathMatch](goals/playerdeathmatch.md) | Player kills win (pre-installed) +[PlayerKillReward](goals/playerkillreward.md) | Player get better gears when killing (pre-installed) +[Rescue](goals/rescue.md) | Rescue a trapped Entity +[PlayerLives](goals/playerlives.md) | Player deaths lose (pre-installed) +[Sabotage](goals/sabotage.md) | Ignite TNT (pre-installed) +[Tank](goals/tank.md) | all vs one (pre-installed) +[TeamDeathConfirm](goals/teamdeathconfirm.md) | Confirmed Team kills win (pre-installed) +[TeamDeathMatch](goals/teamdeathmatch.md) | Team kills win (pre-installed) +[TeamLives](goals/teamlives.md) | Team deaths lose (pre-installed) +[Time](goals/time.md) | Time ends the arena (pre-installed) \ No newline at end of file diff --git a/doc/modules.md b/doc/modules.md new file mode 100644 index 000000000..d1dbb4a7b --- /dev/null +++ b/doc/modules.md @@ -0,0 +1,69 @@ +## PVP Arena Modules + +### Installation + +Unzip the module files (files tab, "PA Files v\*.\*.\*") into the /pvparena/files folder and install them via +`/pa install [modname]`, **activate per arena via** +`/pa [arenaname] !tm [modname]` + + +### PVP Arena Mods + +Hook into many different aspects of the game! + +Mod | Description | Status +------------- | ------------- | ------------- +[AfterMatch](mods/aftermatch.md) | could also be called "Sudden Death" | ⚠ +[Announcements](mods/announcements.md) | announce events happening | ⚠ +[ArenaBoards](mods/arenaboards.md) | stats display | ⚠ +[ArenaMaps](mods/arenamaps.md) | never lose yourself ever again! | ⚠ +[AutoSneak](mods/autosneak.md) | automatically hide player nametags by forcing sneak mode | ⚠ +[AutoVote](mods/autovote.md) | automatism | ⚠ +[BanKick](mods/bankick.md) | secure your arenas! | ⚠ +[BattlefieldGuard](mods/battlefieldguard.md) | secure your battlefield | ✔ +[BattlefieldManager](mods/battlefieldmanager.md) | manage your battlefield | ⚠ +[BetterClasses](mods/betterclasses.md) | add potion effects and more to specific classes | ✔ +[BetterGears](mods/bettergears.md) | give team colored leather | ✔ +[BetterFight](mods/betterfight.md) | kill streaks and one-hit-kill items! | ⚠ +[BetterKillstreaks](mods/betterkillstreaks.md) | even more detailed kill streaks! | ⚠ +[BlockDissolve](mods/blockdissolve.md) | dissolve blocks under fighting players | ✔ +[BlockRestore](mods/blockrestore.md) | restore the battlefield | ✔ +[ChestFiller](mods/chestfiller.md) | fill battlefield chests with customizable content! | ✔ +[Duel](mods/duel.md) | duel someone! | ⚠ +[EventActions](mods/eventactions.md) | do stuff when stuff happens | ⚠ +[Factions](mods/factions.md) | fix pvp not working | ⚠ +[FixInventoryLoss](mods/fixinventoryloss.md) | prevent loss by gamemode / inventory check | ⚠ +[FlySpectate](mods/flyspectate.md) | have players spectating a fight in fly mode | ✔ +[Items](mods/items.md) | spawn (random) items | ⚠ +[LateLounge](mods/latelounge.md) | keep playing until enough ppl are joining | ✔ +[MatchResultStats](mods/matchresultstats.md) | keep stats of player games, who won, who lost? | ⚠ +[PlayerFinder](mods/playerfinder.md) | allow players to find others with a compass | ✔ +[Points](mods/points.md) | allow to restrict certain classes to require players to fight for better classes | ⚠ +[PowerUps](mods/powerups.md) | spawn items giving special powers | ✔ +[RealSpectate](mods/realspectate.md) | spectate the game, CounterStrike style! | ✔ +[RedstoneTriggers](mods/redstonetriggers.md) | add win/lose triggered by redstone | ⚠ +[RespawnRelay](mods/respawnrelay.md) | add a relay for respawning players | ⚠ +[SinglePlayerSupport](mods/singleplayersupport.md) | Allow players to use an arena on their own! | ⚠ +[Skins](mods/skins.md) | add custom skins to teams/classes | ❌ +[SpecialJoin](mods/specialjoin.md) | join via buttons, levers, etc | ⚠ +[Spectate](mods/spectate.md) | use the new 1.8 SPECTATOR mode to allow flying and POV spectating | ⚠ +[Squads](mods/squads.md) | add squads to the game, basically only showing players belonging together apart from teams and classes. | ✔ +[StartFreeze](mods/startfreeze.md) | freeze players at start | ⚠ +[TeamSizeRestrict](mods/teamsizerestrict.md) | a small mod to restrict the size of specific teams | ⚠ +[Titles](mods/titles.md) | send messages to players as the "title" command would do | ✔ +[TempPerms](mods/tempperms.md) | add temporary perms | ⚠ +[Turrets](mods/turrets.md) | add turrets where players fire projectiles | ⚠ +[Vault](mods/vault.md) | add economy | ✔ +[Walls](mods/walls.md) | define wall regions to simulate "The Walls" | ⚠ +[WorldEdit](mods/worldedit.md) | backup/restore regions | ✔ +[WorldGuard](mods/worldguard.md) | import region definitions from WorldGuard | ⚠ + +**Key :** ✔ Recently tested and full-functional | ⚠ Legacy modules, not tested for a while | ❌ Temporarily unavailable + +### Why are there different statuses? + +PVP Arena exists since 2011 and Minecraft servers evolution make modules follow-up complicated. The objective of next +updates will be to make a great check-up of all of them and fix all eventual issues. + +Anyway, don't hesitate to test legacy modules by yourself, a big part of them work normally or have trivial issues. Obviously +if you encounter one, you can report it 😉 \ No newline at end of file diff --git a/doc/update-version.md b/doc/update-version.md index d9385b332..5d7f59117 100644 --- a/doc/update-version.md +++ b/doc/update-version.md @@ -59,4 +59,50 @@ spawns: checkpoint4: world,297,64,1285,14.695302963256836,50.40021514892578 checkpoint5: world,298,64,1289,53.69533920288086,54.75028610229492 checkpoint6: world,295,64,1292,1.795335054397583,46.80023193359375 +``` + +## PowerUps Module + +In powerups mod, items and effects configuration was previously in a dedicated `powerups` bloc at root of your arena +config files. Just move this block content into a the following path `modules.powerups.items` + +Example : + +*Replace this* +```yaml +powerups: + Heal: + item: BREAD + health: + diff: 3 + Repair: + item: WORKBENCH + repair: + items: helmet,chestplate,leggins,boots + factor: 0.2 +# Lines below have no importance +teams: + red: RED + blue: BLUE +``` +*with this* +```yaml +modules: + powerups: + dropspawn: true + usage: death:1 + items: + Heal: + item: BREAD + health: + diff: 3 + Repair: + item: WORKBENCH + repair: + items: helmet,chestplate,leggins,boots + factor: 0.2 +# Lines below have no importance +teams: + red: RED + blue: BLUE ``` \ No newline at end of file diff --git a/readme.md b/readme.md index f0a3e22df..37c5363a8 100644 --- a/readme.md +++ b/readme.md @@ -1,117 +1,83 @@ -![PVP-Arena](/doc/images/logo.png) - -*** -**IF YOU'RE UPGRADING FROM 1.14.x VERSION OR BELOW, PLEASE READ [UPGRADE DOCUMENTATION](doc/update-version.md)** -*** - -**Enhance your server by adding a new dimension of PVP battles!** - -Create fully customizable, moddable, flexible arenas, develop your own arena goal or mod that totally changes the game as you wish. -This flexibility is achieved on the one hand by a module loader created by NodinChan which loads arena goals (/pvparena/goals) and arena mods (/pvparena/mods) which enhance the gameplay just limited by your imagination, on the other hand it features an API, which still is a WIP due to lack of requests. I will enhance it as feature/hook requests arise. +![PVP-Arena](doc/images/logo.png) +

+ + IF YOU'RE UPGRADING FROM 1.14.x VERSION OR BELOW, PLEASE READ + UPGRADE DOCUMENTATION + +

*** +[What is PVP Arena?](#What-is-PVP-Arena?) | [Dependencies](#Dependencies) | [Downloads](#Downloads) | +[Installation](#Installation) | [Documentation](#Documentation) | [Update Checker](#Update-Checker) | +[Telemetry](#Telemetry) | [Credits](#Credits) +*** +
+## What is PVP Arena? -## Features +PVP Arena is a plugin for Spigot based servers which enables creation of customizable fight and mini-games arenas. +Define your own teams, classes, lobbies, spawn points, messages, gear colors, rewards and even game modes! +Theses game modes (included in the plugin) can combined with tens of modules to enhance your gameplay! +In addition, all arenas can be protected with an embedded protection system based on regions. +Anyway, here's a quick (non exhaustive) list of plugin features: - Multiple arenas -- Battlefield regions -- Customizable classes +- Arena regions and protections - Player-state saving -- Arena regions -- In-game configuration access -- Arena disable -- Leader boards +- Customizable classes +- Customizable spawn points, lobbies and spectator zones +- In-game configuration access and simple config files +- Arena disabling +- Scoreboards - Spawn protection - Flag coloring - Inventory drops - Announcements -- Arena end timer +- Time limited match +- Battlefield regeneration +So take time to read the docs, it's full of useful information 😉 *** ## Dependencies - Spigot 1.13+ +- Java 8+ *** ## Downloads -- [spigotmc.org](https://www.spigotmc.org/resources/pvp-arena.16584/) -- [Dev builds on Jenkins](https://ci.craftyn.com/view/Spigot%20PVP%20Arena/) +PVP Arena release version can be downloaded on following pages: +- [PVP Arena - SpigotMC](https://www.spigotmc.org/resources/pvp-arena.16584/) +- [Github releases page](https://github.com/Eredrim/pvparena/releases) + +Development builds (experimental) can be downloaded on Jenkins: +- [Jenkins dev builds](https://ci.craftyn.com/view/Spigot%20PVP%20Arena/) *** -## How to install +## Installation -- Stop your server -- Place jar in plugins folder -- Run a first time to create config folder -- Configure if you wish to -- Done ! +Place PVP Arena `.jar` file in the plugin repository of your server and restart. *** ## Documentation -- [Creation](doc/creation.md) +- [Getting started](doc/getting-started.md) - [Commands](doc/commands.md) -- [Enhancements](doc/enhancements.md) -- [Items](doc/items.md) -- [Languages](doc/languages.md) - [Permissions](doc/permissions.md) - [Regions](doc/regions.md) +- [Goals](doc/goals.md) +- [Modules](doc/modules.md) +- [Items](doc/items.md) +- [Languages](doc/languages.md) - [Configuration](doc/configuration.md) *** -## Video Tutorials - -- Basic Setup (v1.3): - - [Team Arena](https://www.youtube.com/watch?v=PT0piAyVMIw) - - [Free For All Arena](https://www.youtube.com/watch?v=bYNtxGxVGfE) - - [Region Tutorial (Shapes)](https://www.youtube.com/watch?v=jWdWbwRg9zY) - - [Region Tutorial (Protections)](https://youtu.be/WFIZ7ZskPVc) -- Localized Setup (v1.3): - - [Team Arena (German)](https://www.youtube.com/watch?v=2KSAk-PvwRM) -- Goal Tutorials (v1.3): - - [BlockDestroy](https://www.youtube.com/watch?v=i7Fpuh_O5O8) - - [CheckPoints](https://www.youtube.com/watch?v=anO_tYwcKsg) - - [Domination](https://www.youtube.com/watch?v=_Ngq5xBlLsk) -- [CTF (v1.0)](http://www.youtube.com/watch?v=SuL78bce-f0) -- [DeathMatch (v1.0)](http://www.youtube.com/watch?v=KqBueDNbpD8) -- [Food Block Destroy (v1.0)](http://www.youtube.com/watch?v=ntloY1BTKHQ) -- [FreeForAll (v1.0)](http://www.youtube.com/watch?v=xBIxHoKMu98) -- [Spleef (v1.0)](http://www.youtube.com/watch?v=DRmLNXEAs_4) -- [Pillar Domination (v1.0)](http://www.youtube.com/watch?v=Xi7yNURxAjw) -- [TeamDeathMatch (v1.0)](http://www.youtube.com/watch?v=rQ1ljlc6SJM) - -Users tutorials : - -- [TeamDeathMatch (v1.0)](http://www.youtube.com/watch?v=Jw6E8s2kiKw) - -*** - -## Changelog - -- v1.13.5 - address #355 - set some more scoreboard settings to hopefully get colors going -- [read more](doc/changelog.md) - -*** - -## Todo - -- plugin - - [ ] calculate a winner based on ROUND results -- modules -- goals - - [ ] tournament arenas ; rounds switch through arenas - - [ ] siege -> bring PACKET from A to B || prevent - -*** - ## Update Checker If you wan't you can be informed of plugin or modules updates. Each release version was pushed on github since 1.14.0. The update checker will call the github APIs and announce an update to OPs on login. You can configure it to @@ -132,7 +98,7 @@ automatically download updates. ## Telemetry PVPArena uses bStats to get statistics about basic information like plugin version, java version, -kind of used Minecraft server, etc. You can disable it in the dedicated config file `plugins/bStats/config.yml` +kind of used Minecraft server, etc. You can disable it in the dedicated config file `/plugins/bStats/config.yml` *** From 8371f13d3c831feb603a8dd06f98e57d8f586cef Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 16 Jul 2020 21:40:33 +0200 Subject: [PATCH 080/115] v1.15 - update all docs --- doc/changelog.md | 9 -- doc/commands.md | 87 ++++++----- doc/commands/arenaclass.md | 22 +++ doc/commands/blacklist.md | 20 +-- doc/commands/check.md | 5 +- doc/commands/class.md | 13 +- doc/commands/classchest.md | 18 +-- doc/commands/create.md | 18 +-- doc/commands/debug.md | 7 +- doc/commands/disable.md | 7 +- doc/commands/edit.md | 14 ++ doc/commands/enable.md | 7 +- doc/commands/forcewin.md | 7 +- doc/commands/gamemode.md | 7 +- doc/commands/goal.md | 12 +- doc/commands/install.md | 20 --- doc/commands/join.md | 14 ++ doc/commands/modules.md | 32 ++++ doc/commands/playerjoin.md | 9 +- doc/commands/protection.md | 17 +- doc/commands/ready.md | 12 ++ doc/commands/region.md | 30 ++-- doc/commands/regionclear.md | 18 ++- doc/commands/regionflags.md | 13 +- doc/commands/regions.md | 10 +- doc/commands/regiontype.md | 51 ++---- doc/commands/reload.md | 6 +- doc/commands/remove.md | 13 +- doc/commands/round.md | 19 ++- doc/commands/set.md | 45 +++--- doc/commands/setowner.md | 9 +- doc/commands/spawn.md | 30 +++- doc/commands/start.md | 10 +- doc/commands/stats.md | 13 +- doc/commands/stop.md | 9 +- doc/commands/teams.md | 46 +++--- doc/commands/teleport.md | 14 +- doc/commands/togglemod.md | 14 +- doc/commands/uninstall.md | 17 -- doc/commands/update.md | 20 --- doc/commands/whitelist.md | 20 +-- doc/configuration.md | 14 +- doc/enhancements.md | 99 ------------ doc/faq.md | 49 ++++++ doc/getting-started.md | 28 ++-- doc/goals.md | 45 +++--- doc/goals/beacons.md | 2 +- doc/goals/blockdestroy.md | 29 ++-- doc/goals/checkpoints.md | 28 ++-- doc/goals/domination.md | 18 +-- doc/goals/flags.md | 29 ++-- doc/goals/food.md | 45 +++--- doc/goals/infect.md | 25 ++- doc/goals/liberation.md | 22 +-- doc/goals/physicalflags.md | 25 +-- doc/goals/pillars.md | 108 ++++++------- doc/goals/playerdeathmatch.md | 36 ++--- doc/goals/playerkillreward.md | 55 +++---- doc/goals/playerlives.md | 40 +++-- doc/goals/rescue.md | 45 +++--- doc/goals/sabotage.md | 34 ++-- doc/goals/tank.md | 39 +++-- doc/goals/teamdeathconfirm.md | 20 +-- doc/goals/teamdeathmatch.md | 37 ++--- doc/goals/teamlives.md | 31 ++-- doc/goals/time.md | 41 +++-- doc/history/0.1.md | 16 -- doc/history/0.10.md | 97 ------------ doc/history/0.2.md | 4 - doc/history/0.3.md | 17 -- doc/history/0.4.md | 7 - doc/history/0.5.md | 13 -- doc/history/0.6.md | 83 ---------- doc/history/0.7.md | 90 ----------- doc/history/0.8.md | 92 ----------- doc/history/0.9.md | 203 ------------------------ doc/history/1.0.md | 284 ---------------------------------- doc/history/1.1.md | 131 ---------------- doc/history/1.2.md | 78 ---------- doc/history/1.3.0.md | 66 -------- doc/history/1.3.1.md | 47 ------ doc/history/1.3.2.md | 79 ---------- doc/history/1.3.3.md | 112 -------------- doc/history/1.3.4.md | 52 ------- doc/items.md | 10 +- doc/languages.md | 20 ++- doc/mods/powerups.md | 2 +- doc/modules.md | 17 +- doc/permissions.md | 13 +- doc/regions.md | 49 ++++-- doc/update-checker.md | 15 ++ readme.md | 27 ++-- 92 files changed, 958 insertions(+), 2374 deletions(-) delete mode 100644 doc/changelog.md create mode 100644 doc/commands/arenaclass.md create mode 100644 doc/commands/edit.md delete mode 100644 doc/commands/install.md create mode 100644 doc/commands/join.md create mode 100644 doc/commands/modules.md create mode 100644 doc/commands/ready.md delete mode 100644 doc/commands/uninstall.md delete mode 100644 doc/commands/update.md delete mode 100644 doc/enhancements.md create mode 100644 doc/faq.md delete mode 100644 doc/history/0.1.md delete mode 100644 doc/history/0.10.md delete mode 100644 doc/history/0.2.md delete mode 100644 doc/history/0.3.md delete mode 100644 doc/history/0.4.md delete mode 100644 doc/history/0.5.md delete mode 100644 doc/history/0.6.md delete mode 100644 doc/history/0.7.md delete mode 100644 doc/history/0.8.md delete mode 100644 doc/history/0.9.md delete mode 100644 doc/history/1.0.md delete mode 100644 doc/history/1.1.md delete mode 100644 doc/history/1.2.md delete mode 100644 doc/history/1.3.0.md delete mode 100644 doc/history/1.3.1.md delete mode 100644 doc/history/1.3.2.md delete mode 100644 doc/history/1.3.3.md delete mode 100644 doc/history/1.3.4.md create mode 100644 doc/update-checker.md diff --git a/doc/changelog.md b/doc/changelog.md deleted file mode 100644 index c7b7f70c2..000000000 --- a/doc/changelog.md +++ /dev/null @@ -1,9 +0,0 @@ -== PVP-Arena v1.13 Changelog - -- v1.13.5 - address #355 - set some more scoreboard settings to hopefully get colors going -- v1.13.4 - various exceptions caught, addressing issues #351 and #352 -- v1.13.3 - [WIP] the core game should be operational, region setup tested, blockrestore fixed -- v1.13.2 - plugin.yml api update -- v1.13.1 - rework many things that now work differently - among those all things involving items, especially class definitions -- v1.13.0 - slowly work our way to Spigot 1.13 - diff --git a/doc/commands.md b/doc/commands.md index c365da051..a904352e8 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -1,71 +1,78 @@ -*Note that `/pvparena` and `/pa` are the same. Furthermore, those commands only work as-is if you have only one arena, OR entered edit mode with an arena if you have more than one arena: -`/pa [arenaname] edit`* +# Command list -## Command list +Click on a command to get its syntax, usage examples and more information about its working. Commands `/pvparena` and + `/pa` are the same. -Click on a command to view more information about it. +> 🚩 **Note:** +> You always have to precise your arena name in commands (like `/pa myArena enable`) except for these cases: +> - For global admin commands +> - After you joined an arena +> - When you're editing an arena (see [`/pa edit`](commands/edit.md) command) +> - When you have only one arena -### Global Admin Commands -_(Permission: pvparena.admin)_ +
+ +## Global Admin Commands + +> ℹ Permission: pvparena.admin Command | Shorthand | Definition ------------- | ------------- | ------------- -[/pa debug](commands/debug.md) | /pa !d | Debugs nodes +[/pa debug](commands/debug.md) | /pa !d | Debug nodes +[/pa modules](commands/modules.md) | /pa !mi | Manage modules [/pa reload](commands/reload.md) | /pa !r | Reload arena configs -[/pa install](commands/install.md) | /pa !i | Installs a module -[/pa uninstall](commands/uninstall.md) | /pa !ui | Uninstalls a module -[/pa update](commands/update.md) | /pa !u | Updates a module -### Arena Administration Commands +## Arena Administration Commands -_(Permission: pvparena.admin OR ownership AND pvparena.create)_ +> ℹ Permission: pvparena.admin OR both ownership and pvparena.create Command | Shorthand | Definition ------------- | ------------- | ------------- -[/pa blacklist \(or whitelist\)](commands/blacklist.md) | /pa !bl (!wl) | Manage arena blacklists or whitelists -[/pa check](commands/check.md) | /pa !ch | Checks an arena configuration +[/pa blacklist](commands/blacklist.md) | /pa !bl | Manage arena blacklists +[/pa check](commands/check.md) | /pa !ch | Check an arena configuration [/pa class](commands/class.md) | /pa !cl | Manage arena classes [/pa classchest](commands/classchest.md) | /pa !cc | Manage arena class chests -[/pa create](commands/create.md) | /pa !c | Creates an arena -[/pa disable](commands/disable.md) | /pa !dis | Disables an arena. -/pa edit | /pa !e | Toggles editing of an arena -[/pa enable](commands/enable.md) | /pa !en | Enables an arena. -[/pa forcewin](commands/forcewin.md) | /pa !fw | Forces a player/team to win. +[/pa create](commands/create.md) | /pa !c | Create an arena +[/pa disable](commands/disable.md) | /pa !dis | Disable an arena. +[/pa edit](commands/edit.md) | /pa !e | Toggle editing of an arena +[/pa enable](commands/enable.md) | /pa !en | Enable an arena. +[/pa forcewin](commands/forcewin.md) | /pa !fw | Force a player/team to win. [/pa gamemode](commands/gamemode.md) | /pa !gm | Change the general gamemode of an arena [/pa goal](commands/goal.md) | /pa !g | Manage arena goals [/pa playerjoin](commands/playerjoin.md) | /pa !pj | Make a player join -[/pa protection](commands/protection.md) | /pa !p | Manages arena protections -[/pa region](commands/region.md) | /pa !rg | Manages arena regions -[/pa regionclear](commands/regionclear.md) | /pa !rc | Manages arena region clearing exceptions -[/pa regionflags](commands/regionflags.md) | /pa !rf | Manages arena flags -[/pa regiontype](commands/regiontype.md) | /pa !rt | Changes a region type -[/pa regions](commands/regions.md) | /pa !rs | Debugs regions | ^ +[/pa protection](commands/protection.md) | /pa !p | Manage arena protections +[/pa region](commands/region.md) | /pa !rg | Manage arena regions +[/pa regionclear](commands/regionclear.md) | /pa !rc | Manage arena region clearing exceptions +[/pa regionflags](commands/regionflags.md) | /pa !rf | Manage arena flags +[/pa regiontype](commands/regiontype.md) | /pa !rt | Change a region type +[/pa regions](commands/regions.md) | /pa !rs | Debug regions [/pa reload](commands/reload.md) | /pa !rl | Reload arena configs -[/pa remove](commands/remove.md) | /pa !rm | Removes an arena. -[/pa round](commands/round.md) | /pa !rd | Manages arena rounds +[/pa remove](commands/remove.md) | /pa !rm | Remove an arena. +[/pa round](commands/round.md) | /pa !rd | Manage arena rounds [/pa set](commands/set.md) | /pa !s | Set an arena config setting [/pa setowner](commands/setowner.md) | /pa !so | Sets the owner of an arena [/pa spawn](commands/spawn.md) | /pa !sp | Manage arena spawns [/pa start](commands/start.md) | /pa !go | Force starts an arena. [/pa stop](commands/stop.md) | /pa !st | Force stops an arena. -[/pa teams](commands/teams.md) | /pa !ts | Manages arena teams -[/pa teleport](commands/teleport.md) | /pa !tp | Teleports you to an arena spawnpoint -[/pa togglemod \[module\]](commands/togglemod.md) | /pa !tm | Activates/Deactivates module +[/pa teams](commands/teams.md) | /pa !ts | Manage arena teams +[/pa teleport](commands/teleport.md) | /pa !tp | Teleport you to an arena spawnpoint +[/pa togglemod](commands/togglemod.md) | /pa !tm | Enable or disable a module for an arena +[/pa whitelist](commands/whitelist.md) | /pa !wl | Manage arena whitelists -### Arena Standard Commands +## Arena Standard Commands -_(Permission: pvparena.user (defaults to true))_ +> ℹ Permission: pvparena.user (defaults to true) Command | Shorthand | Definition ------------- | ------------- | ------------- -/pa arenaclass | /pa -ac | Changes your class, if allowed (/pa -ac [classname]) -/pa list | none | List available arenas (red: disabled, yellow: edit, green: running) -/pa chat | /pa -c | Sets arena chat mode -/pa info | /pa -i | Displays the active modules of an arena and its settings -/pa join {team} | /pa -j | Joins an arena +[/pa arenaclass](commands/arenaclass.md) | /pa -ac | Change your class, if allowed +/pa chat | /pa -c | Set arena chat mode +/pa info | /pa -i | Display the active modules of an arena and its settings /pa help | /pa -h | Basic help. Splits into subsections. +[/pa join](commands/join.md) | /pa -j | Join an arena (specifying a team or not) /pa leave | /pa -l | Leave an arena -/pa ready | /pa -r | Readys you up or lists who is ready +/pa list | none | List available arenas (red: disabled, yellow: edit, green: running) +[/pa ready](commands/ready.md) | /pa -r | Ready you up or list who is ready /pa spectate | /pa -s | Spectate an arena -[/pa stats](commands/stats.md) | /pa -s | Shows [arena/global] statistics -/pa version | /pa -v | Shows detailed version information \ No newline at end of file +[/pa stats](commands/stats.md) | /pa -s | Show [arena/global] statistics +/pa version | /pa -v | Show detailed version information \ No newline at end of file diff --git a/doc/commands/arenaclass.md b/doc/commands/arenaclass.md new file mode 100644 index 000000000..0aa812c7b --- /dev/null +++ b/doc/commands/arenaclass.md @@ -0,0 +1,22 @@ +# Arenaclass command + +## Description + +This command allow players to change their class if it's allowed. It must be typed inside an arena. + +## Usage Examples + +Command | Definition +------------- | ------------- +/pa arenaclass [className] | switch you current arena class + +Example: `/pa -ac assassin` - get the assassin class + +## Details + +You can change you class in two cases : +- Before a match, when you're waiting in lounge +- During a match if `ingameClassSwitch` arena setting is enabled + +> 🚩**Tip:** +> With `classSwitchAfterRespawn` you can delay ingame class switching on next respawn \ No newline at end of file diff --git a/doc/commands/blacklist.md b/doc/commands/blacklist.md index c84697487..eac587772 100644 --- a/doc/commands/blacklist.md +++ b/doc/commands/blacklist.md @@ -2,18 +2,20 @@ ## Description -This command manages the block place / break blacklist for an arena. +This command manages the block place / break blacklist for an arena. With this, you are able to forbid +some actions to arena players. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf blacklist clear | clear the general blacklist -/pa ctf blacklist break clear | clear the BREAK blacklist -/pa ctf blacklist break add SNOW | add SNOW to the BREAK blacklist -/pa ctf blacklist place show | show the PLACE blacklist -/pa ctf blacklist break remove SNOW | remove SNOW from the BREAK blacklist +/pa [arena] blacklist clear | clear the general blacklist +/pa [arena] blacklist [break/place] clear | clear the BREAK or the PLACE blacklist +/pa [arena] blacklist [break/place] show | show a blacklist content +/pa [arena] blacklist [break/place] add [block] | add a block to a blacklist +/pa [arena] blacklist [break/place] remove [block] | remove a block from a blacklist -## Details +Example: `/pa ctf blacklist break add SNOW` - add SNOW block to the BREAK blacklist -Both ENUMs and ITEM IDs work, you can even add DATA values, e.g. WOOL:13 \ No newline at end of file +> **🚩 Tip:** +> [`/pa whitelist`](whitelist.md) command works exactly in the same way \ No newline at end of file diff --git a/doc/commands/check.md b/doc/commands/check.md index 5d8374202..e11db105f 100644 --- a/doc/commands/check.md +++ b/doc/commands/check.md @@ -8,8 +8,9 @@ The check command basically tries to parse an arena config, in case you are unsu Command | Definition ------------- | ------------- -/pa check myArena | debug the arena "myArena" -/pa check Teams | debug the arena "Teams" +/pa check [arena] | check the config of an arena + +Example: `/pa check myArena` - debug the arena "myArena" ## Hazards diff --git a/doc/commands/class.md b/doc/commands/class.md index 198300246..ed8fee47a 100644 --- a/doc/commands/class.md +++ b/doc/commands/class.md @@ -4,13 +4,18 @@ This command manages the arena classes. You can use it to show, edit and remove arena classes. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test class load Tank | Give you the class items of the Class "Tank" of the arena "test" -/pa temp class save Test | Save your inventory to the class items of the Class "Test" of the arena "temp" -/pa team class remove Blue | Remove the class "Blue" from the arena "team" +/pa [arena] class load [class] | Preview the class items of the class directly in your inventory +/pa [arena] class save [class] | Save your inventory to the class items of a class +/pa [arena] class remove [class] | Remove a class from an arena + +Example: use `/pa temp class save Test` to save your inventory to the class "Test" of the arena "temp" + +> **🚩 Tip:** +> Type `/pa leave` to leave class preview ## Hazards diff --git a/doc/commands/classchest.md b/doc/commands/classchest.md index 1548d2f55..c16a1e556 100644 --- a/doc/commands/classchest.md +++ b/doc/commands/classchest.md @@ -2,22 +2,12 @@ ## Description -This command manages the arena class chests. You use it to define a class item chest. +If you want, you can save class inventories inside chests instead of using [/pa class](class.md) command. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test classchest Ranger | Define the chest containing the items of the class "Ranger" from the arena "test" +/pa [arena] classchest [class] | Use a chest to store items of a class. You have to look at the chest. -## Hazards - -- - -## Details - -Look at a chest you want to set - -## ToDo - -- \ No newline at end of file +Example: `/pa test classchest Ranger` - Define the chest containing the items of the class "Ranger" from the arena "test". \ No newline at end of file diff --git a/doc/commands/create.md b/doc/commands/create.md index d7bff3c89..d0b2ceb89 100644 --- a/doc/commands/create.md +++ b/doc/commands/create.md @@ -4,22 +4,10 @@ The create command basically creates a standard, boring, arena. Given legacy types enhance this, but still you will probably want to customize your arena and definately continue setting it up by setting spawn points. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa create teamArena | create a standard Teams Arena -/pa create capture ctf | create a Capture The Flag Arena called "capture" +/pa create [arenaName] (free) | Create an arena. Arena uses team gamemode by default, add `free` parameter to use FFA gamemode instead. -## Details - -In order to have a quicker start when setting up an arena, you can use the oldschool legacy types, which will be supported until v2.0 I guess. Those types add pre-definitions to define how the arena works in general. You can still go ahead and adjust the goal setup to your needs! - -Valid legacy types include: - -- ctf -- free -- ctp -- sabotage -- tank -- spleef \ No newline at end of file +Example: `/pa create ffa free` - create a free for all arena named "ffa" \ No newline at end of file diff --git a/doc/commands/debug.md b/doc/commands/debug.md index b0b3458c4..cd0106de4 100644 --- a/doc/commands/debug.md +++ b/doc/commands/debug.md @@ -4,15 +4,16 @@ The debug command is used to spam the log file with a hell lot more of information, based on your current issue, or just in general when unsure where the issue comes from. -## Usage Examples +## Usage Command | Definition ------------- | ------------- /pa debug all | debug ALL classes -/pa debug 4 | debug class number 4 -/pa debug 4,7 | debug class 4 and 7 +/pa debug [value] | debug class or arena where name equals to `value` /pa debug none | disable debugging +Example: `/pa debug 4,7` - debug class 4 and 7 + ## Hazards The way PVP Arena debugs is known to **spam** a LOT. This rises exponentially the more people you have on. So if you want to debug and are unsure if you're debugging the right thing, diff --git a/doc/commands/disable.md b/doc/commands/disable.md index 8074a9853..e38a046b2 100644 --- a/doc/commands/disable.md +++ b/doc/commands/disable.md @@ -4,12 +4,13 @@ This command disables arenas, force stopping them in the first place. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test disable | disable the "test" arena -/pa temp disable | disable the "temp" arena +/pa [arena] disable | disable an arena + +Example: `/pa test disable` - disable the "test" arena ## Details diff --git a/doc/commands/edit.md b/doc/commands/edit.md new file mode 100644 index 000000000..cf656932e --- /dev/null +++ b/doc/commands/edit.md @@ -0,0 +1,14 @@ +# Edit command + +## Description + +The edit command switch your arena in edit mode. That temporarily closes your arena and allows you to type +any arena command without precising arena name. + +## Usage Examples + +Command | Definition +------------- | ------------- +/pa [arena] edit | toggle the edit mode of an arena + +Example: `/pa ctf edit` - enable or disable edit mode for "ctf" arena \ No newline at end of file diff --git a/doc/commands/enable.md b/doc/commands/enable.md index bcd700477..59b2ed1bd 100644 --- a/doc/commands/enable.md +++ b/doc/commands/enable.md @@ -4,10 +4,11 @@ This command re-enables an arena after disabling it. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test enable | enable the **"test"** arena -/pa temp enable | enable the **"temp"** arena +/pa [arena] enable | disable an arena + +Example: `/pa test enable` - enable the "test" arena diff --git a/doc/commands/forcewin.md b/doc/commands/forcewin.md index 9d92de2eb..ab0e57bee 100644 --- a/doc/commands/forcewin.md +++ b/doc/commands/forcewin.md @@ -4,10 +4,11 @@ This command forces a player/team to win. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test !fw slipcor | Make **slipcor** the winner in the **"test"** arena -/pa temp forcewin red | Make team **red** the winner in the **"temp"** arena +/pa [arena] forcewin [player/team] | Force a player or a team to win + +Example: `/pa temp forcewin red` - Make team **red** the winner in the **"temp"** arena diff --git a/doc/commands/gamemode.md b/doc/commands/gamemode.md index 8462fd2fb..9602b6b1a 100644 --- a/doc/commands/gamemode.md +++ b/doc/commands/gamemode.md @@ -4,11 +4,12 @@ The gamemode defines the general play mode. Free For All or Team Play ? -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf gamemode team | set the gamemode of arena "ctf" to "team" -/pa ffa !gm free | set the gamemode of arena "ffa" to "free" +/pa [arena] gamemode [team/free] | Change gamemode of an arena + +Example: `/pa ffa gamemode free` - set the gamemode of arena "ffa" to "free" ## Details diff --git a/doc/commands/goal.md b/doc/commands/goal.md index 919428e27..1721c9cdc 100644 --- a/doc/commands/goal.md +++ b/doc/commands/goal.md @@ -4,16 +4,20 @@ The goal command is used to activate certain goals, to enhance your arena or disable goals to narrow down the goals. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free goal Time | Enable the goal "Time" for the arena "free" -/pa ctf !g Time off | Disable the goal "Time" for the arena "ctf" +/pa [arena] goal [goal] (true/false) | Toggle a goal for an arena + +Example: `/pa free goal Time` - Enable the goal "Time" for the arena "free" ## Details You will receive a list of valid (installed) arena goals when trying to activate an unknown goal, so e.g. /pa [arenaname] !g list will show you possible goals. Giving no second argument will just toggle the goal status and show you the result, valid arguments to activate/deactivate include: -on | 1 | true || off | 0 | false \ No newline at end of file +on | 1 | true || off | 0 | false + +> 🚩 **Tip:** +> You can see active goals of your arena with command `/pa [arena] info` \ No newline at end of file diff --git a/doc/commands/install.md b/doc/commands/install.md deleted file mode 100644 index 86090bb44..000000000 --- a/doc/commands/install.md +++ /dev/null @@ -1,20 +0,0 @@ -# Install command - -## Description - -This command manages installation of modules. You can list available modules, see your current state, and install new modules. - -## Usage Examples - -Command | Definition -------------- | ------------- -/pa install | list all available modules -/pa install worldedit | install the worldedit module - -## Hazards - -Know your versions. If unsure, download the latest zip file from the files section, replace the files inside /files and then you can be sure you're up to date. Outdated modules lead to errors. - -## Details - -The list contains all available modules, with their respective version. Yellow names mark installed plugins, green version numbers mark as up to date, red version numbers show that you need to update the files. \ No newline at end of file diff --git a/doc/commands/join.md b/doc/commands/join.md new file mode 100644 index 000000000..74988e862 --- /dev/null +++ b/doc/commands/join.md @@ -0,0 +1,14 @@ +# Join command + +## Description + +Use this command to join an arena. You can specify a team. + + +## Usage Examples + +Command | Definition +------------- | ------------- +/pa [arena] join (team) | join a arena + +Example: `/pa ctf join blue` - join the blue team of "ctf" arena \ No newline at end of file diff --git a/doc/commands/modules.md b/doc/commands/modules.md new file mode 100644 index 000000000..b7cde8e37 --- /dev/null +++ b/doc/commands/modules.md @@ -0,0 +1,32 @@ +# Install command + +## Description + +This command manages modules. You can list installed modules, download latest version, install, uninstall, update and +upgrade your modules. + +## Usage + +Command | Definition +------------- | ------------- +/pa modules (list) | list all available modules (installed modules are highlighted) +/pa modules install [moduleName] | install a module (from the `files` folder) +/pa modules uninstall [moduleName] | uninstall a module (removing from `mods` folder) +/pa modules update | update all modules in `mods` folder with versions which are in `files` folder +/pa modules download | download latest release of modules pack and place it in `files` folder +/pa modules upgrade | upgrade all your modules (perform a download and an update) + + +## Directory management + +In order to increase performances, PVP Arena has two directories for mods: +- `/mods` contains only mods used in arenas and installed by admins +- `/files` contains all downloaded mods + +When you install a mod, the plugin copies it from `/files` to `/mods`. + + +## Details + +The result of list command contains all available modules, with their respective version. Yellow names mark installed +plugins, green version numbers mark as up to date, red version numbers show that you need to update the files. \ No newline at end of file diff --git a/doc/commands/playerjoin.md b/doc/commands/playerjoin.md index 544a05b5e..9fcd467ff 100644 --- a/doc/commands/playerjoin.md +++ b/doc/commands/playerjoin.md @@ -2,12 +2,13 @@ ## Description -This command force joins an online player into an arena. You can specify an arena team, or not. Just as the player would join the game. In fact it "makes the player call the join command" ;) +This command forces an online player to join an arena. You can specify an arena team, or not. Just as the player would join the game. In fact it "makes the player call the join command" ;) -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf playerjoin slipcor | make slipcor join the CTF arena, random team -/pa ctf !pj valera blue | make valera join the CTF arena, team blue +/pa [arena] playerjoin [player] (team) | force a player to join an arena + +Example: `/pa ctf !pj valera blue` - make valera join the CTF arena, team blue diff --git a/doc/commands/protection.md b/doc/commands/protection.md index 28f2c6391..64b8e406d 100644 --- a/doc/commands/protection.md +++ b/doc/commands/protection.md @@ -2,18 +2,20 @@ ## Description -Manage protections of a certain arena region +Manage protections of a certain [arena region](../regions.md). **When a protection is enabled, player actions +are prevented.** -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa main protection battlefield DROP | toggle the DROP protection of the arena "main"s region called "battlefield" -/pa hunger !p battlefield INVENTORY true | enable the INVENTORY protection of the arena "hunger"s region called "battlefield" +/pa [arena] protection [region] [protection] (true/false) | toggle a protection of an arena region + +Example: `/pa main protection battlefield DROP` - toggle the DROP protection of the arena "main"s region called "battlefield" ## Details -Erroneous protection flag usage will show you the supported flags, they include: (definition: when active) +Here is a quick list supported flags, they include: - BREAK - prevent player block breaking - FIRE - prevent fire spreading/burning @@ -29,4 +31,7 @@ Erroneous protection flag usage will show you the supported flags, they include: - PICKUP - prevent player item pickup - TELEPORT - prevent player teleportation -Always verify your protections with `/pa [arenaname] !rs [regionname]` \ No newline at end of file +
+ +> **🚩 Tip:** +> Check your protections with [`/pa [arenaname] !rs [regionname]`](regions.md) diff --git a/doc/commands/ready.md b/doc/commands/ready.md new file mode 100644 index 000000000..fe989dd00 --- /dev/null +++ b/doc/commands/ready.md @@ -0,0 +1,12 @@ +# Ready Command + +## Description + +This command passes players to "ready" state or lists ready players. It must be typed inside an arena. + +## Usage + +Command | Definition +------------- | ------------- +/pa ready | pass a player in "ready" state +/pa ready list | list ready players in current arena \ No newline at end of file diff --git a/doc/commands/region.md b/doc/commands/region.md index 2dfe4f8e5..17fab65be 100644 --- a/doc/commands/region.md +++ b/doc/commands/region.md @@ -2,26 +2,30 @@ ## Description -Set up regions for an arena. Oh, and show their borders. ... and set some WIP values +Manage regions for an arena. More information is available [on dedicated page](../regions.md). -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free region | start setting up a region for the arena "free" -/pa free !r ball | save the cuboid region "ball" to the arena "free" -/pa ctf !r X spher | save the spheric region "X" to the arena "ctf" -/pa ctf !r remove X | remove the region "X" from the arena "ctf" -/pa free !r ball border | shows the border around the region "ball" of the arena "free" - +/pa [arena] region | start setting up a region for an arena (type again to leave region editor) +/pa [arena] region [regionName] (shape) | save a region for the arena. Cuboid is the default shape +/pa [arena] region [regionName] remove | remove an arena region +/pa [arena] region [regionName] border | show limits of a region + +Example: +- `/pa free !r ball` - save the cuboid region "ball" to the arena "free" +- `/pa ctf !r X remove` - remove the region "X" from the arena "ctf" ## Details +If we have to sum up, setting up an arena needs 3 things: + +- `/pa [arenaname] region` +- select two points that define the region +- `/pa [arenaname] region [regionshape]` -For a better display of HOW to setup regions, you might want to check out our tutorial section. -Setting up an arena needs 3 things: +Check out [our tutorial section](../regions.md) for more information. -`/pa [arenaname] region` -select two points that define the region -`/pa [arenaname] region [regionshape]` +
Valid regionshapes include: diff --git a/doc/commands/regionclear.md b/doc/commands/regionclear.md index b003f99ab..d1afde40b 100644 --- a/doc/commands/regionclear.md +++ b/doc/commands/regionclear.md @@ -2,20 +2,24 @@ ## Description -This command manages the regions' clearing behaviour by adding/removing exceptions. +By default, at the end of a match, all entities are removed from [arena regions](../regions.md). If you want to keep some kind of entities +(like armor stands for instance), you can manage an exception list with this command. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf regionclear VILLAGER | toggle the VILLAGER clearing of the arena "ctf" -/pa ctf !rc TNT true | enable the TNT clearing exception of the arena "ctf" (ALLOW TNT to stay after clearing!) +/pa [arena] regionclear [entity] (true/false) | toggle entity clearing of an arena -## Details -Valid entitytypes will be told when you mistype, or you can find them here: +Example: +- `/pa ctf regionclear VILLAGER` - toggle the VILLAGER clearing of the arena "ctf" +- `/pa ctf !rc TNT true` - add a clearing exception for TNT in the arena "ctf" (ALLOW TNT to stay after clearing!) + +## Details -https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html +Valid entitytypes will be told when you mistype, or you can find them +[on this page](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html). Giving no second argument will just toggle exception status and show you the result, valid arguments to activate/deactivate include: diff --git a/doc/commands/regionflags.md b/doc/commands/regionflags.md index 53020dcd0..0cebace49 100644 --- a/doc/commands/regionflags.md +++ b/doc/commands/regionflags.md @@ -2,14 +2,15 @@ ## Description -This command manages the regions' behaviour by enabling/disabling flags. +This command manages the [regions](../regions.md) behaviour by enabling/disabling flags. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf regionflag death1 DEATH | toggle the DEATH regionflag for the region "death1" of the arena "ctf" -/pa ctf !rf win2 WIN true | enable the WIN regionflag for the region "win2" of the arena "ctf" +/pa [arena] regionflag [region] [flag] (true/false) | toggle regionflag for an arena region + +Example: `/pa ctf !rf win2 WIN true` - enable the WIN regionflag for the region "win2" of the arena "ctf" ## Details @@ -17,8 +18,8 @@ There are several region flags that can be set: - NOCAMP - move in here, or get punished ! - DEATH - come in, die ! -- WIN - come in, WIN ! -- LOSE - come in, LOSE ! +- WIN - come in, win ! +- LOSE - come in, lose ! - NODAMAGE - players are invincible ! Giving no second argument will just toggle the flag status and show you the result, valid arguments to activate/deactivate include: diff --git a/doc/commands/regions.md b/doc/commands/regions.md index 150a8ae05..0f103173a 100644 --- a/doc/commands/regions.md +++ b/doc/commands/regions.md @@ -2,14 +2,16 @@ ## Description -This command displays a list of arena regions / their properties. +This command displays a list of arena [regions](../regions.md) / their properties. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free regions | list all arena regions of "free", and their shape and type -/pa free !rs ball | debug print properties of the region "ball" of the arena "free" +/pa [arena] regions | list all regions of an arena +/pa [arena] regions [region] | display properties of a given arena region + +Example: `/pa free !rs ball` - print properties of the region "ball" of the arena "free" ## Details diff --git a/doc/commands/regiontype.md b/doc/commands/regiontype.md index ca630b3ee..c87d812f0 100644 --- a/doc/commands/regiontype.md +++ b/doc/commands/regiontype.md @@ -2,47 +2,28 @@ ## Description -This command sets the region type which is essential for its functionality. +This command sets the [region](../regions.md) type which is essential for its functionality. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf regiontype exit EXIT | set the "ctf" region "exit" type to EXIT -/pa ctf !rt battlefield BATTLE | set the "ctf" region "battlefield" to BATTLE +/pa [arena] regiontype [region] [type] | change the type of an arena regions + +Example: `/pa ctf !rt battlefield BATTLE` - set the "ctf" region "battlefield" to BATTLE ## Details The region types include: -- CUSTOM => a default / module added region -- WATCH => the spectator region -- LOUNGE => the ready lounge region -- BATTLE => the battlefield region -- EXIT => the exit region -- JOIN => the join region -- SPAWN => the spawn region -- BL_INV => blacklist inventory access -- WL_INV => whitelist inventory access - -### BL_INV - -This region type blocks chest access for every team whichs name is in the region name, same for classes - -example names: - -`xxbluexx` => disallows the blue team -`RedSwordsman` => disallows the red team and any Swordsman - -### WL_INV - -This region type restricts chest access to teams / classes which names are part of the region name - -example names: - -`RedBlueRanger` => allows Red and Blue and Rangers to access chests -`%infected%` => allows the infected (class) to access chests - -## Todo - -add functionality like protection to the other region types +- CUSTOM +- WATCH +- LOUNGE +- BATTLE +- EXIT +- JOIN +- SPAWN +- BL_INV +- WL_INV + +Usage of each region type is detailed on [region documentation page](../regions.md#region-types). diff --git a/doc/commands/reload.md b/doc/commands/reload.md index bb926f514..702e4599a 100644 --- a/doc/commands/reload.md +++ b/doc/commands/reload.md @@ -5,13 +5,15 @@ The reload command does what you might think it does. It reloads the arena by force stopping it, removing it from the arena list, and loading it from the config definition. If you don't specify an arena and are not part of an arena, this command reloads all arenas. -## Usage Examples +## Usage Command | Definition ------------- | ------------- /pa reload | reload everything or the arena you're part of /pa reload ymls | reload main config, language and help ymls -/pa reload CTF | reload the arena called CTF +/pa [arena] reload | reload a specific arena + +Example: `/pa ctf reload` - reload the arena called CTF ## Details diff --git a/doc/commands/remove.md b/doc/commands/remove.md index 959e2cfac..7f087d7a4 100644 --- a/doc/commands/remove.md +++ b/doc/commands/remove.md @@ -4,17 +4,16 @@ This command does only one thing: Remove the arena. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test remove | remove the "test" arena -/pa temp remove | remove the "temp" arena +/pa [arena] remove | remove an arena -## Hazards -Well, once you did that, the file is gone. So when unsure, either make backups or use disable instead of remove. +Example: `/pa test remove` - remove the "test" arena -## Todo +## Hazards -Maybe some day I'll add a confirmation that tells you about the fact that the arena will be gone "for a long time" ;) +Well, once you did that, the associated file is deleted. So when unsure, either make backups or use +[disable](disable.md) command instead of remove. \ No newline at end of file diff --git a/doc/commands/round.md b/doc/commands/round.md index 3fddb978b..1a2e8bf89 100644 --- a/doc/commands/round.md +++ b/doc/commands/round.md @@ -1,20 +1,23 @@ # Round Command +> ⚠ This command has NOT been tested at ALL! Use at your own risks. + ## Description This command is a WIP to manage "round behaviour" in arenas. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free round | list rounds of arena "free" -/pa free round 1 | list goals of round 1 of arena "free" -/pa free round 1 Tank | Toggle the Tank goal for the first round of the arena "free" - -## Hazards - -This command has NOT been tested at ALL! This should be warning enough oO +/pa [arena] round | list rounds of an arena +/pa [arena] round [roundNumber] | list goals of an arena round +/pa [arena] round [roundNumber] [goal] | toggle a specific goal for a round of an arena + +Example: +- `/pa free round` - list rounds of arena "free" +- `/pa free round 1 ` - list goals of round 1 of arena "free" +- `/pa free round 1 Tank` - toggle the Tank goal for the first round of the arena "free" ## Details diff --git a/doc/commands/set.md b/doc/commands/set.md index 671795645..0da503543 100644 --- a/doc/commands/set.md +++ b/doc/commands/set.md @@ -2,30 +2,37 @@ ## Description -Sets a specific config node, or lists possible nodes. +Sets a specific config node of an arena configuration, or lists possible nodes. +It's an alternative to manually edit your config files. -## Usage Examples +> ⚠ If you mess up you might change the wrong node, erase parts of the config and render your config useless. +So only use this if you know what you're doing. + +## Usage Command | Definition ------------- | ------------- -/pa test set 0 | get the first page of the arena "test" -/pa test set minPlayers 5 | requires the "test" arena to have 5 players before starting - -## Hazards +/pa [arena] set [pageNumber] | show a list of editable config nodes of your arena +/pa [arena] set [configNode] [value] | edit the value of an arena config node -If you mess up you might change the wrong node, erase parts of the config and render your config useless. So only use this if you know what you're doing. +Examples : +- `/pa test set 0` - get the first page of editable nodes of the arena "test" configuration +- `/pa test set minPlayers 5` - require the "test" arena to have 5 players before starting ## Details -A number as only argument lists that page, a node and value tries to set the config node to the given value. - -You know know what the node types on the pages mean, but here they are: - -- boolean - true or false -- string - a word -- int - a whole number -- double - a decimal (e.g. 0.5) -- tp - a spawn point (exit, old, spectator) -- item - a bukkit ENUM or ID of a material -- items - e.g. class items, see the corresponding page about item definitions - +The value of a configuration node depends on its type. These types are show when you use `/pa [arena] set [pageNumber]`. +However, it's quite simple to guess a node type. +There are severals categories of types and here is how to set them : +- **boolean:** Quite simple, just type `true` or `false` +- **numbers:** They can be integer or floating-point numbers. Just type them after the name of your config node +- **string:** The easiest, just type the word you want. +- **material:** The name of a bukkit material. You can directly type material names picked from +[this list](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html) or type `hand` to get items you're +holding in your hand. +- **items:** A list of items is expected (for instance to give rewards). Type `inventory` to convert all your current +inventory to a list of items (metadata will be saved) or use `hand` get only get the item you're holding. + +> 🚩 **NB:** +> If you want to define items or material nodes directly in your config file, please check +>[this documentation](../items.md). \ No newline at end of file diff --git a/doc/commands/setowner.md b/doc/commands/setowner.md index 7f01ac749..117c1eaf2 100644 --- a/doc/commands/setowner.md +++ b/doc/commands/setowner.md @@ -2,12 +2,15 @@ ##Description -This command hands over ownership. This has to be either "%server%" or a player name. Note that the player name is NOT checked, but you can verify it with `/pa info` +This command hands over ownership. This has to be either "%server%" or a player name. Note that the player name is +NOT checked, but you can verify it with [`/pa info`](../commands.md#arena-standard-commands) ##Usage Examples Command | Definition ------------- | ------------- -/pa slip setowner slipcor | give slipcor ownership of the arena "slip" -/pa global setowner %server% | remove player ownership from the arena "global", set the server as owner +/pa [arena] setowner [player] | give player ownership of an arena + + +Example: `/pa global setowner %server%` - set the server as owner of the "global" arena diff --git a/doc/commands/spawn.md b/doc/commands/spawn.md index 9c9262d7b..1766a775d 100644 --- a/doc/commands/spawn.md +++ b/doc/commands/spawn.md @@ -4,22 +4,36 @@ Set an arena spawn to your current position, including orientation ! -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf spawn redspawn | sets the red team's spawn of the arena "ctf" -/pa free spawn spawnEAST | sets "spawnEAST" of the arena "free" +/pa [arena] spawn [spawnName] | Define a spawn for an arena + + +Example: +- `/pa ctf spawn redspawn` - sets the red team's spawn of the arena "ctf" +- `/pa free spawn spawnEAST` - sets "spawnEAST" of the arena "free" ## Details -If you get a message "spawn unknown", this is probably because you did not install / activate a goal / module ; be sure that you install and activate stuff you want to add, -e.g. the "Flags" goal, or the "StandardSpectate" module... +There are two syntax according to the [gamemode](gamemode.md) of your arena : +- If you're using a "free" arena, you can define unlimited spawns using syntax `/pa myArena spawn spawnX` where X should + be anything (word, digit, letter, etc). +- If your arena works with teams, you have to use `/pa myArena spawn teamspawn` where "team" is the name of one of your +team. + + +If you get a message "spawn unknown", this is probably because you did not install/activate a [goal](../goals.md) or +a [module](../modules.md). +Be sure you have installed and activated stuff you want to add, for instance the "Flags" goal, or the "StandardSpectate" +module... ## Spawn Offset -Since v1.3.1.31 you can define unique offsets for each spawn name, in order to not be placed on the block center but rather one edge: +You can define unique offsets for each spawn name, in order to not be placed on the block center but rather one edge: -- /pa {arenaname} spawn [spawnname] offset X Y Z +- `/pa [arena] spawn [spawnname] offset X Y Z` -For example 0.5 0 0.5 as X Y Z would work setting you on an edge. You might want to keep F3 at hand to see if you actually have to add or subtract to get to the right edge. \ No newline at end of file +For example 0.5 0 0.5 as X Y Z would work setting you on an edge. +You might want to keep F3 at hand to see if you actually have to add or subtract to get to the right edge. \ No newline at end of file diff --git a/doc/commands/start.md b/doc/commands/start.md index 323f5cbca..f471aa23e 100644 --- a/doc/commands/start.md +++ b/doc/commands/start.md @@ -4,13 +4,17 @@ This command force starts an arena for testing purposes or when players don't manage to get ready on their own. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test start | force start the arena called "test" +/pa [arena] start | force start an arena + +Example: +- `/pa test start` - force start the arena called "test" ## Hazards -If you start a game with only one player, the results may vary depending on the goals and the environment. You should know what you're doing ;) \ No newline at end of file +If you start a game with only one player, the results may vary depending on the goals and the environment. +You should know what you're doing ;) \ No newline at end of file diff --git a/doc/commands/stats.md b/doc/commands/stats.md index c6dd93c06..094669396 100644 --- a/doc/commands/stats.md +++ b/doc/commands/stats.md @@ -4,14 +4,19 @@ This command displays the top X players in a specific statistics type. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa stats LOSSES | shows the top 10 losers -/pa stats WINS 5 | shops the top 5 winners +/pa stats [statistic] (number) | show top 10 of a statistic for all the server. Change results size with "number" parameter. +/pa [arena] stats [statistic] (number) | show top 10 of a statistic for current arena game -Valid values are : +Examples: +- `/pa ctf stats DAMAGE` - shows the top 10 player damaged for the current CTF game +- `/pa stats WINS 5` - shops the top 5 winners for all the server + +## Details +Valid statistic values are : - WINS - LOSSES diff --git a/doc/commands/stop.md b/doc/commands/stop.md index 20886f829..81d4a1204 100644 --- a/doc/commands/stop.md +++ b/doc/commands/stop.md @@ -4,13 +4,12 @@ This command force stops an arena in case players are stuck / the game freezes and so on. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa test stop | force stop the arena called "test" +/pa [arena] stop | force stop an arena -## Hazards - -Should be clear, but... players will lose eventual game status that goals might offer. The arena game will start from scratch ;) \ No newline at end of file +Example: +- `/pa test stop` - force stop the arena called "test" \ No newline at end of file diff --git a/doc/commands/teams.md b/doc/commands/teams.md index 2df025e95..cc07e96fa 100644 --- a/doc/commands/teams.md +++ b/doc/commands/teams.md @@ -4,32 +4,38 @@ The teams command adds team management. Add, set and remove teams! -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa *(arena)* teams set blue GREEN | Set the blue team's color to green -/pa *(arena)* teams add yellow YELLOW | Add a yellow team -/pa *(arena)* teams remove blue | Remove the blue team -/pa *(arena)* teams | list all teams +/pa [arena] teams add [team] [color] | Add a new team to an arena +/pa [arena] teams set [team] [color] | Set color to existing team +/pa [arena] teams remove [team] | Remove a team +/pa [arena] teams | list all teams + +Examples: +- `/pa test teams set blue GREEN` - Set the blue team's color to green in the arena "test" +- `/pa ctf teams add yellow YELLOW` - Add a yellow team to the "ctf" arena ## Details You will need a proper color as a value. The possible colors are as follows: -- WHITE -- ORANGE -- MAGENTA -- LIGHT_BLUE -- YELLOW -- LIME -- PINK -- GRAY -- SILVER -- CYAN -- PURPLE -- BLUE -- GREEN -- RED -- BLACK +- AQUA +- BLACK +- BLUE +- DARK_AQUA +- DARK_BLUE +- DARK_GRAY +- DARK_GREEN +- DARK_PURPLE +- DARK_RED +- GOLD +- GRAY +- GREEN +- LIGHT_PURPLE +- RED +- WHITE +- YELLOW + diff --git a/doc/commands/teleport.md b/doc/commands/teleport.md index 5e0f024de..baf8f3f2e 100644 --- a/doc/commands/teleport.md +++ b/doc/commands/teleport.md @@ -2,19 +2,19 @@ ## Description -Teleports you to a specific spawn point of an arena. +Teleports you to a specific spawn point of an arena. This command should be for administration purpose and +not during game. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free teleport spawn2 | teleport to the spawn "spawn2" of arena "free" -/pa free teleport spawn | teleport to a random spawn of arena "free" -/pa ctf !tp bluespawn | teleport to the blue spawn of arena "ctf" +/pa [arena] teleport [spawnPoint] | teleport to a spawn point of an arena -## Hazards +Examples: +- `/pa free teleport spawn` - teleport to a random spawn of arena "free" +- `/pa ctf !tp bluelounge` - teleport to the blue lounge of arena "ctf" -You might not want to do that ingame unless you're godded ;) ## Details diff --git a/doc/commands/togglemod.md b/doc/commands/togglemod.md index a078af80b..006979744 100644 --- a/doc/commands/togglemod.md +++ b/doc/commands/togglemod.md @@ -4,18 +4,16 @@ Toggles a module on or off. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa free togglemod BattleGears | Toggles mod "BattleGears" in arena "free" -/pa ctf togglemod StandardSpectate | Toggles mod "Standard Spectate" in arena "ctf" -/pa ctf !tm WorldEdit | Toggles mod "WorldEdit" in arena "ctf" +/pa [arena] togglemod [module] | Toggles a mod for an arena -## Hazards - -You may need to restart your server for some mods to hook or take effect. +Example: +- `/pa ctf !tm WorldEdit` - Toggles mod "WorldEdit" in "ctf" arena ## Details -Toggling a mod allows you to simply change if a module is active or not. You can do further setting tweaks using the module-specific command or `/pa set` \ No newline at end of file +Toggling a mod allows you to simply change if a module is active or not. +You can do further setting tweaks using the module-specific command or [`/pa set`](set.md). \ No newline at end of file diff --git a/doc/commands/uninstall.md b/doc/commands/uninstall.md deleted file mode 100644 index 10c062734..000000000 --- a/doc/commands/uninstall.md +++ /dev/null @@ -1,17 +0,0 @@ -# Uninstall command - -## Description - -This command manages removal of modules. You can list available modules, see your current state, and remove installed modules. - -## Usage Examples - -Command | Definition -------------- | ------------- -/pa uninstall | list all available modules -/pa uninstall worldedit | uninstall the worldedit module - -## Details - -The list contains all available modules, with their respective version. Yellow names mark installed plugins, green version numbers mark as up to date, -red version numbers show that you need to update the files. \ No newline at end of file diff --git a/doc/commands/update.md b/doc/commands/update.md deleted file mode 100644 index 4b8758513..000000000 --- a/doc/commands/update.md +++ /dev/null @@ -1,20 +0,0 @@ -# Update command - -## Description - -This command manages updating of modules. You can list available modules, see your current state, and update modules. - -## Usage Examples - -Command | Definition -------------- | ------------- -/pa update | list all available modules -/pa update worldedit | update the worldedit module - -## Hazards - -Know your versions. If unsure, download the latest zip file from the files section, replace the files inside /files and then you can be sure you're up to date. Outdated modules lead to errors. - -## Details - -The list contains all available modules, with their respective version. Yellow names mark installed plugins, green version numbers mark as up to date, red version numbers show that you need to update the files. \ No newline at end of file diff --git a/doc/commands/whitelist.md b/doc/commands/whitelist.md index 695f54edf..4114f6a34 100644 --- a/doc/commands/whitelist.md +++ b/doc/commands/whitelist.md @@ -2,18 +2,20 @@ ## Description -This command manages the block place / break whitelist for an arena. +This command manages the block place / break whitelist for an arena. With this, you're able to restrict actions +in your arena. -## Usage Examples +## Usage Command | Definition ------------- | ------------- -/pa ctf whitelist clear | clear the general whitelist -/pa ctf whitelist break clear | clear the BREAK whitelist -/pa ctf whitelist break add SNOW | add SNOW to the BREAK whitelist -/pa ctf whitelist PLACE show | show the PLACE whitelist -/pa ctf whitelist break remove SNOW | remove SNOW from the BREAK whitelist +/pa [arena] whitelist clear | clear the general whitelist +/pa [arena] whitelist [break/place] clear | clear the BREAK or the PLACE whitelist +/pa [arena] whitelist [break/place] show | show a whitelist content +/pa [arena] whitelist [break/place] add [block] | add a block to a whitelist +/pa [arena] whitelist [break/place] remove [block] | remove a block from a whitelist -## Details +Example: `/pa ctf whitelist break add SNOW` - add SNOW block to the BREAK whitelist -Both ENUMs and ITEM IDs work, you can even add DATA values, e.g. WOOL:13 \ No newline at end of file +> **🚩 Tip:** +> [`/pa blacklist`](blacklist.md) command works exactly in the same way \ No newline at end of file diff --git a/doc/configuration.md b/doc/configuration.md index 66193d3b0..924ff6a3d 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -1,6 +1,10 @@ -# Configuration File +# Configuration file + +This page explains what are each parameter of arena config file. +All those parameters can be changed via in-game command ([/pa set](commands/set.md)). + +> ℹ This is a default configuration file. -This is a default configuration file. All parameters can be changed via in-game commands ([/pa set](commands/set.md)). ```yaml configversion: 1.3.3.217 chat: @@ -8,7 +12,7 @@ chat: defaultTeam: false #Limit chat to team only enabled: true #Allows chat usage onlyPrivate: false #Limit chat to the arena - toGlobal: none #Begin word to talk to all the arena of onlyPrivate is active. Eg: @all + toGlobal: none #Begin word to talk to all the arena of onlyPrivate is active. E.g. @all cmds: defaultjoin: true #Join the arena if just typing /pa #List of allowed commands in the arena @@ -22,9 +26,9 @@ damage: spawncamp: 1 #If nocamp region flag is enabled, damage set to player weapons: true #Allow weapon damage - false = unbreakable general: - classspawn: false #Create specific class spawns. Eg: blueTankSpawn + classspawn: false #Create specific class spawns. E.g. blueTankSpawn classSwitchAfterRespawn: false #If IngameClassSwitch is enabled, switch class only on next respawn - customReturnsGear: false #If player has custom inventory, reload it on respawn + customReturnsGear: false #If player has custom inventory, reload it after the match enabled: true #Make arena accessible or not gm: 0 #Arena game mode leavedeath: false #Kill the player on battleground leaving diff --git a/doc/enhancements.md b/doc/enhancements.md deleted file mode 100644 index e9cd1092b..000000000 --- a/doc/enhancements.md +++ /dev/null @@ -1,99 +0,0 @@ -There are currently four ways of adding to the game: -# PVP Arena API - -The API features basic access to several things, based on very few requests. If you need something, give me a shout! -## PVP Arena Modules - -### Installation - -Unzip the module files (files tab, "PA Files v\*.\*.\*") into the /pvparena/files folder and install them via -`/pa install [modname]`, **activate per arena via** -`/pa [arenaname] !tm [modname]` - -### PVP Arena Goals - -Create ways to win the game or lose the game! - -Goal | Description -------------- | ------------- -[Beacons](goals/beacons.md) | Stand near beacons and claim them to win! -[BlockDestroy](goals/blockdestroy.md) | Destroy blocks (pre-installed) -[CheckPoints](goals/checkpoints.md) | Reach checkpoints in order to win (pre-installed) -[Domination](goals/domination.md) | Dominate flag positions (pre-installed) -[Flags](goals/flags.md) | Capture flags and bring 'em home (pre-installed) -[Food](goals/food.md) | Cook food and bring it home (pre-installed) -[Infect](goals/infect.md) | Infect people to win / kill infected players (pre-installed) -[Liberation](goals/liberation.md) | Jail dead players, possibility to unjail! (pre-installed) -[PhysicalFlags](goals/physicalflags.md) | Capture flags physically and bring 'em home (pre-installed) -[Pillars](goals/pillars.md) | Capture pillars by clicking/destroying! -[PlayerDeathMatch](goals/playerdeathmatch.md) | Player kills win (pre-installed) -[PlayerKillReward](goals/playerkillreward.md) | Player get better gears when killing (pre-installed) -[Rescue](goals/rescue.md) | Rescue a trapped Entity -[PlayerLives](goals/playerlives.md) | Player deaths lose (pre-installed) -[Sabotage](goals/sabotage.md) | Ignite TNT (pre-installed) -[Tank](goals/tank.md) | all vs one (pre-installed) -[TeamDeathConfirm](goals/teamdeathconfirm.md) | Confirmed Team kills win (pre-installed) -[TeamDeathMatch](goals/teamdeathmatch.md) | Team kills win (pre-installed) -[TeamLives](goals/teamlives.md) | Team deaths lose (pre-installed) -[Time](goals/time.md) | Time ends the arena (pre-installed) - -### PVP Arena Mods - -Hook into many different aspects of the game! - -Mod | Description -------------- | ------------- -[AfterMatch](mods/aftermatch.md) | could also be called "Sudden Death" -[Announcements](mods/announcements.md) | announce events happening -[ArenaBoards](mods/arenaboards.md) | stats display -[ArenaMaps](mods/arenamaps.md) | never lose yourself ever again! -[AutoSneak](mods/autosneak.md) | automatically hide player nametags by forcing sneak mode -[AutoVote](mods/autovote.md) | automatism -[BanKick](mods/bankick.md) | secure your arenas! -[BattlefieldGuard](mods/battlefieldguard.md) | secure your battlefield -[BattlefieldManager](mods/battlefieldmanager.md) | manage your battlefield -[BetterClasses](mods/betterclasses.md) | add potion effects and more to specific classes -[BetterGears](mods/bettergears.md) | give team colored leather -[BetterFight](mods/betterfight.md) | kill streaks and one-hit-kill items! -[BetterKillstreaks](mods/betterkillstreaks.md) | even more detailed kill streaks! -[BlockDissolve](mods/blockdissolve.md) | dissolve blocks under fighting players -[BlockRestore](mods/blockrestore.md) | restore the battlefield -[ChestFiller](mods/chestfiller.md) | fill battlefield chests with customizable content! -[Duel](mods/duel.md) | duel someone! -[EventActions](mods/eventactions.md) | do stuff when stuff happens -[Factions](mods/factions.md) | fix pvp not working -[FixInventoryLoss](mods/fixinventoryloss.md) | prevent loss by gamemode / inventory check -[FlySpectate](mods/flyspectate.md) | have players spectating a fight in fly mode -[Items](mods/items.md) | spawn (random) items -[LateLounge](mods/latelounge.md) | keep playing until enough ppl are joining -[MatchResultStats](mods/matchresultstats.md) | keep stats of player games, who won, who lost? -[PlayerFinder](mods/playerfinder.md) | allow players to find others with a compass -[Points](mods/points.md) | allow to restrict certain classes to require players to fight for better classes -[PowerUps](mods/powerups.md) | exactly that -[RealSpectate](mods/realspectate.md) | spectate the game, CounterStrike style! -[RedstoneTriggers](mods/redstonetriggers.md) | add win/lose triggered by redstone -[RespawnRelay](mods/respawnrelay.md) | add a relay for respawning players -[SinglePlayerSupport](mods/singleplayersupport.md) | Allow players to use an arena on their own! -[Skins](mods/skins.md) | add custom skins to teams/classes -[SpecialJoin](mods/specialjoin.md) | join via buttons, levers, etc -[Spectate](mods/spectate.md) | use the new 1.8 SPECTATOR mode to allow flying and POV spectating -[Squads](mods/squads.md) | add squads to the game, basically only showing players belonging together apart from teams and classes. -[StartFreeze](mods/startfreeze.md) | freeze players at start -[TeamSizeRestrict](mods/teamsizerestrict.md) | a small mod to restrict the size of specific teams -[Titles](mods/titles.md) | send messages to players as the "title" command would do -[TempPerms](mods/tempperms.md) | add temporary perms -[Turrets](mods/turrets.md) | add turrets where players fire projectiles -[Vault](mods/vault.md) | add economy -[Walls](mods/walls.md) | define wall regions to simulate "The Walls" -[WorldEdit](mods/worldedit.md) | backup/restore regions -[WorldGuard](mods/worldguard.md) | import region definitions from WorldGuard - -### PVP Arena Region Shapes - -Create region shapes to customize your arena! Default: COBOID! - -Shape| Description -------------- | ------------- -[CUBOID](shapes/cuboid.md) | a standard region that all should know -[CYLINDRIC](shapes/cylindric.md) | a standing can/barrel region -[SPHERIC](shapes/spheric.md) | a sphere/ball \ No newline at end of file diff --git a/doc/faq.md b/doc/faq.md new file mode 100644 index 000000000..903143c1b --- /dev/null +++ b/doc/faq.md @@ -0,0 +1,49 @@ +# Frequently Asked Questions + +## How I can create a spleef arena? + +When you create a minigame with PVPArena, you have to ask yourself "How will work score calculation?". In spleef case, +when a player dies, he looses the match. + +So you should use the [playerLives](goals/playerlives.md) goal (enabled by default). Build you arena and configure it +following [this guide](getting-started.md). + +You can restore you battlefield (snow ground) using [BlockRestore](mods/blockrestore.md) or +[Worldedit](mods/worldedit.md) module. Please check [modules documentation](modules.md) to learn more. + +
+ +## Can my players use their own inventories? + +Yes it is possible, just pass `playerclasses` parameter to `true`. You can do this directly by editing your config file +or use the [`/pa [arena] set`](commands/set.md) command. + +Then you can propose player inventories as a class: corresponding class name is `custom`. If you want this class by +default, just set `autoclass` parameter to `custom`. + +Finally, if you want to return player inventory as it was before the beginning of the match, pass `customReturnsGear` to +true. + +
+ +## How can I use arena commands from a command block? + +Maybe you will wish to use buttons, pressure plates and command blocks to allowing players to choose their class, get +ready or leave the arena. + +Most of PvPArena commands must be types by players (in order to keep context). So if you want to use plugins commands in +a command block, you will have to use a **sudo** plugin. Utility plugins like +[EssentialsX](https://www.spigotmc.org/resources/essentialsx.9089/) already include this. + +"Sudo" make possible to type a command as if player typed it. For instance, if you a to create a command block to leave +an arena, use the command `sudo @p pa leave`. + +> ⚙ **Technical precision:** +> Since Minecraft 1.13, spigot based servers does no longer support command selectors (like `@p`). If you want to use it +> you will have to use a plugin like [CommandHook](https://www.spigotmc.org/resources/commandhook.61415/). + +
+ +## Still have questions? + +Don't hesitate to [get in touch](../readme.md#support) with us 😉 \ No newline at end of file diff --git a/doc/getting-started.md b/doc/getting-started.md index 629dd43ac..49c314fe3 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -1,5 +1,4 @@ - -## Getting Started +# Getting Started
@@ -9,7 +8,7 @@ > -### Foreword: what's an arena? +## Foreword: what's an arena? Before creating your first arena, you have to understand what's. Arena is immaterial, it's a game configuration you create with goals, teams, classes, etc. It references your arena @@ -20,7 +19,7 @@ another place, don't destroy it, just redefine your spawn points and your region
-### 1. Create the arena +## 1. Create the arena Just type this command to create your arena: @@ -29,12 +28,13 @@ Just type this command to create your arena: By default your arena will work with a team system. If you add the `free` option, your arena will work on a *Free for all* (FFA) game mode. -> **🚩 Tip:** This parameter can be changed using [/pa gamemode](commands/gamemode.md) command or in your config file by +> **🚩 Tip:** +> This parameter can be changed using [/pa gamemode](commands/gamemode.md) command or in your config file by > setting `general.type` parameter to `free` or `none`.
-### 2. Set goals for the arena +## 2. Set goals for the arena By default, your arena will use [TeamLives](goals/teamlives.md) goal if your arena is in team mode and [PlayerLives](goals/playerlives.md) goal otherwise. If you're ok with this, go to the next point, otherwise please @@ -43,11 +43,16 @@ continue reading. You can choose a custom goal [in the list](goals.md) and set it for your arena with the command: `/pa [arenaName] goal [goalName]` +Each goal has its own setup, so take the time to read [documentation](goals.md) of the goal you want to use. + You will find more information about this command [on this link](commands/goal.md). +> **Reminder:** +> Don't forget to remove _TeamLives_ goal if you don't use it 😉 +
-### 3. Set spawn points +## 3. Set spawn points Now you have to create game spawn points by using this command: `/pa [arenaName] spawn [spawnType]` @@ -68,7 +73,7 @@ By default you need: 4 spawns (spawn1, spawn2, spawn3, spawn4) / 1 lounge / 1 sp
-### 4. Create the battle region +## 4. Create the battle region > *This step is optional but really useful in mostly configurations* @@ -92,7 +97,7 @@ Finally, specify your region type :
-### 5. Place required items in the lounge +## 5. Place required items in the lounge By default, four classes already exist : Swordsman, Tank, Pyro and Ranger. You can chose to keep these classes or create new ones with the the [class command](commands/class.md). @@ -111,10 +116,11 @@ are ready.
-### 6. Join the arena! +## 6. Join the arena! Your first arena was created! Join the game with: `/pa [arenaName] (join) (teamName)` -> **🚩 Tip:** If you just type `/pa [arenaName]` your team will be randomly selected. \ No newline at end of file +> **🚩 Tip:** +> If you just type `/pa [arenaName]` your team will be randomly selected. \ No newline at end of file diff --git a/doc/goals.md b/doc/goals.md index 6a1667489..568aff2fd 100644 --- a/doc/goals.md +++ b/doc/goals.md @@ -1,26 +1,25 @@ ## PVP Arena Goals -Create ways to win the game or lose the game! +Goals are ways to win the game or lose the game! You can see active goals of your arena with `/pa [arena] info`. -Goal | Description -------------- | ------------- -[Beacons](goals/beacons.md) | Stand near beacons and claim them to win! -[BlockDestroy](goals/blockdestroy.md) | Destroy blocks (pre-installed) -[CheckPoints](goals/checkpoints.md) | Reach checkpoints in order to win (pre-installed) -[Domination](goals/domination.md) | Dominate flag positions (pre-installed) -[Flags](goals/flags.md) | Capture flags and bring 'em home (pre-installed) -[Food](goals/food.md) | Cook food and bring it home (pre-installed) -[Infect](goals/infect.md) | Infect people to win / kill infected players (pre-installed) -[Liberation](goals/liberation.md) | Jail dead players, possibility to unjail! (pre-installed) -[PhysicalFlags](goals/physicalflags.md) | Capture flags physically and bring 'em home (pre-installed) -[Pillars](goals/pillars.md) | Capture pillars by clicking/destroying! -[PlayerDeathMatch](goals/playerdeathmatch.md) | Player kills win (pre-installed) -[PlayerKillReward](goals/playerkillreward.md) | Player get better gears when killing (pre-installed) -[Rescue](goals/rescue.md) | Rescue a trapped Entity -[PlayerLives](goals/playerlives.md) | Player deaths lose (pre-installed) -[Sabotage](goals/sabotage.md) | Ignite TNT (pre-installed) -[Tank](goals/tank.md) | all vs one (pre-installed) -[TeamDeathConfirm](goals/teamdeathconfirm.md) | Confirmed Team kills win (pre-installed) -[TeamDeathMatch](goals/teamdeathmatch.md) | Team kills win (pre-installed) -[TeamLives](goals/teamlives.md) | Team deaths lose (pre-installed) -[Time](goals/time.md) | Time ends the arena (pre-installed) \ No newline at end of file +To manage arena goals, use the [`/pa [arena] goal`](commands/goal.md) command. + +Goal | Description | Supported gamemodes +------------- | ------------- | ----------- +[BlockDestroy](goals/blockdestroy.md) | Destroy block of the other team | team +[CheckPoints](goals/checkpoints.md) | Reach checkpoints in order to win | free +[Domination](goals/domination.md) | Dominate flag/beacon positions | team +[Flags](goals/flags.md) | Capture flags and bring them at home | team +[Food](goals/food.md) | Cook food and bring it home | team +[Infect](goals/infect.md) | Infect people to win or kill infected players | free +[Liberation](goals/liberation.md) | Jail your enemies, free your allies! | team +[PhysicalFlags](goals/physicalflags.md) | Destroy enemy flag and place it at yours | team +[PlayerDeathMatch](goals/playerdeathmatch.md) | Score points by killing players | free & team +[PlayerKillReward](goals/playerkillreward.md) | Player get better gears when killing | free & team +[PlayerLives](goals/playerlives.md) | Last alive players win | free & team +[Sabotage](goals/sabotage.md) | Ignite TNT of the opposing team | team +[Tank](goals/tank.md) | all vs one | free +[TeamDeathConfirm](goals/teamdeathconfirm.md) | Confirmed Team kills win | team +[TeamDeathMatch](goals/teamdeathmatch.md) | Team kills win | team +[TeamLives](goals/teamlives.md) | Last alive team wins | team +[Time](goals/time.md) | Time ends the arena | free & team \ No newline at end of file diff --git a/doc/goals/beacons.md b/doc/goals/beacons.md index 459a3a941..b28a27637 100644 --- a/doc/goals/beacons.md +++ b/doc/goals/beacons.md @@ -15,7 +15,7 @@ A claimed beacon gives points every few seconds (tickinterval) that add up to a The GLASS blocks have to be added. In order to do that, use `/pa [arenaname] beacon`. This toggles edit mode. Don't forget to exit it again after setting the beacons. Set them by clicking the GLASS blocks which will color according to claim status. -## Config Settings +## Config settings - spamoffset => after how many updates should the arena announce? (default: 3) - claimrange => how near need players to be? (default: 3) diff --git a/doc/goals/blockdestroy.md b/doc/goals/blockdestroy.md index 730039194..41b9b61c4 100644 --- a/doc/goals/blockdestroy.md +++ b/doc/goals/blockdestroy.md @@ -1,22 +1,27 @@ # BlockDestroy - ## Description -This activates Blocks (to set), per team. Simply break the block of another team to remove a team life! +> ℹ This goal is designed for **team** gamemode -## Setup +## Description + +Each team have to destroy the block of opponent team(s). Blocks have lives, therefore when a block a no longer life, +its team is eliminated. -Blocks have to be added. In order to do that, use `/pa [arenaname] [teamname]block`. This enables setting. -Do this by clicking the block type (IRON_BLOCK by default) +## Setup -## Config Settings +Firstly, make sure the `blockType` parameter is set as you want. -- blockType \- the material checked for blocks (default: IRON_BLOCK) -- bdlives \- the maximum count of blocks/block destructions a team needs to win +If so, you can register destroyable blocks in your arena config. +In order to do that, use `/pa [arenaname] [teamname]block`. This will enable the selection mode. +Then left-click of the chosen block (that has to be of the defined block type). -## Supported Game Modes +## Config settings -Only supports team game mode! +- `blockType` - the material checked for blocks (default: IRON_BLOCK) +- `bdlives` - the maximum count of blocks/block destructions a team needs to win (default: 1) -## YouTube video +
-[click me](http://www.youtube.com/watch?v=ntloY1BTKHQ) +> 🚩 **Tip:** +> If you choose a colorable block (like RED_WOOL or WHITE_CONCRETE) all its variants will be supported. So you will be +> able, for instance, to set a red block for one team and a blue block for the other one. diff --git a/doc/goals/checkpoints.md b/doc/goals/checkpoints.md index 49cffcaf3..4609b8b3f 100644 --- a/doc/goals/checkpoints.md +++ b/doc/goals/checkpoints.md @@ -1,28 +1,28 @@ # CheckPoints +> ℹ This goal is designed for **free** gamemode + ## Description -CheckPoints is designed for free for all game mode! +Players have to take a path composed by checkpoints. The first one every checkpoint up to the last (in order) wins! -It requires you to set spawns that players have to reach, and in case they get lost, they can get back to the latest checkpoint with /pa checkpoint. -First player to reach every checkpoint up to the last (in order) wins! +> 🚩 **One more thing:** +> Players can get back to the latest checkpoint with /pa checkpoint ## Setup Spawns have to be added. In order to do that, use `/pa [arenaname] checkpoint [number]`. This sets checkpoint number [number]. -Make sure you start with 1 and don't forget to add every single number, or else it will not be possible to win :P - -## Config Settings - -- cpclaimrange => how near need players to be? (default: 5) -- cplives => number of checkpoints to reach -- cptickinterval => the amount of ticks to wait before checking for position (default: 20 = 1 second) +Make sure you start with 1 and don't forget to add every single number, or else it will not be possible to win 😋 -## Warnings +## Config settings -This game mode has to check for player's position. Based on the player and checkpoint count this can lag your server. But, how else should I determine a claimed checkpoint? :p +- `cpclaimrange` - how near need players to be? (default: 5) +- `cplives` - number of checkpoints to reach (default: 10) +- `cptickinterval` - the amount of ticks to wait before checking for position (default: 20 = 1 second) -## Supported Game Modes +
-Free for all +> ⚙ **Technical precision:** +> This goal has to check for player's position. Based on the player and checkpoint count this can lag your server. +> Unfortunately, there is no other way to determine a claimed checkpoint. diff --git a/doc/goals/domination.md b/doc/goals/domination.md index 1d334c517..5271554cb 100644 --- a/doc/goals/domination.md +++ b/doc/goals/domination.md @@ -1,8 +1,8 @@ # Domination -## Description +> ℹ This goal is designed for **team** gamemode -Domination is designed to use teams. As always, it defaults to red and blue. +## Description The game is simple : @@ -36,10 +36,10 @@ Given that flag must be able to change color, you can use the following blocks a * WHITE_TERRACOTTA * WHITE_WALL_BANNER -It suggest you to try glass block with a beacon bottom the flag. When flag will be claimed, glass blocks will change its +I suggest you to try glass block with a beacon bottom the flag. When flag will be claimed, glass blocks will change its color, altering beacon light ray in the same time :wink: -## Config Settings +## Config settings - spamoffset => after how many updates should the arena announce? (default: 3) - claimrange => how near need players to be? (default: 3) @@ -49,11 +49,9 @@ color, altering beacon light ray in the same time :wink: - tickinterval => the amount of ticks to wait before doing an update. (default: 60 = 3 seconds) - tickreward => the amount of points to give for each score. (default: 1) -## Warnings - -This game mode has to check for player's position. Based on the player count this can lag your server. -But, how else should I determine a claimed flag? :p +
-## YouTube video (legacy) +> ⚙ **Technical precision:** +> This goal has to check for player's position. Based on the player and checkpoint count this can lag your server. +> Unfortunately, there is no other way to determine a claimed checkpoint. -[click me](http://www.youtube.com/watch?v=Xi7yNURxAjw) diff --git a/doc/goals/flags.md b/doc/goals/flags.md index 260c46ef8..2b2b0cb7d 100644 --- a/doc/goals/flags.md +++ b/doc/goals/flags.md @@ -1,8 +1,10 @@ # Flags +> ℹ This goal is designed for **team** gamemode + ## Description -This activates Flags (to set), per team. Team A captures the flag of team B and brings it home. +There is a flag per team. Team A captures the flag of team B and brings it home. To do this, simply hit/click on flags. ## Setup @@ -23,27 +25,26 @@ of the following material (color prefix doesn't matter): * WHITE_TERRACOTTA * WHITE_WALL_BANNER -  +
Flags have to be added afterwards. In order to do that, use `/pa [arenaname] [teamname]flag` \- this enables setting. Just left click on your flag block. Clicked block must have same type as defined in your config. However nothing will happen. +> 🚩 **One more thing:** You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. Players claim this flag and bring it home. Only one team can bring this flag home, obviously :) -## Config Settings +
+ +## Config settings -- flives \- the count of flags being brought home that lead to winning -- flagType \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType +- `flives` \- the count of flags being brought home that lead to winning +- `flagType` \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType is a colorable item. -- mustBeSafe \- do claimed flags prevent bringing home other flags? \- (default: true) -- woolFlagHead \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) -- effect \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - -slowness, level 2) ; see bukkit docs -- alterOnCatch \- change flag aspect when a player catch it. If flag is colorable (list below), color is passed to white +- `mustBeSafe` \- do claimed flags prevent bringing home other flags? \- (default: true) +- `woolFlagHead` \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) +- `effect` \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - +slowness, level 2) ; [see bukkit docs](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html) +- `alterOnCatch` \- change flag aspect when a player catch it. If flag is colorable (list below), color is passed to white otherwise block is replaced by bedrock. (default: true) - -## YouTube video (legacy) - -[click me](http://www.youtube.com/watch?v=SuL78bce-f0) diff --git a/doc/goals/food.md b/doc/goals/food.md index a937bde90..844b49127 100644 --- a/doc/goals/food.md +++ b/doc/goals/food.md @@ -1,18 +1,22 @@ # Food +> ℹ This goal is designed for **team** gamemode + ## Description -Your players are hungry! The first team gathering enough cooked food items (of their type) wins the game. +Players are hungry! The first team gathering enough **cooked** food items (of their type) wins the game. The following food types exist: +- Beef +- Chicken +- Cod +- Mutton +- Porkchop +- Potato +- Salmon -- RAW_BEEF => COOKED_BEEF -- RAW_CHICKEN => COOKED_CHICKEN -- RAW_FISH => COOKED_FISH -- POTATO_ITEM => BAKED_POTATO -- PORK => GRILLED_PORK - -Note: the module does NOT include coal or furnaces, you have to manage that on your own :) +> 🚩 **Note:** +> The module does NOT include coal or furnaces, you have to manage that on your own ## Setup @@ -20,22 +24,17 @@ You have to prepare chests. To define those, use `/pa [arenaname] [teamname]food Finish the setting by clicking the chest that should be the team's chest. -This chest will be checked for incoming and outgoing food items (of the team type) You can optionally prepare furnaces so that a team can ONLY use this furnace. - -Set this by `/pa [arenaname] [teamname]foodfurnace` and hit the furnace. Teams not having a corresponding furnace will be able to access all of them. Note that one furnace can be set multiple times ! - -So red/blue can share a furnace and green/yellow :) Just set the same spot for multiple teams. - -## Config Settings - -- fmaxitems \- the item count that triggers win (default: 50) -- fplayeritems \- the item count players receive on start and respawn \- (default: 50) -- fteamitems \- the item count the team receives on start, divided by team members \- (default: 100) +This chest will be checked for incoming and outgoing food items (of the team type). You can optionally prepare furnaces so that a team can ONLY use this furnace. -## Supported Game Modes +Set this by `/pa [arenaname] [teamname]foodfurnace` and hit the furnace. -Only supports team game mode! +> 🚩 **Notes:** +> - Teams not having a corresponding furnace will be able to access all of them. +> - One furnace can be set multiple times! Just set the same spot for multiple teams. For example, +> red and blue teams can share the same furnace. -## YouTube video +## Config settings -[click me](http://www.youtube.com/watch?v=ntloY1BTKHQ) +- `fmaxitems` \- the item count that triggers win (default: 50) +- `fplayeritems` \- the item count players receive on start and respawn \- (default: 50) +- `fteamitems` \- the item count the team receives on start, divided by team members \- (default: 100) diff --git a/doc/goals/infect.md b/doc/goals/infect.md index 634c0514a..9f9faab2c 100644 --- a/doc/goals/infect.md +++ b/doc/goals/infect.md @@ -1,28 +1,23 @@ # Infect +> ℹ This goal is designed for **free** gamemode + ## Description -Quite simple. A random player is infected, he can have special gear and it's everyone against that player. +A random player is infected, he can have special gear and everyone is against that player. Killing an infected player kicks him out of the game, killing a non infected player infects him. Either the infected win by killing everyone else, or the other way round. ## Setup -At least one special "infected" spawn has to be set. You know how to do that, right? `/pa [arena] spawn infected*` - -The other spawns are set like the standard free for all goals, with spawns named like spawn1 through spawn10 or alike. - -You can set a class called "%infected%" in order to give infected players special gear - -## Config Settings - -- iilives \- infected player's lives (1) -- inlives \- normal player's lives (1) +At least one special "infected" spawn has to be set. Type the following command: +[`/pa [arena] spawn infected*`](../commands/spawn.md) -## Warnings +The other spawns are set like the standard free for all goals, with spawns named like _spawn1_ through _spawn10_ or alike. -\- +You can set a class called `%infected%` in order to give infected players special gear. -## Supported Game Modes +## Config settings -Only supports free game mode! +- `iilives` \- infected player's lives (default: 1) +- `inlives` \- normal player's lives (default: 1) diff --git a/doc/goals/liberation.md b/doc/goals/liberation.md index 81235331b..3d0f34668 100644 --- a/doc/goals/liberation.md +++ b/doc/goals/liberation.md @@ -1,22 +1,22 @@ # Liberation +> ℹ This goal is designed for **team** gamemode + ## Description A medium complex game mode. Dead players are teleported to the killer team's jail. -They can be unjailed, liberated, get one life back, so to speak :) +Other team member of jailed players can liberate them by clicking on a button, giving them one life back. ## Setup -You have to add spawns for the jails, set them like every other spawn (bluejail, redjail) and on top of that, -you have to set a button that will trigger the liberation of jailed players. - -It needs to be a stone block, and you set it with `/pa [arenaname] [teamname]button` \- Set it by clicking the button. - -## Config Settings - -- llives \- the lives players have before being put to prison +You have to add spawns for the jails, set them with command [`/pa [arena] spawn [team]jail`](../commands/spawn.md). +Then you have to set a button, at the outside of the jail, that will trigger the liberation of jailed players. To do +that: +- place a **stone button** where you want +- type `/pa [arenaname] [teamname]button` (to open selection mode) +- do a left-click on your button -## Supported Game Modes +## Config settings -Only supports team game mode! +- `llives` \- the lives players have before being put to prison (default: 3) diff --git a/doc/goals/physicalflags.md b/doc/goals/physicalflags.md index 2d4df4731..962fb3657 100644 --- a/doc/goals/physicalflags.md +++ b/doc/goals/physicalflags.md @@ -1,9 +1,11 @@ # PhysicalFlags +> ℹ This goal is designed for **team** gamemode + ## Description -This activates Flags (to set), per team. Team A have to break team B flag and brings it at home. -Point is score when team A place team B flag on its own flag. +There is a flag per team. Team A have to **break** team B flag and brings it at home. +Point is scored when team A place team B flag on its own flag. ## Setup @@ -23,22 +25,25 @@ of the following material (color prefix doesn't matter): * WHITE_TERRACOTTA * WHITE_WALL_BANNER -  +
Flags have to be added afterwards. In order to do that, use `/pa [arenaname] [teamname]flag` \- this enables setting. Just left click on your flag block. Clicked block must have same type as defined in your config. However nothing will happen. +> 🚩 **One more thing:** You can activate a special "touchdown" way of playing. Set a flag called "touchdown", it will be BLACK ingame. Players claim this flag and bring it home. Only one team can bring this flag home, obviously :) -## Config Settings +
+ +## Config settings -- flives \- the count of flags being brought home that lead to winning -- flagType \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType +- `flives` \- the count of flags being brought home that lead to winning +- `flagType` \- the material checked for flags (default: WHITE_WOOL). Plugin handle automatically flag colors if flagType is a colorable item. -- mustBeSafe \- do claimed flags prevent bringing home other flags? \- (default: true) -- woolFlagHead \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) -- effect \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - -slowness, level 2) ; see bukkit docs +- `mustBeSafe` \- do claimed flags prevent bringing home other flags? \- (default: true) +- `woolFlagHead` \- should PVP Arena enforce putting a wool head on flag carriers? - (default: true) +- `effect` \- the potion effect a player should get when carrying the flag (default: none; possible value: SLOWx2 - +slowness, level 2) ; [see bukkit docs](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html) diff --git a/doc/goals/pillars.md b/doc/goals/pillars.md index 474fe89d3..0374b1554 100644 --- a/doc/goals/pillars.md +++ b/doc/goals/pillars.md @@ -1,52 +1,56 @@ -# Pillars - ## Description - -This activates pillars being defined by a wool block / pillar. People can then click/destroy them. Future versions will include actually physically bringing pillar blocks to your base to score - ## Setup - -You have to define pillars. Prepare a WOOL block, this will be the base of the pillar. This base will be the operational block and will react to: - -- clicking -- breaking -- placing against - -(based on your settings) - -In order to do that, use /pa [arenaname] [teamname]pillar* - this enables setting. Finally set the block by clicking the WOOL block. - -Note that there are three kinds of pillars: - -- empty pillar - - starts empty (duh ;) ) - - gains points for everyone, when claimed - - naming: Any name containing "pillar" and NOT containing a team name! -- team pillar (filled) - - starts with the predefined fill height, claimed by the team name - - gains no points for the initial claimed team - - naming: Any name starting with the team name and containing "pillar" -- team pillar (not filled) - - starts empty, only gives points to the team name contained, if claimed - - naming: Any name not starting with the team name, containing pillar, and containing the team name that should NOT get points - - ## Config Settings - -- announcetick (true) - should the score be publicly announced? -- breakable (true) - should you break the base to unclaim and place to claim? -- claimall (false) - should a team win by claiming all pillars? -- onlyfree (true) - only get points for free pillars (only the first type) - -- announceoffset (3) - how many ticks should pass before announcing the current scores? -- emptyheight (1) - how high should free pillars start? -- maxclicks (10) - how many clicks do people need to claim/unclaim? (overrides break allowing!! set to 0 for breaking ;) ) -- maxheight (5) - what is the full height of a pillar? -- pillives (10) - how many points does a team need to win? -- teamheight (2) - how high should a claimed pillar be at start? -- tickpoints (1) - points per pillar per tick (in the future you can disable this, but you shouldnt do this now ;) ) -- tickinterval (20) - the interval (in ticks, 20 per second!) to check for pillar points - -## Supported Game Modes - -Only supports team game mode! - ## YouTube video - -[click me](http://www.youtube.com/watch?v=Xi7yNURxAjw) +# Pillars + +## Description + +This activates pillars being defined by a wool block / pillar. People can then click/destroy them. Future versions will include actually physically bringing pillar blocks to your base to score + +## Setup + +You have to define pillars. Prepare a WOOL block, this will be the base of the pillar. This base will be the operational block and will react to: + +- clicking +- breaking +- placing against + +(based on your settings) + +In order to do that, use /pa [arenaname] [teamname]pillar* - this enables setting. Finally set the block by clicking the WOOL block. + +Note that there are three kinds of pillars: + +- empty pillar + - starts empty (duh ;) ) + - gains points for everyone, when claimed + - naming: Any name containing "pillar" and NOT containing a team name! +- team pillar (filled) + - starts with the predefined fill height, claimed by the team name + - gains no points for the initial claimed team + - naming: Any name starting with the team name and containing "pillar" +- team pillar (not filled) + - starts empty, only gives points to the team name contained, if claimed + - naming: Any name not starting with the team name, containing pillar, and containing the team name that should NOT get points + + +## Config settings + +- announcetick (true) - should the score be publicly announced? +- breakable (true) - should you break the base to unclaim and place to claim? +- claimall (false) - should a team win by claiming all pillars? +- onlyfree (true) - only get points for free pillars (only the first type) + +- announceoffset (3) - how many ticks should pass before announcing the current scores? +- emptyheight (1) - how high should free pillars start? +- maxclicks (10) - how many clicks do people need to claim/unclaim? (overrides break allowing!! set to 0 for breaking ;) ) +- maxheight (5) - what is the full height of a pillar? +- pillives (10) - how many points does a team need to win? +- teamheight (2) - how high should a claimed pillar be at start? +- tickpoints (1) - points per pillar per tick (in the future you can disable this, but you shouldnt do this now ;) ) +- tickinterval (20) - the interval (in ticks, 20 per second!) to check for pillar points + +## Supported Game Modes + +Only supports team game mode! + +## YouTube video + +[click me](http://www.youtube.com/watch?v=Xi7yNURxAjw) diff --git a/doc/goals/playerdeathmatch.md b/doc/goals/playerdeathmatch.md index 2b576632c..3a6abd23b 100644 --- a/doc/goals/playerdeathmatch.md +++ b/doc/goals/playerdeathmatch.md @@ -1,21 +1,15 @@ -# PlayerDeathMatch - ## Description - -This goal adds a counter to players killing others. The first one to have the required number of kills wins the game. - ## Setup - -\- - ## Config Settings - -- tdlives - how many kills does a team need to win? - -## Warnings - -\- - -## Supported Game Modes - -Supports team and free game mode! - ## YouTube video - -[click me](http://www.youtube.com/watch?v=KqBueDNbpD8) +# PlayerDeathMatch + +> ℹ This goal supports **team** and **free** gamemodes + +## Description + +This goal adds a counter to players killing others. The first one to have the required number of kills wins the game. + +## Setup + +There is no special setup. + +## Config settings + +- `tdlives` - how many kills does a team need to win? diff --git a/doc/goals/playerkillreward.md b/doc/goals/playerkillreward.md index 0c744a63d..e4ad5917f 100644 --- a/doc/goals/playerkillreward.md +++ b/doc/goals/playerkillreward.md @@ -1,27 +1,28 @@ -# PlayerKillReward - ## Description - -This activates configurable battle gear being given to players on kill, or on special kills - ## Setup - -There are 5 default kill gears, you can alter them or set new ones with `/pa [arenaname] !kr [kills]` \- of course this means, you have to equip yourself with the gear ppl should have, -and do that command. - -If you want to remove a kill stage, just add another word after the kill number. - -Default kills: - -- 5 \- Leather Armor & Wooden Sword -- 4 \- Chain Armor & Stone Sword -- 3 \- Gold Armor & Iron Sword -- 2 \- Iron Armor & Diamond Sword -- 1 \- Diamond Armor & Diamond Sword - -Note that the Kill number is to be understood as "kills left to win" - ## Config Settings - -\- - -## Supported Game Modes - -Supports team and free game mode! +# PlayerKillReward + +> ℹ This goal supports **team** and **free** gamemodes + +## Description + +In this goal, players have to make kills to wins. When they kill someone, their remaining kill number decreases and +they get a new item set. + +## Setup + +By default, there are 5 default kill gears: +- 5 \- Leather Armor & Wooden Sword +- 4 \- Chain Armor & Stone Sword +- 3 \- Gold Armor & Iron Sword +- 2 \- Iron Armor & Diamond Sword +- 1 \- Diamond Armor & Diamond Sword + +> Note that the Kill number is to be understood as "kills left to win" + +You can alter them or set new ones by doing that: +- Equip your own inventory with wanted gears (place armor and off-hand in good slots) +- Type `/pa [arenaname] !kr [remainingKillNumber]` + +## Config settings + +- `graduallyDown` - on death, keep current number of remaining kills instead of resetting it (default: false) +- `onlyGive` - just give new items to players instead of replacing their inventory (default: false) diff --git a/doc/goals/playerlives.md b/doc/goals/playerlives.md index cc173d6b3..89930d339 100644 --- a/doc/goals/playerlives.md +++ b/doc/goals/playerlives.md @@ -1,21 +1,19 @@ -# PlayerLives - ## Description - -The basic arena goal. Players have individual lives. After a player has run out of lives, he is removed. - ## Setup - -\- - ## Config Settings - -- plives \- the amount of lives a player has before being removed out of the arena - -## Warnings - -\- - -## Supported Game Modes - -Supports team and free game mode! - ## YouTube video - -[FreeForAll](http://www.youtube.com/watch?v=xBIxHoKMu98) +# PlayerLives + +> ℹ This goal supports **team** and **free** gamemodes + +## Description + +The basic arena goal. Players have individual lives. After a player has run out of lives, he is removed. + +> 🚩 **Note:** +> Contrary to [playerDeathMatch](playerdeathmatch.md) goal, here players can lose lives because of external elements +> (lava, falling, drowning, etc) + +## Setup + +There is no special setup. + +## Config settings + +- `plives` \- the amount of lives a player has before being removed out of the arena (default: 3) \ No newline at end of file diff --git a/doc/goals/rescue.md b/doc/goals/rescue.md index 75ad89a3d..0e48637f4 100644 --- a/doc/goals/rescue.md +++ b/doc/goals/rescue.md @@ -1,21 +1,24 @@ -# Rescue - ## Description - -A team game! Each team has a preset place where you hold captive an other team's entity. Invade the other team's base and "rescue" your entity! - ## Setup - -Set the entityspawn with `/pa [team]rescue` and clicking the block on which the entity will be spawned - ## Config Settings - -- rescue.flagType \- the entity Type, default: VILLAGER -- rlives \- the rescue count to achieve -- rescue.mustBeSafe \- can a team only bring home the entity if the own captive is not stolen? -- rescue.effect \- the potion effect for when carrying a rescued entity - -## Warnings - -\- - -## Supported Game Modes - -Only supports team game mode! +# Rescue + +## Description + +A team game! Each team has a preset place where you hold captive an other team's entity. Invade the other team's base and "rescue" your entity! + +## Setup + +Set the entityspawn with `/pa [team]rescue` and clicking the block on which the entity will be spawned + +## Config settings + +- rescue.flagType \- the entity Type, default: VILLAGER +- rlives \- the rescue count to achieve +- rescue.mustBeSafe \- can a team only bring home the entity if the own captive is not stolen? +- rescue.effect \- the potion effect for when carrying a rescued entity + +## Warnings + +\- + +## Supported Game Modes + +Only supports team game mode! diff --git a/doc/goals/sabotage.md b/doc/goals/sabotage.md index 9b791235d..440145ace 100644 --- a/doc/goals/sabotage.md +++ b/doc/goals/sabotage.md @@ -1,19 +1,15 @@ -# Sabotage - ## Description - -This activates TNT blocks (to set) that can be ignited by players that carry proper gear. An ignited TNT kills the team to whom the TNT belongs. - ## Setup - -TNTs have to be added.In order to do that, use `/pa [arenaname] [teamname]tnt` \- this enables tnt setting. Do it by clicking the TNT at the team's base. -Don't click with your wand, just click with your hand or anything else. - ## Config Settings - -\- - -## Warnings - -\- - -## Supported Game Modes - -Only supports team game mode! +# Sabotage + +> ℹ This goal is designed for **team** gamemode + +## Description + +Each team has a TNT block in its base. If this block is ignited by other players, the team is eliminated. + +## Setup + +TNTs have to be added. + +In order to do that, for each team: +- Type `/pa [arenaname] [teamname]tnt` - this enables tnt selector +- Left-click with your hand on the TNT block \ No newline at end of file diff --git a/doc/goals/tank.md b/doc/goals/tank.md index bb6b9313d..dbaaae043 100644 --- a/doc/goals/tank.md +++ b/doc/goals/tank.md @@ -1,20 +1,19 @@ -# Tank - ## Description - -This is a simple round. One random tank is assigned, he has special gear and it's everyone against that tank. Either the tank wins by killing everyone else, or the rest wins by killing the tank. - -You can optionally give a special gear to the tank, set the class "%tank%" - ## Setup - -A special "tank" spawn has to be set. You know how to do that, right? `/pa [arena] spawn tank` - ## Config Settings - -- tank.tlives \- the amount of lives players and the tank have before being removed - -## Warnings - -\- - -## Supported Game Modes - -Only supports free game mode! +# Tank + +> ℹ This goal is designed for **free** gamemode + +## Description + +One random tank is assigned, he has special gear and, everyone is against them. +Either the tank wins by killing everyone else, or the rest wins by killing the tank. + +## Setup + +A special "tank" spawn has to be set. Just type [`/pa [arena] spawn tank`](../commands/spawn.md). + +Optionally, you can give a special gear to the tank by [setting the class](../commands/class.md) `%tank%`. + +## Config settings + +- `tank.tlives` \- the amount of lives players and the tank have before being removed (default: 1) + diff --git a/doc/goals/teamdeathconfirm.md b/doc/goals/teamdeathconfirm.md index 8fe879d8b..2fc9b5662 100644 --- a/doc/goals/teamdeathconfirm.md +++ b/doc/goals/teamdeathconfirm.md @@ -1,23 +1,19 @@ # TeamDeathMatch +> ℹ This goal is designed for **team** gamemode + ## Description -Team play. Team kills are counted by collecting the drops when a player is killed, the first team collecting the set amount of drops wins. +Team kills are counted by collecting the drops when a player is killed, the first team collecting the set amount of drops wins. The big difference to standard PVP is that a team can prevent the other team from scoring by collecting the drops themselves. ## Setup -\- - -## Config Settings - -- tdcitem \- the amount of (enemy) drops a team has to collect in order to win - -## Warnings - -\- +There is no special setup. -## Supported Game Modes +## Config settings -Only supports team game mode! +- `tdcitem` \- item type dropped on player death (default: WHITE_WOOL) +- `tdclives` \- the amount of (enemy) drops a team has to collect in order to win, i.e. number of team lives +(default: 10) diff --git a/doc/goals/teamdeathmatch.md b/doc/goals/teamdeathmatch.md index 5e3372a76..c4adbdfc8 100644 --- a/doc/goals/teamdeathmatch.md +++ b/doc/goals/teamdeathmatch.md @@ -1,21 +1,16 @@ -# TeamDeathMatch - ## Description - -Simple team play. Team kills are counted, the first team killing that many people wins. - ## Setup - -\- - ## Config Settings - -- tdlives \- the amount of kills a team has to achieve in order to win - -## Warnings - -\- - -## Supported Game Modes - -Only supports team game mode! - ## YouTube video - -[click me](http://www.youtube.com/watch?v=rQ1ljlc6SJM) +# TeamDeathMatch + +> ℹ This goal is designed for **team** gamemode + +## Description + +Simple team play. Team kills are counted, the first team killing enough players wins. + +## Setup + +There is no special setup. + +## Config settings + +- `tdlives` - the amount of kills a team has to achieve in order to win (default: 10) +- `suicideScore` - does suicide is taken into account in score calculation? (default: false) diff --git a/doc/goals/teamlives.md b/doc/goals/teamlives.md index be979d884..1d12a2fc7 100644 --- a/doc/goals/teamlives.md +++ b/doc/goals/teamlives.md @@ -1,18 +1,13 @@ -# TeamLives - ## Description - -Very basic. Teams have lives. Once a team runs out of lives, it loses. - ## Setup - -\- - ## Config Settings - -- teamlives.tlives \- the amount of lives a team has before being removed - -## Warnings - -\- - -## Supported Game Modes - -Only supports team game mode! +# TeamLives + +## Description + +Very basic. Teams have lives. Once a team runs out of lives, it loses. + +## Setup + +There is no special setup. + +## Config settings + +- `teamlives.tlives` \- the amount of lives a team has before being removed diff --git a/doc/goals/time.md b/doc/goals/time.md index df76bb67a..bb6a0188d 100644 --- a/doc/goals/time.md +++ b/doc/goals/time.md @@ -1,23 +1,18 @@ -# Time - ## Description - -Guess what it does. \- Yes! it adds a timer, that ends the arena after a certain time. Based on all other active goals, it calculates the winning team/player. - -The scores that each goal gives are subject to change so ... don't rely on the output there :) - ## Setup - -\- - ## Config Settings - -- goal: - - time: - - timedend: 0 # the time in seconds the match should last - - winner: none # the team name that should win as soon as the time runs out - -## Warnings - -\- - -## Supported Game Modes - -Supports team and free game mode! +# Time + +> ℹ This goal supports **team** and **free** gamemodes. + +## Description + +This goal adds a timer, that ends the arena after a certain time. Based on all other active goals, it calculates the winning team/player. + +It is recommended to use this goal with another one. + +## Setup + +There is no special setup + +## Config settings + +- `timedend` - duration of the match in seconds (default: 0 - disabled) +- `winner` - the team name that should win as soon as the time runs out (default: none) diff --git a/doc/history/0.1.md b/doc/history/0.1.md deleted file mode 100644 index b69259dab..000000000 --- a/doc/history/0.1.md +++ /dev/null @@ -1,16 +0,0 @@ -== PVP-Arena v0.1 Changelog - -* v0.1.13 - place bets on a match -* v0.1.12 - display stats with /pa users | /pa teams -* v0.1.11 - config: woolhead: put colored wool on heads! -* v0.1.10 - config: only start with even teams -* v0.1.9 - teleport location configuration -* v0.1.8 - lives! -* v0.1.7 - commands to show who is playing and on what team -* v0.1.6 - custom class: fight with own items -* v0.1.5 - class choosing not toggling -* v0.1.4 - arena disable via command * disable / * enable -* v0.1.3 - ingame config reload -* v0.1.2 - class permission requirement -* v0.1.1 - ready block configurable -* v0.1.0 - release version \ No newline at end of file diff --git a/doc/history/0.10.md b/doc/history/0.10.md deleted file mode 100644 index b8dbb9dc4..000000000 --- a/doc/history/0.10.md +++ /dev/null @@ -1,97 +0,0 @@ -== PVP-Arena v0.10 Changelog - -* v0.10.3.15 - LOGICALLY set the player location before saving the state (for laggy servers) -* v0.10.3.14 - Stop ppl from setting the flags as a SPAWN ... -* v0.10.3.13 - aim to fix CosmoVibe :p -* v0.10.3.12 - allow teleportation into arena regions that are NOT type BATTLE -* v0.10.3.11 - fix Flags. Period. -* v0.10.3.10 - fix BlockDestroy with explosions -* v0.10.3.9 - fix /pa ready -* v0.10.3.8 - add Ticket #227 - player time and auto igniting TNT -* v0.10.3.7 - fix DOM - points lead to winning, not to losing! -* v0.10.3.6 - re-add MODULES_COLORTEAMS_HIDENAME - who removed that?! -* v0.10.3.5 - fix Ticket #197 - readying up mechanism messed up -* v0.10.3.4 - aims to fix Ticket #193 - arena not ending -* v0.10.3.3 - Support TNT in BlockDestroy -* v0.10.3.2 - Several fixes -* v0.10.3.1 - StartRunnable now is on the main... thank you, TagAPI :p -* v0.10.3.0 - violations! -* v0.10.2.36 - ouch ... quick command fix! -* v0.10.2.35 - formatting ? -* v0.10.2.34 - correctly reset Domination and BlockDestroy on start -* v0.10.2.33 - stop people from destroying their own block in BlockDestroy ^^ -* v0.10.2.32 - add a special class being assigned when being the tank: %tank% -* v0.10.2.31 - No more restarts! Modules shall NOT rely on server restarts! - No more restarts! Modules shall NOT rely on server restarts! -* v0.10.2.30 - WorldEdit module announcements -* v0.10.2.29 - fix the arena end timer -* v0.10.2.28 - stop kicking everyone on start !!! -* v0.10.2.27 - add a debug line that might change everything -* v0.10.2.25 - properly fix players dying. Take that, logic!! -* v0.10.2.24 - try to hackfix the hackfix -* v0.10.2.23 - critical fix. WHO REMOVED THAT!!?? -* v0.10.2.22 - fix player death handling -* v0.10.2.21 - add goal: BlockDestroy -* v0.10.2.20 - add goal: PhysicalFlags -* v0.10.2.19 - Pull #4 - Don't return false! -* v0.10.2.18 - some small fixes -* v0.10.2.17 - ignore ready blocks unless not ready -* v0.10.2.16 - BetterFight: explosions on death ^^ -* v0.10.2.15 - add region flag NODAMAGE - yay! -* v0.10.2.14 - add "winner" config in case of timeout! -* v0.10.2.13 - add configurable GAMEMODE :) -* v0.10.2.12 - stop ignoring players being removed! -* v0.10.2.11 - fix AutoVote infinity :D -* v0.10.2.10 - /pa class display error, more debug -* v0.10.2.9 - RelayRunnable implementation -* v0.10.2.8 - rewrite respawn handling -* v0.10.2.7 - add TOUCHDOWN gamemode to Flags -* v0.10.2.6 - add configurable PlayerKillRewards -* v0.10.2.5 - add Goal "PlayerKillRewards" and fix NPE -* v0.10.2.4 - fix book saving and loading -* v0.10.2.3 - add lore saving and loading -* v0.10.2.2 - cancel region selection by redoing /pa [arena] region -* v0.10.2.1 - add configurable POTION EFFECT to flag carriers -* v0.10.2.0 - Debugger rewrite -* v0.10.1.21 - add LOUNGE region type functionality (kick ;) ) -* v0.10.1.20 - allow FFA players to win and lose via region :p -* v0.10.1.19 - I) fix arenas with flags being derpy II) secret. DONT use! -* v0.10.1.18 - attempt to save more than casual items. don't try this at home! - yet -* v0.10.1.17 - save armor when saving a class -* v0.10.1.16 - added default confirmation for /pa [arena] remove -* v0.10.1.15 - add "not enough EXP to choose class" (BetterClasses) -* v0.10.1.14 - addresses Ticket #119 -* v0.10.1.13 - add a configurable timer to start without PVP -* v0.10.1.12 - re-add timer scheduling (WIN,LOSE,DEATH regions) -* v0.10.1.11 - fix Sabotage -* v0.10.1.10 - fix Sabotage Spawn parsing -* v0.10.1.9 - fix Player death parsing -* v0.10.1.8 - fix ArenaRunnable setup -* v0.10.1.7 - fix first smart spawn -.- -* v0.10.1.6 - fix death announcements, clean up death handling -* v0.10.1.5 - finally fix the WarmupJoin module -* v0.10.1.4 - fix NPE about sign joining -* v0.10.1.3 - add /pa [arena] team! -* v0.10.1.2 - remove unused config nodes -* v0.10.1.1 - fix FFA respawning (locations) -* v0.10.1.0 - CraftBukkit 1.4.6 -* v0.10.0.21 - once and for all, fix deathmatches! -* v0.10.0.20 - this should work. fixed DeathMatch respawns! -* v0.10.0.19 - hopefully fix DeathMatch respawns :) -* v0.10.0.18 - fix NPE in DeathMatch :) -* v0.10.0.17 - allow re-joining for Lives and all DeathMatch modules -* v0.10.0.16 - properly check for BATTLE regions instead for "battlefield" -* v0.10.0.15 - fix smart spawning not being implemented in a smart way -* v0.10.0.14 - add debug for a strange bug when teleporting people -* v0.10.0.13 - stop telling people they are already part of arenas! -* v0.10.0.12 - reset fall distance to not kill people twice ;) -* v0.10.0.11 - fix BetterGears -* v0.10.0.10 - fix updating via /pa update mods | /pa update goals -* v0.10.0.9 - version bump for DBO -* v0.10.0.8 - wow, what a fail. sorry guys, updater fixed :D -* v0.10.0.7 - re-add automatic plugin update !! -* v0.10.0.6 - EndRunnable now is Sync - thanks, TagAPI :p -* v0.10.0.5 - activate lounge, spectator and internals by default -* v0.10.0.4 - fix the blacklist/whitelist removal message -* v0.10.0.3 - allow re-joining, if ppl know what they're doing -* v0.10.0.2 - avoid NPE in Time Goal -* v0.10.0.1 - module system rewrite \ No newline at end of file diff --git a/doc/history/0.2.md b/doc/history/0.2.md deleted file mode 100644 index c71c35517..000000000 --- a/doc/history/0.2.md +++ /dev/null @@ -1,4 +0,0 @@ -== PVP-Arena v0.2 Changelog - -* v0.2.1 - cleanup, comments, iConomy 6 support -* v0.2.0 - language support \ No newline at end of file diff --git a/doc/history/0.3.md b/doc/history/0.3.md deleted file mode 100644 index f1b40514f..000000000 --- a/doc/history/0.3.md +++ /dev/null @@ -1,17 +0,0 @@ -== PVP-Arena v0.3 Changelog - -* v0.3.14 - timed arena modes -* v0.3.13 - Telepass via Permission -* v0.3.12 - set flag positions -* v0.3.11 - set regions for lounges, spectator, exit -* v0.3.10 - CraftBukkit #1337 config version, rewrite -* v0.3.9 - Permissions, rewrite -* v0.3.8 - BOSEconomy, rewrite -* v0.3.7 - Bugfixes, Cleanup -* v0.3.6 - CTF Arena -* v0.3.5 - Powerups!! -* v0.3.4 - Rewrite -* v0.3.3 - Random spawns possible for every arena -* v0.3.2 - Classes now can store up to 6 players -* v0.3.1 - New Arena! FreeFight -* v0.3.0 - Multiple Arenas \ No newline at end of file diff --git a/doc/history/0.4.md b/doc/history/0.4.md deleted file mode 100644 index 3d177b4fe..000000000 --- a/doc/history/0.4.md +++ /dev/null @@ -1,7 +0,0 @@ -== PVP-Arena v0.4 Changelog - -* v0.4.4 - Random spawns per team, not shared -* v0.4.3 - max / min bet -* v0.4.2 - command blacklist -* v0.4.1 - command manager, arena information and arena config check -* v0.4.0 - mayor rewrite, improved help \ No newline at end of file diff --git a/doc/history/0.5.md b/doc/history/0.5.md deleted file mode 100644 index 67a6b8bf2..000000000 --- a/doc/history/0.5.md +++ /dev/null @@ -1,13 +0,0 @@ -== PVP-Arena v0.5 Changelog - -* v0.5.11 - CTF flag bug, command error msg improvement -* v0.5.10 - fight temp perms, custom class drops, spectate fix -* v0.5.9 - max players, max team pleayers -* v0.5.8 - private arenas, item reward fix -* v0.5.7 - bugfixes, spawn remove command, enable/disable save -* v0.5.6 - ready handling fix, min team size -* v0.5.5 - blacklist, update check -* v0.5.4 - Capture the Pumpkin arena! -* v0.5.3 - Backend rewrite, -* v0.5.2 - Bugfixes, configurable player start values -* v0.5.1 - rewrite, temporary sign bug fix \ No newline at end of file diff --git a/doc/history/0.6.md b/doc/history/0.6.md deleted file mode 100644 index fbfdc935c..000000000 --- a/doc/history/0.6.md +++ /dev/null @@ -1,83 +0,0 @@ -== PVP-Arena v0.6 Changelog - -* v0.6.41.1 - fix the Potion Type NPE -* v0.6.41.0 - possibility to customize the Arena prefix -* v0.6.40.26 - fix NPE when not selecting a region before trying to save the selection -* v0.6.40.25 - fix inventory protection -* v0.6.40.24 - fix region protection issues -* v0.6.40.20 - fix dead players still wearing their armor -* v0.6.40.19 - set debug ingame /pa debug [value] -* v0.6.40.18 - recognize players running outside of the arena -* v0.6.40.17 - fix woolhead removal for flag arenas -* v0.6.40.16 - fix ready block hit while countdown teleporting ppl inside the arena. Bad, bad players! -* v0.6.40.15 - hackfix Potion Effects not vanishing. Bad, bad API! -* v0.6.40.14 - fix resetting of player stats -.- -* v0.6.40.13 - fix abusing the spectator state -* v0.6.40.11 - fix a random NPE; fix WoolHead enforcement -* v0.6.40.10 - fix powerup type REPAIR and a NPE in flag arenas -* v0.6.40.9 - fix another issue with the startup countdown -* v0.6.40.8 - Backend organising by NodinChan, has NO effect on the plugin atm -* v0.6.40.7 - Fix NPE and fix LeaderBoards -* v0.6.40.6 - Tries to fix mcMMO damage messing up the arena ;) -* v0.6.40 - Multiple flags for CTF -* v0.6.39 - Enchantments -* v0.6.38 - Arena chat -* v0.6.37 - Item reward random -* v0.6.36.11 - fix a bug where players were able to start alone / with just one team -* v0.6.36.8 - fix various bugs -* v0.6.36.4 - add a proper arena start message ; add a PAKillEvent -* v0.6.36.3 - fix bet placing NPE -* v0.6.36.2 - add Vault support -* v0.6.36 - fix for every arena start bug caused by leaving / quitting players -* v0.6.35.3 - taught talking to DOM arena -* v0.6.35.2 - fix the CTF issues -* v0.6.35 - fix the death issues, finally -* v0.6.29.9 - fix the fire bug, finally -* v0.6.29.8 - create custom events properly -* v0.6.29.7 - reset team flags on arena startup to be colored -* v0.6.29.6 - fixed CTF NPE -* v0.6.29.5 - added config setting protection.restore to stop block restoring -* v0.6.29.4 - added teleport ignoring INSIDE the battlefield -* v0.6.29.3 - fixed countdown join bug, for real :D -* v0.6.29.2 - fixed sign restoring bug -* v0.6.29.1 - fixed inventory hack bug -* v0.6.29 - join teams with sign. Line 2: teamname -* v0.6.28.6 - cancel 5s countdown if player joins -* v0.6.28.5 - spawn camping just for battlefield & fighting players -* v0.6.28.4 - add config: protection.punish (default false) -* v0.6.28.3 - fix 2 NPEs happening when spawn camping or using /pa leave -* v0.6.28.2 - fix a very bad bug occurring after fixing an NPE -* v0.6.28.1 - fix various NPEs -* v0.6.28 - potion effects for PowerUps -* v0.6.27 - join range possible without set region -* v0.6.26.2 - fixed NPE -* v0.6.26.1 - added proper join event calling -* v0.6.26 - add custom events for other plugins to listen to -* v0.6.25 - get stats with /pa {name} stats [stattype] -* v0.6.24 - sort arena board by click -* v0.6.23 - config "hideName": remove names over head -* v0.6.22 - punish spawn camping -* v0.6.21 - [PUMPKIN|CTF|DOM] join arenas ingame -* v0.6.20 - arena start runnable (5s, if readycount > x%), interrupted by player join -* v0.6.19 - fixed players joining from vehicles -* v0.6.18 - added entry fee "pay" message -* v0.6.17 - force joining from a special region, if one arena has set "join" region -* v0.6.16 - "explicitPermission" to enable need of "pvparena.join.[arenaname]" -* v0.6.15 - new debug system -* v0.6.14 - main config: onlyPVPinArena -> cancel all damage except arena! -* v0.6.13.2 - quitting ingame does not break anything -* v0.6.13.1 - fixed block destruction being possible -* v0.6.13 - EDIT mode /pa {name} edit -* v0.6.12 - "[player] killed" + " by [player/cause]" -* v0.6.11 - config: betWinFactor [2], betTeamWinFactor [1], betPlayerWinFactor [2] -* v0.6.10 - config: allowDrops [true] -* v0.6.9 - config: flagColors: set flag (head) colors -* v0.6.8 - config: woolFlagHead: change/set woolhead on flag grabbing -* v0.6.7 - config: autoclass: [classname] -* v0.6.6 - team chat: add player name -* v0.6.5 - [Spout] wool lock (inv change cancel) -* v0.6.4 - [Spout] color name over head -* v0.6.3 - game mode: death match, spheric regions, block repair, powerup spawn -* v0.6.2 - leaderboards RELOADED, spawn protection, flag coloring/whitening, inv drops -* v0.6.1 - sign update/check, announcements, death!, arena end timer -* v0.6.0 - huge rewrite \ No newline at end of file diff --git a/doc/history/0.7.md b/doc/history/0.7.md deleted file mode 100644 index 3a1e1ae41..000000000 --- a/doc/history/0.7.md +++ /dev/null @@ -1,90 +0,0 @@ -== PVP-Arena v0.7 Changelog - -* v0.7.25.2 - cancel woolhead removal when needed -* v0.7.25.1 - properly handle piston event protection -* v0.7.25.0 - rewrite of /pa {arenaname} info -* v0.7.24.0 - attempt to improve the statistics usage -* v0.7.23.4 - fixed the woolhead removal - again -* v0.7.23.3 - fix an issue with death events -* v0.7.23.2 - fix late joining -* v0.7.23.1 - fix freefight type issues, fix classitems messing causing NPEs -* v0.7.23.0 - /pa [name] alive - list alive players -* v0.7.22.2 - fix PotionEffects not being removed properly -* v0.7.22.1 - more intelligent and extroverted help system -* v0.7.22.0 - add readying of all teams with checkEachTeam: false -* v0.7.21.0 - fix many issues inside modules -* v0.7.20.13 - fix an NPE on non pvp death -* v0.7.20.12 - add cylindric arena region shape -* v0.7.20.11 - fix custom class not working -* v0.7.20.10 - fix the end timer not deactivating PVP for losers -* v0.7.20.8 - fix issues.... -* v0.7.20.7 - fix stuff and update for tank arena mode -* v0.7.20.6 - fix alot of permissions issues oO -* v0.7.20.5 - fix the wool head not being correctly secured -* v0.7.20.4 - fix the ready up bug -* v0.7.20.3 - fix various bugs -* v0.7.20.2 - fix various bugs -* v0.7.20.1 - fix teams/ctf/pumpkin lounge setting not working -* v0.7.20.0 - feature freeze, future updates will just add/update modules or fix bugs -* v0.7.19.5 - fix messy code about random spawns -* v0.7.19.4 - fix teams/ctf/pumpkin spawn setting not working -* v0.7.19.3 - fix region NPE -* v0.7.19.2 - fix missing messages -* v0.7.19.1 - fix multiple enchantments -* v0.7.19.0 - command handling rewrite -* v0.7.18.0 - region modules -* v0.7.17.4 - fix chest restoring -* v0.7.17.3 - make the countdown timer configurable -* v0.7.17.2 - fix arenaboards displaying the global stats for players during a match -* v0.7.17.1 - fix fluids and block burning not being cancellable/replaced properly -* v0.7.17.0 - (more) correctly calculate armor in order to detect death -* v0.7.16.1 - fix when teleporting players -* v0.7.16.0 - more colors! -* v0.7.15.0 - /pa readylist - to see people not being flagged as ready -* v0.7.14.1 - add a delay to teleporting, making the player teleporting thread safe -* v0.7.14.0 - teleport to spawns with /pa tp [spawnname] -* v0.7.13.1 - FIRST restore blocks, then restore inventories! -* v0.7.13.0 - add config setting to force warming up on /pa join | /pa spectate -* v0.7.12.1 - fix /pa [name] remove [spawnname] -* v0.7.12.0 - multiple Enchantments -* v0.7.11.3 - add a different tracker -* v0.7.11.2 - fix the player handling / inventory issue -* v0.7.10.6 - fix the Loader -* v0.7.10.5 - fix watching players not belonging to the arena -* v0.7.10.4 - fix restoring of the team nameplate -* v0.7.10.3 - fix timed (team) arenas giving no rewards -* v0.7.10.2 - fix timed arenas totally f up -* v0.7.10.1 - fix CraftBukkitUpToDate compatibility -* v0.7.10.0 - add restoring of dispensers and furnaces -* v0.7.9.22 - change game.allowDrops priority. Custom class not needed! -* v0.7.9.21 - fix module loading -* v0.7.9.20 - fix modules not containing version -* v0.7.9.19 - fix player recognition -.- -* v0.7.9.18 - fix spheric regions not being saved properly -* v0.7.9.17 - fix all arena type ready methods -* v0.7.9.16 - fix CTF/Pumpkin interact cancelling -* v0.7.9.15 - hook inv shift click to protection.inventory -* v0.7.9.14 - fix ColorTeams -* v0.7.9.13 - fix CTF/Pumpkin arena returning "Flag set:" on many occasions ^^ -* v0.7.9.12 - fix mobs messing up the game. bad, bad mobs! -* v0.7.9.11 - fix an NPE with activated quit check -* v0.7.9.10 - fix ArenaBoards not working if spectators are present -* v0.7.9.9 - fix many issues with invisible armor, players etc by disabling the team coloring function -* v0.7.9.8 - fix team chat doubling -* v0.7.9.7 - add customisable end timer, add damage cancelling -* v0.7.9.6 - fix an NPE with /pa bet [player] -* v0.7.9.5 - fix an NPE possible on arena end -* v0.7.9.4 - fix more beta bugs -* v0.7.9.2 - fix various bugs -* v0.7.9 - rewrite concerning ArenaPlayer / Players -* v0.7.8 - ArenaModule: Announcements -* v0.7.7 - ArenaModule: TempPerms -* v0.7.6 - ArenaModule: PowerUps -* v0.7.5 - ArenaModule: VaultSupport -* v0.7.4 - ArenaModule: Economy -* v0.7.3 - ArenaModule: BlockRestore -* v0.7.2 - ArenaModule: ColorTeams -* v0.7.1 - ArenaModule: ArenaBoards -* v0.7.0.3 - Kick leads to arena leave -* v0.7.0.2 - Chest restoring -* v0.7 - another huge rewrite, modules that provide Arena Types \ No newline at end of file diff --git a/doc/history/0.8.md b/doc/history/0.8.md deleted file mode 100644 index 0e8d54b26..000000000 --- a/doc/history/0.8.md +++ /dev/null @@ -1,92 +0,0 @@ -== PVP-Arena v0.8 Changelog - -* v0.8.12.3 - trimmed some unneeded methods -* v0.8.12.2 - offline updating -* v0.8.12.1 - fix several NPEs -* v0.8.12.0 - fix disconnect exploit -* v0.8.11.28 - maybe fix the chatting the correct way ^^ -* v0.8.11.27 - fix 1.3.1 spamming about PlayerChatEvent. real fix incoming -* v0.8.11.26 - fix class saving -* v0.8.11.25 - fix regions being one block too short on each side -* v0.8.11.24 - fix non-fighters inside an arena being damaged. -* v0.8.11.23 - fix the loser's inventory disappearing issue -* v0.8.11.22 - fix general protection issues (greedy protection) -* v0.8.11.21 - fix joining teams with signs -* v0.8.11.20 - fix /pa [] class -* v0.8.11.19 - fix some spawn settings not working -* v0.8.11.18 - fix battlefield/arena end/win/lose issues -* v0.8.11.17 - add ingame class preview / edit / saving / removing -* v0.8.11.16 - also restrict blockplace on block whitelist/blacklist -* v0.8.11.15 - attempt to fix losers being counted as winners, adding PALoseEvent on the way -* v0.8.11.14 - fix several issues about players logically hurting themselves (ender pearls etc) -* v0.8.11.13 - prevent teleporting INTO an arena -* v0.8.11.12 - fix arena join messages -* v0.8.11.11 - unknown -* v0.8.11.10 - fix multiple join regions need you to be in all join regions oO -* v0.8.11.9 - fix losing making you leave the match -* v0.8.11.8 - fix deaths and kills not being registered -* v0.8.11.7 - fix players being kicked from arena -* v0.8.11.6 - add proper CUSTOM announcement implementation -* v0.8.11.5 - zip NPE bug? -* v0.8.11.4 - fix spectator check -* v0.8.11.3 - fix other issues -* v0.8.11.2 - fix a player death NPE -* v0.8.11.1 - fix StartRunnable issues -* v0.8.11.0 - add PAWinEvent -* v0.8.10.14 - revert inventory handling -* v0.8.10.13 - change and fix update check -* v0.8.10.12 - allow module update deactivation -* v0.8.10.11 - properly reset inventories! -* v0.8.10.10 - reset Potion Effects on respawn -* v0.8.10.9 - add MultiInv compatibility -* v0.8.10.8 - fix NPE about resetPlayer -* v0.8.10.7 - add config setting to change default command -* v0.8.10.6 - fix custom classes inventory handling -* v0.8.10.5 - re-activate the escape check -* v0.8.10.4 - fix inventory being removed for custom classes at the end... -* v0.8.10.3 - properly ignore alpha and beta builds from update nag -* v0.8.10.2 - fix WIN and LOSE region not triggering timers -* v0.8.10.1 - fix spawn setting not working for some modules -* v0.8.10.0 - add WIN and LOSE regions -* v0.8.9.0 - finish region protection -* v0.8.8.9 - fix Projectile Exception (Ticket 338) -* v0.8.8.8 - fix the region selection spam -* v0.8.8.7 - add message coloring -* v0.8.8.6 - fix synchronisation issues -* v0.8.8.5 - fix "youescaped" bug -* v0.8.8.4 - fix NPE in statistics handling -* v0.8.8.3 - fix /pa update [type] -* v0.8.8.2 - fix /pa uninstall * -* v0.8.8.1 - block break NPE -* v0.8.8.0 - timer rewrite to fix many issues -* v0.8.7.2 - fix minor display bug -* v0.8.7.1 - fix NPE when players disconnect while being told something -* v0.8.7.0 - add /pa update, /pa install and /pa uninstall -* v0.8.6.20 - fix TimerInfo visibility -* v0.8.6.19 - support arena name guessing -* v0.8.6.18 - enhance /pa version flexibility -* v0.8.6.17 - give proper error when using unsupported region types -* v0.8.6.16 - fixed other regions not being initialized properly -* v0.8.6.15 - fixed cubic regions not being initialized properly -* v0.8.6.14 - fixed /pa reload messing up when an arena was running -* v0.8.6.13 - better information about missing game modes -* v0.8.6.12 - add proper error for old pa create command -* v0.8.6.11 - distinguish tnt block damage from player block damage -* v0.8.6.10 - remove mobs and animals on region reset -* v0.8.6.9 - fix spawn access (players taking the enemy flag at other positions) -* v0.8.4.8 - add hook parseRespawn to Modules -* v0.8.4.7 - fix woolHead support -* v0.8.4.6 - teach the countdowns to talk! (continued) -* v0.8.4.5 - fix the player not being reset properly after a fight -* v0.8.4.4 - teach the countdowns to talk! -* v0.8.4.3 - add hook to add required spawns via modules -* v0.8.4.2 - revert hook for sabotage arena, fix Player velocity on respawn -* v0.8.4.1 - add hook for sabotage arena, ArenaType.onEntityExplode -* v0.8.4.0 - read default classes from config.yml, if set -* v0.8.3.0 - add blacklist/whitelist for block breaking -* v0.8.2.3 - fix droppings inside the spectator area -* v0.8.2.2 - only track plugin if used (if arenas defined) -* v0.8.2.1 - add arena wide command whitelist -* v0.8.2.0 - rewrite in order to fix the player teleporting / ghosting issue -* v0.8.1.0 - major fix - more to come, but this is a severe bug fix -* v0.8.0.0 - major rewrite of player death handling, fixes many things \ No newline at end of file diff --git a/doc/history/0.9.md b/doc/history/0.9.md deleted file mode 100644 index 57b7068e1..000000000 --- a/doc/history/0.9.md +++ /dev/null @@ -1,203 +0,0 @@ -== PVP-Arena v0.9 Changelog - -* v0.9.9.18 - /pa [arena] region [regionname] border - YAY! -* v0.9.9.17 - don't spawn players on flags. derp :p -* v0.9.9.16 - activate region force join - hooray! -* v0.9.9.15 - enhance the battlefield quit process: add "death" instead of kick -* v0.9.9.14 - add SPAWN regions that >enforce< random spawning -* v0.9.9.13 - broadcast when a player / team is ready -* v0.9.9.12 - allow data values for blacklist and whitelist -* v0.9.9.11 - SET - stop being so damn PICKY about cases! -* v0.9.9.10 - regions are now safe when the arena is off/disabled :p -* v0.9.9.9 - add /pa togglemodule/!tm [module] !!! -* v0.9.9.8 - add running commands in ALL arenas /pa ALL [...] -* v0.9.9.7 - fix node collision: battlefieldguard=> BFGACTIVE -* v0.9.9.6 - fix spectating cause an NPE -* v0.9.9.5 - fix internal modules vanishing on reload -* v0.9.9.4 - fix CLASS help -* v0.9.9.3 - add module hooks to BattlefieldJoin start -* v0.9.9.2 - add BetterGears - COLORED DYES -* v0.9.9.1 - fix the place/break whitelist / blacklist ! -* v0.9.9.0 - fix /pa install | uninstall | update -* v0.9.8.25 - support TEAM based PlayerLives goal !! -* v0.9.8.24 - support TANK gamemode - welcome back !! -* v0.9.8.23 - activate MOBS protection, and teach Listeners some RESPECT -* v0.9.8.22 - rewrite spawning (FREE) - new config settings! -* v0.9.8.21 - split the announcing of "join the arena!" (ADVERT) and "let the fight begin" (START) -* v0.9.8.20 - make sure PA loads after SKINS dependencies -* v0.9.8.19 - re-introduce arena.getWorld() -* v0.9.8.18 - update Skins language -* v0.9.8.17 - allow setting classes to have empty inventory -* v0.9.8.16 - update importer (weapondamage), remove unnecessary WORLD node from config! -* v0.9.8.15 - fix an ConcurrentModificationException about region restoring -* v0.9.8.14 - fix #97 - Other -- Additional grammar issues - ITERVAL !!!!! -* v0.9.8.13 - add /pa [arena] start -* v0.9.8.12 - add proper functionality to /pa [arena] spectate -* v0.9.8.11 - finally implement the SOFT version of a player leave - FIX ppl spectating after death -* v0.9.8.10 - fix the ArenaRunnable implementation ("XXX has not been scheduled yet") -* v0.9.8.9 - restructure the player removal to allow proper removement by modules -* v0.9.8.8 - add #96 - Feature Request - Ability to disable armor durability -* v0.9.8.7 - properly update the config if nodes are missing -* v0.9.8.6 - add #92 - Feature Request - List number of players per team -* v0.9.8.5 - fix #85 - Other - Grammar fix for capturing a flag? -* v0.9.8.4 - support WorldEdit auto loading and saving of BATTLE regions -* v0.9.8.3 - add module hooking into class selection -* v0.9.8.2 - add config node and langage for BetterClasses -* v0.9.8.1 - re-add module arena start handling -* v0.9.8.0 - rewrite the arena start. use with caution! -* v0.9.7.14 - fix part of #101 - free team can be colored other than WHITE -* v0.9.7.13 - fix #103 - Bug - FFA games not ending! -* v0.9.7.12 - fix #98 - Bug - Fire continuation after leaving/death -* v0.9.7.11 - remove debug -* v0.9.7.10 - quick fix for players not being properly set to fighting state -* v0.9.7.9 - more output and less team resetting -* v0.9.7.8 - properly update the gamemode when it is being set -* v0.9.7.7 - never code when your brain is infected! -* v0.9.7.6 - fix fixes causing broken commands -* v0.9.7.5 - fix #84 - Bug - Disconnecting with flag does not reset flag -* v0.9.7.4 - add missing classes -* v0.9.7.3 - fix #90 - Bug - Class signs with player names not working properly. -* v0.9.7.2 - fix #89 - Bug - Unable to join arena on a specific team -* v0.9.7.1 - fix Sabotage spawning a second destructive TNT -* v0.9.7.0 - welcome back, Sabotage! -* v0.9.6.30 - remove calling of the unused ArenaGoal.commitJoin method -* v0.9.6.29 - add soft depends to fix loading issues -* v0.9.6.28 - place every flag block on the player's head for now -* v0.9.6.27 - prevent removing your head gear when carrying a flag -* v0.9.6.26 - attempt to fix disconnecting players not resetting carried flags -* v0.9.6.25 - reset WoolHeads even if inventories should not be reset -* v0.9.6.24 - fix regions activating all protections on server start -* v0.9.6.23 - fix players being able to re-join a match -* v0.9.6.20 - fix regions being messed on restarting -* v0.9.6.19 - more debug -* v0.9.6.18 - Items -* v0.9.6.17 - aiming to fix the player drops being dropped at the respawn position instead of the death position -* v0.9.6.16 - fix non-pvp deaths messing up the Flags goal -* v0.9.6.15 - fix .10 -* v0.9.6.14 - fix the FFA game mode team count logic -* v0.9.6.13 - globally activate head gear removal prevention -* v0.9.6.12 - fix saved players not being physically reset -* v0.9.6.11 - quick debug NPE fix -* v0.9.6.10 - re-enable Debug override -* v0.9.6.9 - fix inventory loss because of disconnect and server crash, finally -* v0.9.6.8 - there are more signs! -* v0.9.6.7 - allow readying up and using signs in the lounge -* v0.9.6.6 - add a bit more of debug -* v0.9.6.5 - fix an NPE in the InventoryRefillRunnable -* v0.9.6.4 - fix issue #81 -* v0.9.6.3 - fix the last commit which in fact broke more than it should fix -* v0.9.6.2 - fix refillInventory -* v0.9.6.1 - fix the Location->Block calculation -* v0.9.6.0 - add /pa import [arenaname] - v0.8 import! -* v0.9.5.21 - fix TeamDeathMatch kill announcement #2 -* v0.9.5.20 - fix TeamDeathMatch kill announcement -* v0.9.5.19 - add default spawn "exit" to possible spawns -* v0.9.5.18 - reactivate /pa reload -* v0.9.5.17 - enhance and finish the help system -* v0.9.5.16 - fix issue #72.1 | block offset in negative X/Z ranges - fix issue #72.1 | block offset in negative X/Z ranges -* v0.9.5.15 - fix issue #71 -* v0.9.5.14 - hotfix -* v0.9.5.13 - finish .11 -* v0.9.5.12 - fix players being said to be in an arena when they aren't -* v0.9.5.11 - fix players being able to mess up the lounge / spectator / battlefield before starting -* v0.9.5.10 - attempt to fix the player status error with BattlefieldJoin (no lounges) -* v0.9.5.9 - last player(s) teleport bug -* v0.9.5.8 - fix wrong player death handling at the end of the arena -* v0.9.5.7 - enhancing help messages to reflect shorthand commands -* v0.9.5.6 - update all modules. This is information and order :p -* v0.9.5.5 - integrate NodinChan's loader, the update is just. f. -* v0.9.5.4 - fix StandardLounge + FreeForAll -* v0.9.5.3 - fix Runnables being cancelled when not being running -* v0.9.5.2 - fix tracker / stats deactivation derpyness -* v0.9.5.1 - fix player reset (first restore, then teleport) -* v0.9.5.0 - add /pa round -* v0.9.4.1 - add /pa stats -* v0.9.4.0 - add /pa help -* v0.9.3.52 - add language and config for the duel module -* v0.9.3.51 - properly tell a player that an arena is disabled -* v0.9.3.50 - don't ask... -* v0.9.3.48 - fix a blockrestore bug about regions -* v0.9.3.47 - fix joining not cancelling the start countdown, finally -* v0.9.3.46 - reanimate StandardSpectator -* v0.9.3.45 - fix two language issues -* v0.9.3.44 - add some little debug to StartRunnable -* v0.9.3.43 - revert InventoryRefillRunnable to be a simple Runnable -* v0.9.3.42 - correctly display /pa list - depending on game mode, fix player damage on teleport -* v0.9.3.41 - use BukkitRunnables instead of Runnables -* v0.9.3.40 - fix respawning players not being restored under certain circumstances -* v0.9.3.39 - fix the Timers -* v0.9.3.38 - fix #29 - Inventory not being restored on respawn. Hilarious collateral damage! -* v0.9.3.37 - fix the Flag goal not activating spawn setting -* v0.9.3.36 - fix a bug about timers ^^ -* v0.9.3.35 - add a tiny bit more debug -* v0.9.3.34 - aim to fix #57 and #46 -* v0.9.3.33 - fix players DCing / being kicked getting double refund (and other things) -* v0.9.3.32 - fix the next NPE ^^ -* v0.9.3.31 - quick fix for a sleeping NPE -* v0.9.3.30 - possibly resolve #46 - Bug -- Stuck in the floor? -* v0.9.3.29 - try to fix ticket #55 - Bug -- Min/Max player limit not working -* v0.9.3.28 - hopefully fix ticket #58 - NPE while joining when the arena is full -* v0.9.3.27 - fix ticket #59 - Bug -- Champion team is announced numerous times -* v0.9.3.26 - startup error fix -* v0.9.3.25 - fix bug #56 -* v0.9.3.24 - yet another attempt to fix the spawn bug -* v0.9.3.23 - fix tickets #48, #52 -* v0.9.3.22 - a new attempt to fix the spawn bug -* v0.9.3.21 - fix several small things -* v0.9.3.20 - aims to fix the spawn issues -* v0.9.3.19 - fix some more color issues -* v0.9.3.18 - fix bug #41 -* v0.9.3.17 - fix players not always getting told they are ready -* v0.9.3.16 - fix players being able to drop stuff in the lounge ^^ -* v0.9.3.15 - separate edit mode and arena lock state -* v0.9.3.14 - fix the start countdown -* v0.9.3.13 - fix a NPE about player chatting, language tweaks -* v0.9.3.12 - fix playerLeave -* v0.9.3.11 - remove debug StackTrace for ticket #32 -* v0.9.3.10 - fix the SpawnManager choking on block locations -* v0.9.3.9 - fix IllegalStateException for configParse -* v0.9.3.8 - aim to fix ticket #31 -* v0.9.3.7 - fix tickets #25, #32 -* v0.9.3.6 - fix tickets #33, #34, add debug StackTrace for Ticket #32 -* v0.9.3.5 - language fixes -* v0.9.3.4 - and another one. aiming to fix arenas not announcing players leaving the arena -* v0.9.3.3 - for mibby -* v0.9.3.2 - fix /pa reload resetting configs - finally :/ -* v0.9.3.1 - fix an NPE (BlockChange), remove EDIT calling STOP, fix the command whitelist -* v0.9.3.0 - PACheckResult -> rewrite -> PACheck | new check, commit, parse system -* v0.9.2.12 - fix the even check, ticket #28 -* v0.9.2.11 - fix people not being able to ready themselves up in special cases -* v0.9.2.10 - remove debug, fix #19 and #20 -* v0.9.2.9 - fix the startup, affecting VAULT (entryfee), announcements (join message) and more -* v0.9.2.8 - fix several little issues -* v0.9.2.7 - resolve #3, #4, #5, #7, #8, #9, #18 -* v0.9.2.6 - final fix of #2,#11,#15,#16,#17 -* v0.9.2.5 - fix spam of "No arenas found!" -* v0.9.2.4 - fix Issues #2,#11,#15,#16,#17 -* v0.9.2.3 - fix Issue #12,#13 -* v0.9.2.2 - fix a NPE -* v0.9.2.1 - fix a display bug about the Protection command help -* v0.9.2.0 - inventory issue fixed! -* v0.9.1.X - beta test release -* v0.9.0.0 - major organisation rewrite -** <<<<< changes since v0.8.12.5 >>>>> -** use NC-BukkitLib instead of NC-LoaderLib -** the region modules are not "Regions", they are "RegionShapes" ;) -** attach the chatting determination to the player, not to an arena -** remove ArenaType, add ArenaGoal (one type => multiple goals) -** remove lives from the main plugin, attach this logic to the arena goals -** remove positions from the arena, attach to player -** enormous rewrite considering renaming, restructuring, improvements during 1.0 development -** intense command rewrite -** <<<<< updated commits of v0.8.12.5 >>>>> -** allow other-world-spawns -** flatfile inventories for restoring -** [PVP Arena] [arenaname] -> format properly -** arena welcome message per arena -** check what to repair on interact / hit (dont reset every freaking block :p ) -** intelligent and case insensitive arena guessing -** ready up with /pa ready -** splash damage/healing affects teams correctly -** teleport -> 2L -> inv save -** inv restore -> 2L -> teleport -** rewards: "rewards-min-players" \ No newline at end of file diff --git a/doc/history/1.0.md b/doc/history/1.0.md deleted file mode 100644 index c5e1be38e..000000000 --- a/doc/history/1.0.md +++ /dev/null @@ -1,284 +0,0 @@ -== PVP-Arena v1.0 Changelog - -=== Changelog - -* v1.0.9.292 - maybe support CrackShot and other plugins utilizing "only" projectiles -* v1.0.9.291 - add more goal specific events -* v1.0.9.290 - enhance duel module messaging -* v1.0.9.289 - add regiontypes! BL_INV / WL_INV => blacklist / whitelist inventory -* v1.0.9.288 - make /pa teams properly read the color variables -* v1.0.9.287 - compare changes or fix greedy replacements - derp -* v1.0.9.286 - if we have to care about case, we should do it the right way and constistently -* v1.0.9.285 - fix the install.yml error and add the new curse API updater -* v1.0.9.284 - don't remove a player from the has played list if we need to track them -* v1.0.9.283 - add a Vault setting to only allow betting during the first X seconds -* v1.0.9.281 - add language for chestfiller reset -* v1.0.9.279 - fix BattleFieldJoin putting ppl nowhere before the match started -* v1.0.9.278 - allow to enforce late joining only to initial players "onlyifhasplayed" -* v1.0.9.277 - remove import command. goodbye, v0.8 -* v1.0.9.276 - properly iterate through random spawns -* v1.0.9.275 - actually allow multiple block related goals -.- -* v1.0.9.274 - allow Potions to contain more than one effect - derp -* v1.0.9.271 - make PAJoinEvent and PAStartEvent cancellable -* v1.0.9.270 - add a DBO guideline compliant updater -* v1.0.8.269 - yippie, fixed? -* v1.0.8.268 - revert the replacement of the color code char. gg slipcor -* v1.0.8.267 - hackfix commands to work for players being in the LateLounge queue -* v1.0.8.266 - allow "quickloot" per arena, so players just click a chest to loot -* v1.0.8.265 - silently support BattlefieldManager [/spoiler] -* v1.0.8.264 - minor language format fix -* v1.0.8.263 - don't reset skulls because they receive no damage :P -* v1.0.8.262 - do not drop experience if there is none to drop -* v1.0.8.261 - seriously, bukkit - Y U F up? -* v1.0.8.260 - reset EXP on death (if dropping) -* v1.0.8.259 - drop orbs, because bukkit doesn't want to -* v1.0.8.258 - create pseudo teams before trying to teleport members to it -* v1.0.8.257 - properly implement Bukkit 1.6 API -* v1.0.8.256 - update to MC 1.6 - Bukkit 1.6.2-R0.1 -* v1.0.8.255 - never gonna give you up, #254 -* v1.0.8.254 - fix EXP not properly dropping on some occasions -* v1.0.8.253 - #252 - next try -* v1.0.8.252 - allow late join for PlayerKillReward -* v1.0.8.251 - fix late joining spawns and /pa [arena] teams -* v1.0.8.250 - support class spawns and fix issue #249, revealing that spawning was still broken -* v1.0.7.249 - remove dead code and properly add spawns & blocks when defining them -* v1.0.7.248 - attemt to fix issues #618 and #621 -* v1.0.7.247 - fix spawning, please - (begging works, fyi) -* v1.0.7.246 - add more debug, because everyone loves debugging :) -* v1.0.7.245 - properly check the TNT flag, not the FIRE flag -* v1.0.7.244 - [BREAKING?] - only for dev tests! - SpawnManager rewrite -* v1.0.7.243 - fix ValeraSTK's spawning - break others? no clue -* v1.0.7.242 - spawn debug enhancement (maybe fix) -* v1.0.7.241 - finally fix initial spawning (maybe) -* v1.0.7.240 - enhance the debug for Wahrheit -* v1.0.7.239 - Wahrheit will love this fix! -* v1.0.7.238 - fix an NPE in /pa stats -* v1.0.7.237 - apply default chat parameter -* v1.0.7.236 - allow Wahrheit to use multiple team spawns with PlayerLives -* v1.0.7.235 - allow to require a minimum game length to reward -* v1.0.7.234 - allow to find out how long an arena is running -* v1.0.7.233 - maybe fix the issue by supporting spawn maps? -* v1.0.7.232 - clarify debug for #578 -* v1.0.7.231 - stop punishing players that are left alone. Reward them! -* v1.0.7.230 - re-add announcement config language node -* v1.0.7.229 - try to fix tank spawning -* v1.0.7.228 - add infect death debug - investigating #578 -* v1.0.7.227 - add language node debug - for all the debugs I don't understand :P -* v1.0.7.226 - fix a minor language issue -* v1.0.7.225 - add "customReturnsGear" - allows to play with items but not bringing/taking things -* v1.0.7.224 - prevent death as promised -* v1.0.7.223 - support third party health boosts that vanish after joining -* v1.0.7.222 - maybe fix an issue about autoClass not working on some occasions? -* v1.0.7.221 - properly set the claimed determination map -* v1.0.7.220 - add announce offset and points limitation for DOM -* v1.0.7.219 - properly use wool byte instead of dye byte -* v1.0.7.218 - add autovote autostart - so PA manages ALL THE SERVERS -* v1.0.7.217 - stop breaking servers that didnt want stats in the first place -* v1.0.7.216 - reset stats for admins that /pa reload -* v1.0.7.215 - do not set to an empty path - sry... -* v1.0.7.214 - hell yeah. How about we save the player files? Derp! - thx, Uhehesh -* v1.0.7.213 - stop creating debug files if we don't need them. please... -* v1.0.7.212 - fix startup NPE due to Statistics -* v1.0.7.211 - properly support "none" as an item list -* v1.0.7.210 - for ravand and others: CONFIG: autovote only spams to JOIN regions -* v1.0.6.209 - properly apply #208 and always load the yml! -* v1.0.6.208 - properly load statistics from the player.yml - since when is this broken!? -* v1.0.6.207 - try to fix spawn calculation for the infect goal -* v1.0.6.206 - properly escape & before blindly handing it to the colorize method -* v1.0.6.205 - first check if the arena is running, then check for other errors -* v1.0.6.204 - be prepared for weird multi world setups (a bit better) -* v1.0.6.203 - add proper player name when debugging a player -* v1.0.6.202 - try to fix join edit mode determination - and fix 80% of the lag caused by joining -* v1.0.6.201 - allow to enforce the start countdown -* v1.0.6.200 - allow to restrict autovote to one world, or multiple worlds - allow to restrict autovote to one world, or multiple worlds -* v1.0.6.199 - reduce kill count of deathmatch goals for the DEATH region flag -* v1.0.6.198 - allow taking specific things out of the match -* v1.0.6.197 - add some language nodes for proper error/notice display -* v1.0.6.196 - enhance/clarify debug -* v1.0.6.195 - add the possibility to interact in lounge mode -* v1.0.6.194 - awesome feature: join a game before it has begun -* v1.0.6.193 - everyone loves derpy server implementations -* v1.0.6.192 - add config setting for respawnrelay spawn choosing -* v1.0.6.191 - allow to respawn to a specific spawn -* v1.0.6.190 - update Metrics to revision 7 -* v1.0.6.189 - adjust reward handling for FREE arenas to reflect the recent rewrites -* v1.0.6.188 - add language per arena; add items.excludeFromDrops -* v1.0.5.187 - prepare for a language rewrite, fix all warnings! -* v1.0.5.186 - allow to set config materials by "hand" and items by "inventory" -* v1.0.4.185 - enhance arena list command display -* v1.0.4.184 - add PAPlayerClassChangeEvent -* v1.0.4.183 - try fixing BlockDestroy ending -* v1.0.4.182 - fix NPE -* v1.0.4.181 - craftbukkit is a lie! -* v1.0.4.180 - add a warning if a player has a state when joining (no autoClass then?) -* v1.0.4.179 - properly call PAExitEvent and PALeaveEvent on timed end -* v1.0.4.178 - fix little NPE -* v1.0.4.177 - add a max radius to PlayerFinder -* v1.0.4.176 - try to fix PlayerKillReward -* v1.0.4.175 - properly remove spectators -* v1.0.4.174 - fix #473, #474, #478, #493, #498, #505 -* v1.0.4.173 - allow to debug to server.log, oldschool, if files are not working -* v1.0.4.172 - allow to disallow arena gameplay if player has a scoreboard -* v1.0.3.171 - revert an attempt to fix rewards (leading to double rewards and messed up players) -* v1.0.3.170 - finally allow of force joining players to a team -* v1.0.3.169 - properly start timers. this time for real. -* v1.0.3.168 - little region tick rewrite -* v1.0.3.167 - fix #486 -* v1.0.3.166 - allow disallowing of spectator talk -* v1.0.3.165 - verify that rewards were not already given -* v1.0.3.164 - various fixes -* v1.0.3.163 - properly put BlockDestroy loser to the lose location -* v1.0.3.162 - fix Valera's server. btw: v2.0 is a LIE! -* v1.0.3.161 - update player's inventories. just because we can -* v1.0.3.160 - revert #155; fixed properly in #159 -* v1.0.3.159 - spectators and players in lounge do NOT have lives! -* v1.0.3.158 - revert #156; fix readyup countdown messups -* v1.0.3.157 - only care about arena players teleporting OUT, not FROM OUTSIDE -* v1.0.3.156 - properly initiate spectators -* v1.0.3.155 - properly initiate late joining players -* v1.0.3.154 - hackfix lore - we need v2.0 ! -* v1.0.2.153 - check region ticks on everyone, not just fighters -* v1.0.2.152 - fix custom potions and colored description/lore -* v1.0.2.151 - catch a NPE about deaths -* v1.0.2.150 - properly read item descriptions -* v1.0.2.149 - never stop WATCH region timers. period. -* v1.0.2.148 - properly give rewards when time determines the winners -* v1.0.2.147 - remove arrows from players; this is said to cause crashes -* v1.0.2.146 - properly update plugin files that have been renamed -* v1.0.2.145 - add some more debug to 3 (arena) -* v1.0.2.144 - fix an announcement not happening in special cases -* v1.0.2.143 - add all the helmets! And check before replacing the helmet ;) -* v1.0.2.142 - force ready up people joining late on an arena that counts down to start -* v1.0.2.141 - fix NPE -* v1.0.2.140 - genius developer! Check if too far away before joining. -* v1.0.2.139 - check for worlds before comparing locations -* v1.0.2.138 - fix /pa shutup with arguments! -* v1.0.2.137 - don't spam the winning/losing message for every remaining infect player -* v1.0.2.136 - properly allow players to fly if they ... did Oo -* v1.0.2.135 - fix infected player display, attempt tp properly end the infected mode -* v1.0.2.134 - Only force arena configuration loading if configs were messed up -* v1.0.2.133 - Reload root config and all arena configs, even lost ones! -* v1.0.1.132 - Fix displayname loading -* v1.0.1.131 - STOP removing paintings on arena end. You idiot plugin! -* v1.0.1.130 - add legacy types "infect" and "liberation" -* v1.0.1.129 - add a way of not using plugins in "Skins" module -* v1.0.1.128 - properly set un-infected players' lives -* v1.0.1.127 - properly round decimal calculation -* v1.0.1.126 - support decimals in life display (for pillars) -* v1.0.1.125 - support autoClass definitions per team -* v1.0.1.124 - properly calculate losing players -* v1.0.1.123 - stop giving rewards to matches where more than half of the players win -* v1.0.1.122 - attempt to fix an NPE about colored items -* v1.0.1.121 - attempt to fix TNT ignite determination -* v1.0.1.120 - update blockrestore config to allow block restore disabling -* v1.0.1.119 - don't clear the killrewards map after one match. bad plugin! -* v1.0.1.118 - start join tasks when resetting an arena -* v1.0.1.117 - fix leaf decay determination -* v1.0.1.116 - fix block listener logic -* v1.0.1.115 - fix v#113 to support woolheads -* v1.0.1.114 - prevent exception when spawns are on different worlds -* v1.0.1.113 - properly clear inventory when changing via arenaclass command -* v1.0.1.112 - alter v110 fix to only apply for Snowballs. Fixes #375 -* v1.0.1.111 - properly start JOIN tick before arena start. Fixes #370 -* v1.0.1.110 - allow projectiles to knock back -* v1.0.1.109 - attempt to fix v108 and v102 -* v1.0.1.108 - more precise debugging -* v1.0.1.107 - properly start an arena with BattlefieldJoin and no regions -* v1.0.1.106 - more secret fixes -* v1.0.1.105 - fix getLives method of ArenaGoals -* v1.0.1.104 - more hacking for automation -* v1.0.1.103 - properly deny players joining an arena because of explicit perms missing -* v1.0.1.102 - properly save, fix and revert fly mode -* v1.0.1.101 - make y offset configurable and add nodamage timer on leave -* v1.0.1.100 - add /pa [arena] playerjoin [playername] {team} - join enforcing -* v1.0.1.99 - add API access to player's teams and team names -* v1.0.1.98 - properly print error message when arena is full; #343 -* v1.0.1.97 - properly implement the proper implementation of adding players to the life pool -* v1.0.1.96 - add the "CustomSpawn" module to define custom named spawns -* v1.0.1.95 - attempt to fix statistics madness -* v1.0.1.94 - Support CUSTOM POTIONS - fixes ticket #330 -* v1.0.1.93 - EventActions now is able to activate redstone! -* v1.0.1.92 - properly implement players adding to the life pool -* v1.0.1.91 - fix AIOOB error due to /pa install -* v1.0.1.90 - optimization and TagAPI fix for autovote -* v1.0.1.89 - enhance information about config messups -* v1.0.1.88 - allow giving/taking food for pvp killing -* v1.0.1.87 - add /pa [arena] shutup - disables arena announcements -* v1.0.1.86 - repair tools when breaking blocks -* v1.0.1.85 - pro tip: when altering the Config, save it! -* v1.0.1.84 - properly parse /pa round arguments -* v1.0.1.83 - fix /pa round error message -* v1.0.1.82 - allow modules to hook into tnt explosions in unprotected regions -* v1.0.1.81 - automatically ready ppl that join and select a class when an arena is starting -* v1.0.1.80 - fix BattlefieldJoin (direct joining) -* v1.0.1.79 - fix Infect goal. Strange noone witnessed this :p -* v1.0.1.78 - revert v0.10.0.3 (zOMG), fix re-join arenas messing up -* v1.0.1.77 - default to teamkill = true -> fixes 99% of all issues :p -* v1.0.1.76 - stop respawning players that have lost a TDM match! -* v1.0.1.75 - don't reset the (ready) countdown if player count is ok -* v1.0.1.74 - add Citizens support (don't remove NPCs) -* v1.0.1.73 - fix #295 - display proper help when trying to set spawn wrongly -* v1.0.1.72 - add SpecialJoin setting for player count display -* v1.0.1.71 - add [team]foodfurnace to only allow the team to use THAT furnace -* v1.0.1.70 - fix tank winning message -* v1.0.1.69 - fix /pa class load [classname] - remember: /pa class done ! -* v1.0.1.68 - and, yeah fixed /pa stats ! -* v1.0.1.67 - half-assed fix for arenaboards, so that they at least display SOMETHING -* v1.0.1.66 - fix the TNTBREAK flag, this (finally) prevents block damage -* v1.0.1.65 - support "My Worlds" worlds -* v1.0.1.64 - fix splash potions for free for all arenas -* v1.0.1.63 - repair bows if wanted -* v1.0.1.62 - finish JavaDocs for ArenaGoal and ArenaModule -* v1.0.1.61 - finish /pa info output -* v1.0.1.60 - add Walls MATERIAL and RespawnRelay SECONDS config setting -* v1.0.1.59 - enhance /pa info output -* v1.0.1.58 - update LateLounge to display queue position -* v1.0.1.57 - oups, default to NOT "claimall" for Pillars -* v1.0.1.56 - Add [m]PlayerFinder, [m]Walls, enhance Pillars -* v1.0.1.55 - Add GOAL: Food! -* v1.0.1.54 - save regions on region update. This should prevent WorldEdit messups when resizing. -* v1.0.1.53 - fix StringParser, bug about LORE affected player dumps and classes -* v1.0.1.52 - fix #271 - properly handle mis-set wand settings instead of spamming -* v1.0.1.51 - fix and improve arena creation, add proper message if no goal active -* v1.0.1.50 - allow colored prefixes, fix BlockDestroy destruction detection -* v1.0.1.49 - fix what NodinChan promised: You dun goofed! -* v1.0.1.48 - improve handling of admins sticking files into wrong folders -* v1.0.1.47 - fix #2 and #4 of Ticket #262 -* v1.0.1.46 - try fixing Ticket #209, correctly remove player from arena -* v1.0.1.45 - add LIBERATION! [ WIP! ] -* v1.0.1.44 - add INFECT! -* v1.0.1.43 - add class spawns! -* v1.0.1.42 - properly add a draw for team games -* v1.0.1.41 - revert former "fixes" + stop resetting configs! -* v1.0.1.40 - finally fix the timed end bug! -* v1.0.1.39 - attempt #3 to fix the timed end -* v1.0.1.38 - attempt #2 to fix the timed end -* v1.0.1.37 - properly reset ArenaPlayers on timed end -* v1.0.1.36 - properly reset ArenaPlayers that still have a team -* v1.0.1.35 - fix some little derping inside the goal winning management -* v1.0.1.34 - Turret module settings and spawn management! -* v1.0.1.33 - fix #251 - rather than triggering the end, check for remaining teams -* v1.0.1.32 - fix #209 - only replace BlockDestroy Block if more lives than blocks! -* v1.0.1.31 - Pillars config setting fix -* v1.0.0.30 - more pillar configuration! -* v1.0.0.29 - PILLAR goal! -* v1.0.0.28 - fix more issues with CB 1.7 and respawning -* v1.0.0.27 - override .equals() for PALocation and PABlockLocation -* v1.0.0.26 - fix an NPE due to disconnecting when the arena checks if it is ready -* v1.0.0.25 - fix WarmupJoin - anyone remember stupid messups? Now we know why. -* v1.0.0.24 - fix the Map.clone() issues in all goals -* v1.0.0.23 - what you say! -* v1.0.0.22 - rewrite part one: fix lives. affects ALL GOALS! -* v1.0.0.21 - fix a little NPE in BlockDestroy goal. REWRITE incoming! -* v1.0.0.20 - new attempt to fix the .clone() issue -* v1.0.0.19 - revert #18 - first sleep then code. night! -* v1.0.0.18 - .clone() Lesson 1: unlink field references -* v1.0.0.17 - wait. what? if this fixes it, Im gonna... -* v1.0.0.16 - add to /pa debug 102 -* v1.0.0.15 - add to /pa debug 9 -* v1.0.0.14 - support multiple destroyable blocks! -* v1.0.0.13 - fix #243 - trying to add a team -* v1.0.0.12 - don't send messages if empty -* v1.0.0.11 - fix an NPE when calculating the winner -* v1.0.0.10 - attempt to fix Ticket #193,#198,#209 -* v1.0.0.1 - update versions and readme \ No newline at end of file diff --git a/doc/history/1.1.md b/doc/history/1.1.md deleted file mode 100644 index 599f3824e..000000000 --- a/doc/history/1.1.md +++ /dev/null @@ -1,131 +0,0 @@ -== PVP-Arena v1.1 Changelog - -=== Changelog - -* v1.1.2.420 - add config settings for DBO ticket 815 -* v1.1.2.419 - don't trigger a score trigger for destroying your own block -* v1.1.2.418 - remove unneeded event, there is a static hook present! -* v1.1.2.417 - properly implement the event -* v1.1.2.416 - add "proper" (hackfix) API to use Announcements in other modules -* v1.1.2.415 - update classes for 1.7 -> ProjectileSource -* v1.1.2.414 - update to bukkit 1.7 -* v1.1.2.413 - fixed: add goal "PlayerDeathConfirm" - FUN FUN FUN !!! -* v1.1.2.412 - jenkins no likey switch? -* v1.1.2.411 - add goal "PlayerDeathConfirm" - FUN FUN FUN !!! -* v1.1.1.410 - take worlds into account when comparing region overlap -* v1.1.1.409 - expose shortcut definitions and values -* v1.1.1.408 - consoleoffduty: allow the console to use shortcuts by default -* v1.1.1.407 - actually allow usage of /pa duty -* v1.1.1.406 - revert 403 and 405 - sorry, moo :P -* v1.1.1.405 - fix 403 - maybe -* v1.1.1.404 - shortcut determination debug enhancement -* v1.1.1.403 - try to queue teleports at the end, for less invisibility?? -* v1.1.1.402 - adds /pa duty; adding github issue #41 -* v1.1.0.401 - address github issue #44 -* v1.1.0.400 - address github issue #42 - hooray for single arena shortcuts! -* v1.1.0.399 - address github issue #46 -* v1.1.0.398 - change inv clearing: NONE / SURVIVAL / CREATIVE / ALL -* v1.1.0.397 - fix issue #808 - team kills score in TDM -* v1.1.0.396 - properly / sanely initiate shortcut definition defaults -* v1.1.0.395 - make classes.yml copy-able - needs reordering if you already set global classes. sorry! -* v1.1.0.394 - add a "maxhealth" setting to alter starting health, and allow setting health to -1 for FULL health -* v1.1.0.393 - allow admins to create multiple battle regions and only need players to be in one of those -* v1.1.0.392 - allow for case insensitive ALL / FULL debug -* v1.1.0.391 - fix Liberation LOST determination -* v1.1.0.390 - add "items.keepOnRespawn" to ... duh... keep items on respawn -* v1.1.0.389 - add "clearCreative" setting to clear creative players before joining -* v1.1.0.388 - properly unkill PlayerDeathMatch losers -* v1.1.0.387 - properly mark users as such -* v1.1.0.386 - tweak liberation debug output -* v1.1.0.385 - properly return that there are not enough players -* v1.1.0.384 - finalize the finalization -* v1.1.0.383 - finalize the arena shortcut system -* v1.1.0.382 - don't remove liberation and TDM players on the final kill -* v1.1.0.381 - have playerdeathmatch and playerkillrewards reflect default arena ending behaviour -* v1.1.0.380 - double check each goal if the arena is counting down to end -* v1.1.0.379 - attempty to activate loggers per arena ... maybe? -* v1.1.0.378 - properly display warning on module enabling -* v1.1.0.377 - support tank late joining, addresses github issue #40 -* v1.1.0.376 - fix class saving and load messup - sorry ! -* v1.1.0.375 - sort all the things! -* v1.1.0.374 - ... -* v1.1.0.373 - don't ask -* v1.1.0.372 - fix spectators not being completely reset -* v1.1.0.371 - allow specification of armor slot (0!BONE -> bone hat) -* v1.1.0.370 - totally not break anything by fixing githubg issue #37 -* v1.1.0.369 - address github issue #39 - rotation -* v1.1.0.368 - together with Announcements v367, fix github issue #38 -* v1.1.0.367 - plugin for sale. I pay you 100 bucks! -* v1.1.0.366 - never code when not drunk! -* v1.1.0.365 - clarify missing goal/arena file message -* v1.1.0.364 - run the "score" goal when players destroy blockdestroy blocks -* v1.1.0.363 - address github issue #36 - arenas are saved lowercase! -* v1.1.0.362 - add global class definitions, classes.yml -* v1.1.0.361 - allow for case insensitive lazy usage of shortcuts -* v1.1.0.360 - add /pa [arena] template save|load [file] -* v1.1.0.359 - finish /pa reload, reloading the main config and all arenas+subs -* v1.1.0.358 - correctly place shortcuts instead of arena names, when enforcing -* v1.1.0.357 - add pvparena.override - to specifically allow/deny special privileges -* v1.1.0.356 - add new main config settings to allow for arena management -* v1.1.0.355 - fix playerlives goal lives calculation for team arenas -* v1.1.0.354 - support hoppers and droppers and stuff for FOOD goal! -* v1.1.0.353 - if this breaks all the things, blame moo ! -* v1.1.0.352 - attempt to add readme files to the jar -* v1.1.0.351 - really fix the NPE mentioned in #351 -* v1.1.0.350 - fix strange refill runnable NPE -* v1.1.0.349 - don't require a lounge for infected people! -* v1.1.0.348 - force reset an arena if the start event has been cancelled -* v1.1.0.347 - properly allow autovote to access running arenas -* v1.1.0.346 - sanely handle non global non arena notification runnables -* v1.1.0.345 - add an evil invisibility fix attempt -* v1.1.0.344 - finally finish! fix arrows staying stuck on players! -* v1.1.0.343 - still onyl for moo !!! -* v1.1.0.342 - only for moo !!! arrow debugging! -* v1.1.0.341 - suprise, #340 now works -* v1.1.0.340 - fix invisibility - configurably -* v1.1.0.339 - stop removing region runnables if they are needed -* v1.1.0.338 - support max health changing ingame by double checking max health -* v1.1.0.337 - allow to select classes and ready up with right click -* v1.1.0.336 - actually apply proper duration and level for flag carrier potion effefct -* v1.1.0.335 - allow hunger disabling (player.hunger) -* v1.1.0.334 - stop starvation in the lounge -* v1.1.0.333 - attempt to properly remove liberation losers -* v1.1.0.332 - attempt to tackle github issue #16 and github issue #19 -* v1.1.0.331 - implement #330 in a more sane way -* v1.1.0.330 - allow mods to notify admins that forgot to set their regions to BATTLE -* v1.1.0.329 - check if anyone IS liberated before stating and giving points! fixes github issue #32 -* v1.1.0.328 - fix liberation liberation formatting -* v1.1.0.327 - address github issue #22 - properly parse dead player's chat and refill inventory -* v1.1.0.326 - address github issue #22 - read the player's team name rather than trying to teleport to nulljail -* v1.1.0.325 - suppress an issue about non arena players damaging arena players or vice versa - github issue #27 -* v1.1.0.324 - stop using multiple end countdowns at at time, addresses github issue #23 -* v1.1.0.323 - address github issue #19 - refresh arena debuggers -* v1.1.0.322 - allow players to re-ready -* v1.1.0.321 - omnom on force start github issue #16, maybe even github issue #14 -* v1.1.0.320 - stop counting suicides as deathmatch points - addresses github issue #29 -* v1.1.0.319 - attempt to maintain WATCH region maintainance -* v1.1.0.318 - properly check before blocking commands -* v1.1.0.317 - undo #316; try again later -* v1.1.0.316 - little gamemode deprecation fix -* v1.1.0.315 - automatically assign joining to one arena if only one is running -* v1.1.0.314 - in 3+ team games, properly determine if there is a draw -* v1.1.0.313 - bettergears config addition: only replace armor if leather -* v1.1.0.312 - prevent a NPE apparently happening on perm removal -* v1.1.0.311 - offer bettergears armor customisation; revert #310 -* v1.1.0.310 - offer betterclasses armor customisation -* v1.1.0.309 - language fixes, partially fixes github issue #23 -* v1.1.0.308 - addresses github issue #21 - hackfix -* v1.1.0.307 - add specific vault reward settings -* v1.1.0.306 - fix GitHub issue #18 -* v1.1.0.305 - restructure logging creating - now per command - maybe -* v1.1.0.304 - allow re-readying to initiate an arena start -* v1.1.0.303 - fix the Time Goal ending and NPE derp -* v1.1.0.302 - end games where people leave a Time Goal only match -* v1.1.0.301 - FORCE START OVERRIDE! let's pray this does not break all the thingsthat -* v1.1.0.300 - if this does not disable flying, you are hacking, mibby -* v1.1.0.298 - attempt to enforce flymode removal -* v1.1.0.297 - merge code optimisations by Iaccidentally -* v1.1.0.296 - nope, backwards compatibility is too hard - more changes to come. Hands off! -* v1.1.0.295 - try to establish backwards compatibility -* v1.1.0.294 - finish the ArenaRegion rewrite. Use with caution!!! -* v1.1.0.293 - rewrite the ArenaRegion system. Hope noone created their own Shapes yet :O \ No newline at end of file diff --git a/doc/history/1.2.md b/doc/history/1.2.md deleted file mode 100644 index 64df2c55f..000000000 --- a/doc/history/1.2.md +++ /dev/null @@ -1,78 +0,0 @@ -== PVP-Arena v1.2 Changelog - -=== Changelog - -* v1.2.4.494 - remove some debug spam about dye and leather data -* v1.2.4.493 - properly make use of the "keepOnDeath" together with "dropsInventory" -* v1.2.4.492 - remove the remaining Exceptions -.- -* v1.2.4.491 - remove debug leftovers - sorry! -* v1.2.4.490 - address DBO ticket #874 - various fixes/additions -* v1.2.4.489 - finally correctly address the inventory restoring issues (keepItems should be fixed now!) -* v1.2.4.488 - add showRemainingLives - allow hiding of the remaining lives -* v1.2.4.487 - fix little Arcade related NPE -* v1.2.4.486 - add (hacky) support for Arcade; and: jenkins maven repo! -* v1.2.4.485 - possibly fix PlayerLives ending? -* v1.2.4.484 - shift death parsing order; attempt to fix respawnrelay - ticket #792 -* v1.2.4.482 - [DOM] change announceOffset to display logic, not to count logic; addresses github issue #66 -* v1.2.4.481 - fix TDM kill output. address github issue #65; revert fix build #465 -* v1.2.4.480 - address github issue #64 -* v1.2.4.479 - add Domination tickinterval (60) and tickreward (1); adds github issue #60 -* v1.2.4.478 - fix a respawn relay NPE, e.g. when a player leaves while respawning -* v1.2.4.477 - more Inventory dropping/restoring fixes -* v1.2.4.476 - WARNING - MAYBE BREAKING -* v1.2.3.475 - add config settings for global points system -* v1.2.3.474 - address ticket #866 -* v1.2.3.473 - forward allowed items instead of the (mostly cleared) event drops -* v1.2.3.472 - add respawnrelay specific debug -* v1.2.3.471 - rewrite the smart respawning -* v1.2.3.470 - fixed debug -* v1.2.3.469 - even more debug :/ -* v1.2.3.468 - godgodgodgo - I will! [smart respawn debug spam] -* v1.2.3.467 - default to VILLAGER instead of WOOL as Rescue Entity -* v1.2.3.466 - add "Rescue" language and config node -* v1.2.3.465 - mibby sais push, slipcor pushes! -* v1.2.3.464 - another instance of false proclamation of rewards -* v1.2.3.463 - add final liberation kill, don't tell the arena the rewards have been given too early -* v1.2.3.462 - address github issue #46 - buffer team players -* v1.2.3.461 - fix WorldGuard language nodes -* v1.2.3.461 - fix arena player class determination -* v1.2.3.460 - fix "custom" classes not being considered as such, fixes #828 -* v1.2.3.459 - allow inventory access for Flag Holders; fixes #828 -* v1.2.3.458 - add WorldGuard config settings -* v1.2.3.457 - add PlayerClass command implementation -* v1.2.3.456 - add player created classes [pvparena.create.class] -* v1.2.3.455 - add better named ArenaBoard headers -* v1.2.3.454 - support colored ArenaBoard signs -* v1.2.3.453 - add default goal config settings -* v1.2.3.452 - add the teleport lag y-offset to "old" (pre-join) locations -* v1.2.3.451 - add ' ' to the non printed messages. addresses github issue #59 -* v1.2.3.450 - finish github issue #53 [Infect] -* v1.2.3.449 - small fixes -* v1.2.3.448 - [WARNING] only for mibby & github issue #54 - might break player resets!! - force remove players from arenas -* v1.2.3.447 - anyone having an issue with us NOT kicking everyone if the arena fails to start? addresses github issue #44 -* v1.2.3.446 - add PATeamChangeEvent for infect, tank and other things like that -* v1.2.3.445 - fix github issue #57 - modules/goals do not add default config settings -* v1.2.3.444 - [WARNING] only for mibby & github issue #44 - rewrote the start check, might either fix it or break everything -* v1.2.3.443 - add ColorTeams->ScoreBoard to use the scoreboard coloring instead of TagAPI -* v1.2.3.442 - little fixes, thanks to samoatesgames -* v1.2.3.441 - add debug for github issue #44 - countdown ignoring uneven teams -* v1.2.3.440 - add debug for github issue #46 - "teamrewards" -* v1.2.3.439 - [BlockDissolve] add "startSeconds" to wait X seconds before removing -* v1.2.3.438 - properly maintain sorting when handing over sorted collections -* v1.2.3.437 - add debug for github issue #43 -* v1.2.3.436 - properly save the config after setting an inventory to a config node -* v1.2.3.435 - add BlockDissolve config values -* v1.2.3.434 - only add needed config nodes -* v1.2.2.433 - [g:TeamLives] only mark a player as lost when needed -* v1.2.2.432 - verify #431 -* v1.2.2.431 - properly remove player names that are longer than 15 characters -* v1.2.2.430 - nerf #429 -* v1.2.2.429 - add an error stacktrace while unsuccessfully handling a sign removal -* v1.2.2.428 - finish the old/new updater! -* v1.2.2.427 - fix a ClassCastException when using /pa info -* v1.2.2.426 - change the updater to my former way for several reasons. see documentation -* v1.2.2.425 - add alwaysJoinInBattle - allow people to join late, no matter what! -* v1.2.2.424 - fix issue #830 - only care about players not playing or players part of the current arena -* v1.2.2.423 - enforce inventory reset (if wanted) -* v1.2.2.422 - properly reset the "players that have played" counters -* v1.2.2.421 - prepare for 1.8 - STEP 1: use player UUIDs for stats \ No newline at end of file diff --git a/doc/history/1.3.0.md b/doc/history/1.3.0.md deleted file mode 100644 index 5278f1ef0..000000000 --- a/doc/history/1.3.0.md +++ /dev/null @@ -1,66 +0,0 @@ -== PVP-Arena v1.3.0 Changelog - -- v1.3.0.558 - fix github issue #83 -- v1.3.0.557 - fix github issue #61 -- v1.3.0.556 - fix github issue #64 -- v1.3.0.555 - add x-offset and z-offset, so one can change the default behaviour of putting ppl on the middle of a block -- v1.3.0.554 - fix an NPE in some places due to a return value of null should be expected! -- v1.3.0.553 - add chat.toGlobal to allow private talking players to talk to the public with a prefix -- v1.3.0.552 - add CRAFT RegionProtection to prevent item crafting -- v1.3.0.551 - add damage.fromOutsiders (false) to allow players (and other entities) to hurt fighters -- v1.3.0.550 - properly check for some things before adding players to a class via command -- v1.3.0.549 - try to fix long usernames staying on signs -- v1.3.0.548 - prevent a NPE -- v1.3.0.547 - call the leave event - I am shocked noone noticed that until yesterday -- v1.3.0.546 - reverse all the things and do what I promised the last 2 commits -- v1.3.0.545 - fix books! (for real) -- v1.3.0.544 - fix books! -- v1.3.0.543 - trying again -- v1.3.0.542 - attempt to fix some data reading issues (for ink sacks and wool blocks) -- v1.3.0.541 - fix some display issues about max team players -- v1.3.0.540 - attempt to fix special character issues -- v1.3.0.539 - allow to take suicides into account for TDM -- v1.3.0.538 - still on github issue #78 - never remove perms! -- v1.3.0.537 - fix missing perms message, addressing github issue #78 -- v1.3.0.536 - finish github issue #78 - typo messup -- v1.3.0.535 - address github issue #78 - add language nodes for missing perms -- v1.3.0.534 - prevent tamed animals belonging to an arena player from teleporting -- v1.3.0.533 - finally fix github issue #76 - inventory reset messup -- v1.3.0.532 - address github issue #76 -- v1.3.0.531 - address github issue #64 -- v1.3.0.530 - add "classSwitchAfterRespawn", defaulting to false -- v1.3.0.529 - revert #523 - I don't care anymore - this HAS to fix it, otherwise I give up on development :P -- v1.3.0.528 - revert #519 - second attempt at fixing an issue on several implementations -- v1.3.0.527 - revert #518 - this fixed dbo issue #912 (duplications on Cauldron) but caused items disappearing on other implementations -- v1.3.0.526 - add more config settings for PlayerKillReward -- v1.3.0.525 - address DBO issue #923 -- v1.3.0.524 - address DBO issue #921 -- v1.3.0.522 - fix integer/integer divisions -.- -- v1.3.0.521 - clarify custom class determination debug -- v1.3.0.520 - clarify damage debug values -- v1.3.0.519 - forcefully place players where they joined if the player is disconnecting -- v1.3.0.518 - forcefully remove items when a player leaves the arena -- v1.3.0.517 - address DBO issue #907 - don't try to teleport null/dead players -- v1.3.0.516 - try fixing NOCAMP damage -- v1.3.0.515 - [IDEA] various fixes -- v1.3.0.511 - address DBO issue #888 - reset chat color if desired -- v1.3.0.510 - add mobs fighting by your side. Give classes a spawn egg with displayname "SPAWN" -- v1.3.0.509 - properly build #507 prefix -- v1.3.0.507 - add materialprefixes to the global config, for special Material names (bukkit:SAND) -- v1.3.0.506 - add '*' command for the whitelist to allow all commands -- v1.3.0.505 - add per command permissions - defaulting to old behaviour -- v1.3.0.504 - don't drop inventory if not desired -- v1.3.0.503 - fix the UUID interpretation; use player names for creation, not the UUID -.- -- v1.3.0.502 - how about we actually RUN the runnable? -- v1.3.0.501 - force /pa leave on final player death if no specate module present -- v1.3.0.500 - address ticket #869, #884, #792 - - add time.resetDelay (default: -1 --> off) - delay for resetting players (TP & inventory) - - support single SPAWN regions for team matches - - support lore and displayname for keepItems -- v1.3.0.499 - address ticket 792, 879, 881 - - attempt to fix the Food Goal to properly handle player deaths - - require explicit perms for /pa arenaclass (if desired) -- v1.3.0.498 - properly initiate late joining PlayerDeathMatch players -- v1.3.0.497 - check for explicit class perms, even though we have no Sign! -- v1.3.0.496 - minor fixes -- v1.3.0.495 - add Command Tab support; Big Command rewrite!! \ No newline at end of file diff --git a/doc/history/1.3.1.md b/doc/history/1.3.1.md deleted file mode 100644 index c5c6fdf8a..000000000 --- a/doc/history/1.3.1.md +++ /dev/null @@ -1,47 +0,0 @@ -== PVP-Arena v1.3.1 Changelog - -- v1.3.1.49 - fix an NPE on server shutdown -- v1.3.1.48 - update all the things in the doc -- v1.3.1.46 - pull #106 - thanks a TON to @Oruss7 for putting together this load of information! -- v1.3.1.45 - the final update for 1.7.9 - unless critical errors arrive. I need to get ready for 1.9 -- v1.3.1.44 - prevent an NPE in the WarmupJoin module -- v1.3.1.43 - revert the last commit and furthermore clarify and verify correctly. Modules build incoming -- v1.3.1.42 - fix a logic messups in an internal join check -- v1.3.1.41 - duel module finished -- v1.3.1.40 - allow to disable the Duel force ready & start -- v1.3.1.39 - duel module language finish -- v1.3.1.38 - finish off github issue #118 -- v1.3.1.37 - more shurtcut arena list fixes -- v1.3.1.36 - try to fix the round arena status check -- v1.3.1.35 - apply former fix for arena listing -- v1.3.1.34 - override only_shortcuts with allow_ungrouped to allow joining arenas not grouped under shortcuts -- v1.3.1.33 - properly format and save spawn offsets -- v1.3.1.32 - properly format and save spawn offsets -- v1.3.1.31 - properly allow for 5 arguments of /pa spawn -- v1.3.1.30 - fix github issues #115, #118 -- v1.3.1.29 - address github issue #112 -- v1.3.1.28 - how about we don't delete the spawn after offsetting it? -.- -- v1.3.1.26 - github issue #104 - EXPERIMENTAL! -- v1.3.1.25 - this time for real - we need to tell people they CAN decline :) -- v1.3.1.24 - add final language for github issue #97 -- v1.3.1.23 - add config for github issue #86 -- v1.3.1.22 - release build -- v1.3.1.21 - and more language nodes -- v1.3.1.20 - prepare Dual fixes and commit some language/message fixes -- v1.3.1.19 - fix another Exception in the time goal -- v1.3.1.18 - properly output unclaiming vs contesting flags in domination goal - language file consistency fixed -- v1.3.1.17 - fix some language derps and move the delayed class change to where it makes more sense -- v1.3.1.16 - fix github issue #108 - contesting (unclaiming) too late -- v1.3.1.15 - add github issue #100 - player.healforkill - true/false :) -- v1.3.1.14 - use the SNAPSHOT distinction and address github issue #85 -- v1.3.1.13 - hide the not-really stat type NULL (player name) -- v1.3.1.12 - fix github issue #95 by adding a null check -- v1.3.1.11 - clarify language for RespawnRelay and fix a little Exception in the Time goal -- v1.3.1.10 - address github issue #88 - properly keep players as DEAD when being relayed -- v1.3.1.9 - address github issue #87 - add THORNS damage handling -- v1.3.1.8 - properly deal with inventory protection -- v1.3.1.7 - how about we don't spam EVERYthing but spam after collecting everything, and inform people that we have prevented something? -- v1.3.1.6 - fix some mathematical and logical derps -- v1.3.1.5 - really add INVENTORY check - properly define new Infect commands [setprotect|getprotect] -- v1.3.1.4 - allow goals to deny BREAK, PLACE, TNT, TNTBREAK, DROP, INVENTORY, PICKUP, CRAFT - proof of concept! -- v1.3.1.1 - link to new jenkins. Thanks to @graywolf336 \ No newline at end of file diff --git a/doc/history/1.3.2.md b/doc/history/1.3.2.md deleted file mode 100644 index 6d0af568e..000000000 --- a/doc/history/1.3.2.md +++ /dev/null @@ -1,79 +0,0 @@ -== PVP-Arena v1.3.2 Changelog - -- v1.3.2.137 - address github issue #205 -- v1.3.2.136 - add language response for ChestFiller -- v1.3.2.135 - add documentation about ChestFiller changes, add some more config nodes that are now properly loaded with defaults automatically -- v1.3.2.134 - address github issue #201 - properly call PAJoinEvent, this never was implemented correctly. Sorry! -- v1.3.2.133 - prepare ChestFiller addition by adding language and documentation -- v1.3.2.132 - prepare ChestFiller addition by adding config node -- v1.3.2.131 - remove FallingAnvils hooks and documentation - it did not work out :/ -- v1.3.2.130 - stop spamming, please. Aims at fixing github issue #154 -- v1.3.2.129 - address github issue #209 - oups -- v1.3.2.128 - add a module method "parseStartCountDown" to possibly override the remaining seconds to go -- v1.3.2.127 - fix github issue #204 by removing all traces of the nonexisting command "import" -- v1.3.2.126 - address github issue #202 - remove "error" and only write it to debug -- v1.3.2.125 - address github issue #155, prevent double dropping of inventory. Hope this does not break anything :P -- v1.3.2.124 - address github issue #154 - just remove tick 4, it's not that important anyways. And remove the blocklist spam :) -- v1.3.2.122 - furthermore fix the uninstall routine -- v1.3.2.121 - address github issue #131 - I think I found the bug! -- v1.3.2.120 - address github issue #203 by firstly fixing the NPE and adding more info to the uninstalling error (Main server log!) -- v1.3.2.119 - prevent double instantiation of arenas - use with caution! :P -- v1.3.2.118 - [CheckPoints] - address github issue #197 -- v1.3.2.117 - [BetterFight] add config setting to restrict explosions only to one-hit deaths -- v1.3.2.116 - add CheckPoint goal (github issue #184) - have fun testing! -- v1.3.2.115 - add "refillforkill" - restocks the inventory with the class items -- v1.3.2.114 - address github issue #191 - prevent NPE due to NULL item in class items -- v1.3.2.113 - add more debug to investigate fire charge ignition issues -- v1.3.2.112 - continue fix for Scoreboards being double reset in modules -- v1.3.2.111 - prepare fix for Scoreboards being double reset in modules -- v1.3.2.110 - address github issue #185 by fixing WorldEdit documentation and messages -- v1.3.2.109 - address github issue #186 -- v1.3.2.107 - address github issue #178 - prevent enderpearl teleport when not alive and fighting -- v1.3.2.106 - [TeamDeathMatch] fix a double broadcast of the winning team -- v1.3.2.105 - fix the documentation for EventAction config -- v1.3.2.103 - furthermore attempt to fix #175 by adding a teleport lock variable -- v1.3.2.102 - support multiple WATCH and LOUNGE regions - addresses github issue #175 -- v1.3.2.101 - finish github issue #174 -- v1.3.2.100 - address github issue #174 -- v1.3.2.99 - add Beacons settings and documentation -- v1.3.2.97 - add Titles API hooks, documentation will follow -- v1.3.2.96 - add a configuration node to change the schematics folder for WorldEdit - adds github issue #129 -- v1.3.2.95 - add region command documentation - thanks @Oruss7 -- v1.3.2.94 - add Language for special Duel/Vault hooking -- v1.3.2.93 - add config settings and documentation for the FallingAnvils module -- v1.3.2.92 - [forcewin] how about we load the command so it can be used? -- v1.3.2.91 - add /pa [arena] forcewin, shorthand !fw - forces a player / team to win -- v1.3.2.90 - fix some more errors about the new command. Works now :) -- v1.3.2.89 - fix the shorthand and the doc linking -- v1.3.2.88 - add /pa [arena] classchest [class] - shorthand !cc - fixed class chests containing the items -- v1.3.2.87 - address github issue #168, NPE on StructureGrowEvent -- v1.3.2.85 - revert deprecation of ArenaModule.getArena() - failsafe(r) loading of modules and goals - arenas will not appear lost any more! -- v1.3.2.84 - address github issue #161, properly read ambiguous ready block definition -- v1.3.2.83 - address github issue #159 - do not instanciate the tracker if disabled -- v1.3.2.82 - address github issue #158 by adding 'shortcut_shuffle' -- v1.3.2.81 - address github issue #154, maybe even issue #86 - only check necessarily flagged regions and BATTLE regions, with include-check -- v1.3.2.80 - properly fix build #68 -- v1.3.2.79 - add TELEPORT protection to allow teleport prevention (it was silently allowed if only happening IN the region, without command) -- v1.3.2.78 - change WALLS config setting command to "wallseconds", it interfered with the most probable arena name -- v1.3.2.77 - revert the CommandPreProcessEvent and rather fix the underlying problem, the command whitelist being too greedy. Added a config setting to use comand list as wildcards -- v1.3.2.76 - enforce player and teamplayer max values, move CommandPreProcessEvent to priority low to fix MobArena join related exploits -- v1.3.2.75 - properly save an ArenaGoal name to the round map (instead of its instance) -- v1.3.2.74 - fix a NPE in the EndRunnable when using rounds -- v1.3.2.73 - add a new command "regionclear" to manage region clearing exceptions -- v1.3.2.72 - add language and documentation for the WorldEdit addition -- v1.3.2.71 - add WorldEdit config to specify regions to autoload/autosave -- v1.3.2.70 - allow data values in MATERIAL definitions (only works with /pa set [node] hand) -- v1.3.2.69 - properly apply rewards when teamrewards is used -- v1.3.2.68 - remove repo pushing to maybe fix building for now -- v1.3.2.64 - fix issue #143 - thanks to Oruss7! -- v1.3.2.63 - add some message output when class changing fails -- v1.3.2.62 - prepare module class change hooking -- v1.3.2.61 - address github issue #114 - add LibsDisguises support -- v1.3.2.60 - fix CTF being messed up by people continuing to play -- v1.3.2.59 - fix update check -- v1.3.2.58 - /pa help - it still shows the colored standard reply even with sub-arguments -- v1.3.2.57 - address github issue #135 - language addition -- v1.3.2.56 - address github issue #141 - add config calcoffset to tweak block dissolve greediness -- v1.3.2.55 - fix Spectate Spectators being told they cannot teleport when switching view -- v1.3.2.54 - new Module: Spectate - uses the 1.8 SPECTATOR GameMode -- v1.3.2.51 - update to Java 7 \ No newline at end of file diff --git a/doc/history/1.3.3.md b/doc/history/1.3.3.md deleted file mode 100644 index 17572ca81..000000000 --- a/doc/history/1.3.3.md +++ /dev/null @@ -1,112 +0,0 @@ -== PVP-Arena v1.3.3 Changelog - -- v1.3.3.248 - /pa reload ymls | reload main config, language and help ymls -- v1.3.3.247 - do not duplicate offhand items and don't try to set objectives that are not needed (because of disabled scoreboard) -- v1.3.3.246 - address github issue #280, reload global language and help nodes on /pa reload -- v1.3.3.245 - revert player names appearing on scoreboards, maybe properly display 0 team lives left? -- v1.3.3.244 - catch an NPE about scoreboards and dead/offline players and fix a scoreboard crash vulnerability -- v1.3.3.243 - eventually delay scoreboard display to arena start, delay inventory reset to when a player gets put back to their exit spawn, delay fire tick reset -- v1.3.3.242 - properly reset scoreboard when simply leaving by command -- v1.3.3.241 - address github issue #278 - support "hand" placeholder for multiple-item-definitions too -- v1.3.3.240 - address github issue #276 by catching the NPE even deeper -- v1.3.3.239 - fix inventory double drop bug when losing the last life -- v1.3.3.238 - allow for default death messaeges by setting both deathmessage config nodes to false -- v1.3.3.237 - address github issue #271 - do not remove/use player list scoreboard if scoreboard is disabled -- v1.3.3.236 - address github issue #273 - add Elytra to chestplate definition list -- v1.3.3.235 - address github issue #274 - fix player leaving handling in general -- v1.3.3.234 - properly require permission for /pa command -- v1.3.3.233 - address github issue #273 - single item definitions (maybe more) gets lost until restart -- v1.3.3.232 - add github issue #258 - liberation scoreboard separation of jailed players -- v1.3.3.231 - add github issue #198 - particle display of domination claim radius -- v1.3.3.230 - add github issue #237 - items on kill, settable via command and "inventory" handle! -- v1.3.3.229 - address github issue #254 - update Arrow Hack for Spigot > 1.9 -- v1.3.3.228 - address github issue #151 and try to add a custom scoreboard entry to show round progress -- v1.3.3.227 - fix scoreboard removal and fix a bug that caused doubled starting method call -- v1.3.3.226 - allow longer scoreboard entries (48 characters for now) -- v1.3.3.225 - reintroduce custom scoreboard entries -- v1.3.3.224 - address github issue #264 - ArenaClass equipping debug triggers NPE -- v1.3.3.223 - address github issue #267 - critical fix about gamemodes -- v1.3.3.222 - fix grabbing the flag giving you no wool head -- v1.3.3.221 - refresh debug instance for global debug when stopping / changing debug output -- v1.3.3.220 - further ID fixes, and fix a but about GameMode setting and one about players being able to join an arena when it is restoring -- v1.3.3.219 - finish the item ID burial -- v1.3.3.218 - stop supporting item IDs in configs - configs shall be updated! -- v1.3.3.217 - do not nag people to update if updater type DOWNLOAD is selected - addresses github issue #244 -- v1.3.3.216 - address a bug about invisibility being nullified by internal scoreboard -- v1.3.3.215 - address issue #238 by adding refillCustomInventory - defaulting to true -- v1.3.3.214 - address issue #255 - Remove arrows stuck to everyone -- v1.3.3.213 - address issue #256 - Exception about ScoreBoards when shutting down -- v1.3.3.212 - fix issue #252 by catching a NPE -- v1.3.3.211 - revert c67e4a6 - never mess with flying speed or walking speed again plz :P -- v1.3.3.210 - revert 4f75803 - never mess with flying speed or walking speed again plz :P -- v1.3.3.209 - final attempt to get rid of the speed issue - deactivate with -10 -- v1.3.3.208 - address issues with commit 4f75803 -- v1.3.3.207 - address github issues #245 and #248 -- v1.3.3.206 - finish the spawn region fix -- v1.3.3.205 - continue attemmpt to fix region spawning -- v1.3.3.204 - revert the last commit and try to fix region spawning -- v1.3.3.203 - try to fix an issue about respawning players not getting reset properly -- v1.3.3.202 - try to finish off github issue #212 by delaying scoreboard slot selection and player removal -- v1.3.3.201 - allow to disable all gamemode changes; make "takeOutOfGame" actually work -- v1.3.3.200 - prevent the plugin from messing up player restoring in certain reset cases -- v1.3.3.199 - address github issue #238 - allow to keep ALL items on respawn -- v1.3.3.198 - add "teleportonkill" to allow force respawn of killers -- v1.3.3.197 - address github issue #238 - allow to keep ALL items on respawn -- v1.3.3.196 - address github issue #240 - message consistency -- v1.3.3.195 - address github issue #241 - don't use Location, use Vectors for offset -- v1.3.3.194 - fix github issue #232 - Potions disappearing when readying up -- v1.3.3.193 - fix StatisticsManager to actually be persistent. SORRY! -- v1.3.3.192 - add config for github issue #220 -- v1.3.3.191 - fix github issue #188 - I found the right way to deactivate collision -- v1.3.3.190 - address github issue #120 - limiting class changes -- v1.3.3.189 - address github issue #99 - can we finally bury this? ^^ -- v1.3.3.188 - [FFA] allow to punish being killed by other things than a player: punishsuicide -- v1.3.3.187 - allow to set keepOnRespawn to "all" to, yes, keep all items -- v1.3.3.186 - implement ColorTeams and ScoreBoards modules into core - addresses github issue #212 -- v1.3.3.185 - add an announcement verification hack to WarmupJoin -- v1.3.3.184 - revert build #177 (saturation lock), does not work anyways -- v1.3.3.183 - very important module fix - player resetting was broken! -- v1.3.3.182 - reduce command whitelist case sensitivity -- v1.3.3.181 - reduce command case sensitivity -- v1.3.3.180 - allow modules to know whether to soft reset a player -- v1.3.3.179 - fix config node typo -- v1.3.3.178 - allow to quick leave with caps lock -- v1.3.3.177 - add saturation lock, to prevent regains going crazy -- v1.3.3.176 - apply global and specific teleport offset when resetting player -- v1.3.3.175 - fix github issue #230 -- v1.3.3.174 - little thing about #230 and add more debug to see why it might not work yet -- v1.3.3.173 - address github issue #222, again -- v1.3.3.172 - finish github issue #225 -- v1.3.3.171 - add github issue #230 - apply the teleport protection to the lounge, too, to prevent teleport warnings -- v1.3.3.170 - try to fix disabling breaking arena shortcut rotation -- v1.3.3.169 - maybe fix an issue that shortcut rotation doesn't work when the arenas are disabled at start -- v1.3.3.168 - partially revert breaking #222 even more -- v1.3.3.167 - address github issue #227 - reset killer's items to KILLER's class -- v1.3.3.166 - maybe finally tackle github issue #222 -- v1.3.3.165 - properly implement github issue #225 -- v1.3.3.164 - finish up github issue #203 -- v1.3.3.163 - address github issue #224 -- v1.3.3.162 - address all remnants of issue #203 -- v1.3.3.161 - address github issue #224 - double output in the lounge -- v1.3.3.160 - I got an idea, how about we actually implement issue #188 ?! oh and add issue #225 -- v1.3.3.159 - address github issue #222 -- v1.3.3.158 - continue fixing the issue mentioned in build #153 -- v1.3.3.157 - address github issue #222, again -- v1.3.3.156 - change the updating process and block installing/updating when there is no install.yml due to "update.files" (you can allow this setting and disable automatic updates with updatemode "none" or "announce") -- v1.3.3.155 - remove spectral arrows from the potion meta list, those don't seem to have potion effects -- v1.3.3.153 - try to fix the issue of lounge players not being able to interact where they should -- v1.3.3.152 - try to implement github issue #188 -- v1.3.3.151 - add config setting for github issue #188 -- v1.3.3.150 - address github issue #131 - if it's not fixed, I at least added debug -- v1.3.3.149 - address github issue #215 by removing a never launched minigame API and make sure to get the proper shortcut name, if possible -- v1.3.3.148 - finally fix github issue #205 -- v1.3.3.147 - prevent inventory dropping even if custom class is active -- v1.3.3.146 - found the little bug that caused github issue #205 ! -- v1.3.3.145 - partially revert d8d9bf174027aadc6ccd641b6cef7b660f435f25 to address github issue #205 -- v1.3.3.144 - potions are operational. Please update your class definitions (if you did not use class chests) -- v1.3.3.143 - please use the same logic for saving and loading -- v1.3.3.142 - potions should work now. Please redo all your potionish classes (potions, splash potions, lingering, arrows, etc) -- v1.3.3.141 - try to fix armor supply -- v1.3.3.140 - properly fix Potion creation/saving broken by Spigot 1.9 API changes -- v1.3.3.139 - properly fix Inventory handling broken by Spigot 1.9 API changes -- v1.3.3.138 - move to Spigot 1.9.4 \ No newline at end of file diff --git a/doc/history/1.3.4.md b/doc/history/1.3.4.md deleted file mode 100644 index e26bb8668..000000000 --- a/doc/history/1.3.4.md +++ /dev/null @@ -1,52 +0,0 @@ -== PVP-Arena v1.3.4 Changelog - -- v1.3.4.298 - attempt to properly back up NBT data of player's items in case of an unnatural leaving of the arena -- v1.3.4.297 - address github issue #351 - add yet another delay to fix Spigot -- v1.3.4.296 - address github issue #329 - actually change the scoreboard title :O -- v1.3.4.295 - fix the fact that the scoreboard did not update on losing the last life. Thanks to @Oruss7 -- v1.3.4.294 - add team size and total team count when joining -- v1.3.4.293 - address github issue #332 - display first checkpoint message, and display numbers starting from 1 -- v1.3.4.292 - address github issue #329 - use arena prefix instead of name, if still too long, shorten manually -- v1.3.4.291 - added debug to PotionSplashEvent for someone to have evidence to report a bug -- v1.3.4.290 - when setting up a region, check that it has actual resulting volume before saving -- v1.3.4.289 - address github issue #324 - call home asynchronously -- v1.3.4.288 - stop igniting your own TNT - and tell people that it is not okay -- v1.3.4.287 - update EventActions docs to properly reflect the node names -- v1.3.4.286 - update EventActions docs and fix github issue #314 by not stopping arenas twice on reload! -- v1.3.4.285 - allow to update spawn and blocks on the fly -- v1.3.4.284 - fix docs [remove colorteams and scoreboard] and add language and docs for BetterClass "respawnCommand" -- v1.3.4.283 - add EventActions addition (classchange hook) -- v1.3.4.282 - address github issue #305 - check max health before setting health -- v1.3.4.281 - address github issue #302 - prevent NPE for spectators when joining the arena -- v1.3.4.280 - remove debug output of time message nodes -- v1.3.4.279 - add github issue #249 - playSound (???) to add particle effect, DONE -- v1.3.4.278 - add github issue #124 - add timer configs to add/remove/change timer interval messages -- v1.3.4.277 - add github issue #117 - BossBar for Domination -- v1.3.4.276 - do not setup a scoreboard if spectating is cancelled/not possible -- v1.3.4.275 - allow right clicking blocks when LOST attempt 2 -- v1.3.4.274 - allow right clicking blocks when LOST and add Region Protection Tutorial -- v1.3.4.273 - update player equip function to support offhand slots -- v1.3.4.272 - properly protect and not overprotect, affected: MOBS [block lightning], TNT [prevent entity damage], GROW [actually block block growth] -- v1.3.4.271 - remove metrics and update the readme with new region shape tutorial -- v1.3.4.270 - do not add spectator names to the scoreboard -- v1.3.4.269 - update the spectator scoreboard -- v1.3.4.268 - create a scoreboard for spectators -- v1.3.4.267 - address github issue #291 by adding "perms.spectatorinteract" to allow spectators to interact -- v1.3.4.266 - remove debug and address github issue #292 by checking if a player already joined an arena before doing anything -- v1.3.4.265 - how I miss those debug times. IS THE PLAYER FLYING OR NOT!??!! -- v1.3.4.264 - why not try without delay? -- v1.3.4.263 - change fly mode saving and restoring -- v1.3.4.262 - do not restore flying state if specating on death -- v1.3.4.261 - delay flying mode setting by 5 ticks when restoring a player -- v1.3.4.260 - address github issue #290 - catch NPE about Spawn Eggs -- v1.3.4.259 - finish off github issue #280 by adding a proper message about reloading the languages -- v1.3.4.258 - finish the fix for issue #198 by supporting beacon block definitions -- v1.3.4.257 - address github issue #198 - make particle circle function goal independant -- v1.3.4.256 - address github issue #285 - catch NPE by checking for missing round argument -- v1.3.4.255 - address github issue #263 - properly cancel interact event - I assumed that they come uncancelled - wrong -- v1.3.4.254 - who ordered .lck files? Not me! Byebye! [debugging file handler not closed] -- v1.3.4.253 - hotfix about cancelling PlayerItemConsumeEvent - sorry @mibby, fasting is over now! -- v1.3.4.252 - fix issue #263 by cancelling PlayerItemConsumeEvent - since when is this a necessity? The interact event was cancelled :P -- v1.3.4.251 - fix spawn alignment glitches, some of which were fixed by restarting the server, fix double messages around right clicking -- v1.3.4.250 - update some things to the latest API - fix CheckPoints spawn set logic, fix PlayerDeathMatch required kill display -- v1.3.4.249 - update to Spigot 1.11 - address github issue #218 \ No newline at end of file diff --git a/doc/items.md b/doc/items.md index 2de209fac..1c1eab366 100644 --- a/doc/items.md +++ b/doc/items.md @@ -1,7 +1,11 @@ +# Items in configuration files -If you are brave, you can set items for inventories or enhancements directly in -arena config files. It's quite verbose but not really hard. If you aren't at ease with YAML -config files, please use [/pa class](commands/class.md) commands. +With PvPArena, all your arena configuration is stored in a [dedicated config file](configuration.md). For some reasons, +it could be useful to check it or edit it directly. This document will try to explain how you can edit list of items +for inventories or enhancements directly in arena config files. + +This is an **advanced level** tutorial, so if you aren't at ease with YAML config files, please use +[/pa class](commands/class.md) and [/pa set](commands/set.md) commands. JavaDoc : [Bukkit Material ENUMs](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html) diff --git a/doc/languages.md b/doc/languages.md index 7382ccab1..7d691c83b 100644 --- a/doc/languages.md +++ b/doc/languages.md @@ -1,10 +1,18 @@ -These are the language files for PVP Arena, not (all) created or updated by me. +# Languages -Download the file and set lang: en to lang: value inside the config.yml +Here are the language files for PVP Arena, not (all) created or updated by me. -download | lang: value | language | author | date +Download the file and set `lang:` parameter inside the config.yml to +value of the second column. + +download | lang: value | language | author | last update ------------- | ------------- | ------------- | ------------- | ------------- -[link](../lang/lang_en.yml) | 'en' (default) | English | slipcor | 2013/09/11 +[link](../lang/lang_en.yml) | 'en' (default) | English | slipcor/Eredrim | 2020 [link](../lang/lang_es-es.yml) | 'es-es' | Español | Anubis3467 | 2014/09/11 -[link](../lang/lang_fr.yml) | 'fr' | Français | Fizzweapon | 2013/08/22 -[link](../lang/lang_ru.yml) | 'ru' | Russki | llNeosGamer | 2013/04/13 \ No newline at end of file +[link](../lang/lang_fr.yml) | 'fr' | Français | Eredrim | 2020 +[link](../lang/lang_ru.yml) | 'ru' | Russki | llNeosGamer | 2013/04/13 + +
+ +> 💡 **Did you know ?** +> You can propose your own language file by [creating an issue](https://github.com/Eredrim/pvparena/issues). \ No newline at end of file diff --git a/doc/mods/powerups.md b/doc/mods/powerups.md index a3d5463fb..8742aa829 100644 --- a/doc/mods/powerups.md +++ b/doc/mods/powerups.md @@ -13,7 +13,7 @@ Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files f ## Setup -Sorry, but you have to add a freaking block to your arena config under `module.powerups.items`. Eg: +Sorry, but you have to add a freaking block to your arena config under `module.powerups.items`. E.g.: ```yaml items: diff --git a/doc/modules.md b/doc/modules.md index d1dbb4a7b..9f9ea4b31 100644 --- a/doc/modules.md +++ b/doc/modules.md @@ -1,13 +1,16 @@ -## PVP Arena Modules +# PVP Arena Modules -### Installation +## About -Unzip the module files (files tab, "PA Files v\*.\*.\*") into the /pvparena/files folder and install them via -`/pa install [modname]`, **activate per arena via** -`/pa [arenaname] !tm [modname]` +PvPArena modules are ways to enhance your arenas. They could modify a lot of things like configuration, fights, classes +or spectating... +To manage your arena mods (download, install, remove, etc), please check [documentation](commands/modules.md) of +`/pa modules` command. -### PVP Arena Mods +To enable a module for an arena, use [`/pa togglemod`](commands/togglemod.md) command. + +## PVP Arena Mods Hook into many different aspects of the game! @@ -66,4 +69,4 @@ PVP Arena exists since 2011 and Minecraft servers evolution make modules follow- updates will be to make a great check-up of all of them and fix all eventual issues. Anyway, don't hesitate to test legacy modules by yourself, a big part of them work normally or have trivial issues. Obviously -if you encounter one, you can report it 😉 \ No newline at end of file +if you encounter one, you can [report it](https://github.com/Eredrim/pvparena/issues) 😉 \ No newline at end of file diff --git a/doc/permissions.md b/doc/permissions.md index 89619397e..c9eb4f9af 100644 --- a/doc/permissions.md +++ b/doc/permissions.md @@ -1,4 +1,4 @@ -# Permission Nodes +# Permission nodes The following nodes can be used: @@ -10,18 +10,23 @@ pvparena.create| Allows you to create and administrate your arenas (default: op) pvparena.telepass| Allows you to teleport while in an arena (default: op) pvparena.user | Allows you to use the arena (default: true) -If you activate **explicitClassNeeded** you have to add permissions e.g. (proper class name case !!) + +### Specific class permissions + +If you activate `explicitClassNeeded` you have to add permissions e.g. (proper class name case !!) Node | Definition ------------- | ------------- pvparena.class.Ranger | Give Ranger class permission pvparena.class.Tank | Give Tank class permission -If you activate **explicitArenaNeeded** you have to add permissions e.g. (all lowercase!) +### Specific arena permissions + +If you activate `explicitArenaNeeded` you have to add permissions e.g. (all lowercase!) Node | Definition ------------- | ------------- pvparena.join.ctf | Give ctf join permission pvparena.join.spleef | Give spleef join permission -PVP Arena uses the SuperPerms interface \ No newline at end of file +PVP Arena uses the SuperPerms interface, i.e. default bukkit permissions interface. \ No newline at end of file diff --git a/doc/regions.md b/doc/regions.md index cb4ba5625..15a469d0e 100644 --- a/doc/regions.md +++ b/doc/regions.md @@ -1,47 +1,57 @@ # Regions -Regions allow further functions to be added to your game play. +Regions enhance your game play by adding protections, triggers or special configurations. -You can list existing arena regions with `/pa [arena] regions` +You can list existing arena regions with [`/pa [arena] regions`](commands/regions.md) ## Region Creation -All following commands assume you either have edit mode enabled or just one arena in place ! +*All following commands assume you either have edit mode enabled or just one arena in place.* + +Start creating an arena region with [`/pa region`](commands/region.md). -Start creating an arena region with `/pa !r` Now select a region by holding your arena wand (a STICK by default) and left click for position 1 and right click for position 2. Detailed information about the special region shapes, i.e. which points to select, check out the tutorial. -After selecting those points, use `/pa !r [regionname] [regionshape]` to save the region. -Region Shapes +After selecting those points, use [`/pa !r [regionname] [regionshape]`](commands/region.md) to save the region. -The following (self explanatory) region shapes exist: +The following region shapes exist: - CUBOID (default) - SPHERIC - CYLINDRIC -Of course, different shapes cover different areas. Note that a cylinder means a room like a can, so a standing cylinder. +Of course, different shapes cover different areas. Note that a cylinder means an area like a can, so a standing cylinder. -To remove a region, use `/pa region remove [regionname]` +To remove a region, use [`/pa !r [regionname] remove`](commands/region.md) ## Region Types -Set a region's type with `/pa !rt [regionname] [regiontype]` +Set a region's type with [`/pa !rt [regionname] [regiontype]`](commands/regiontype.md) The following Region Types exist: - CUSTOM (default) => does nothing -- WATCH => is the place where spectators should be, BattleFieldGuard will kick spectators not being part inside of one WATCH region -- LOUNGE => is the place where fighters select their class. It currently has no use, but might do in the future +- WATCH => the place where spectators should be, BattleFieldGuard will kick spectators not being part inside of one WATCH region +- LOUNGE => the place where fighters select their class. Required to allow players interactions in the lounge. - BATTLE => the most important type. It adds battlefield reservation (for overlapping arenas, only caring about that actually battle region), region protection, restoring and check if fighters are in the right place. - EXIT => the region where players should be after exiting the arena, no functionality atm - JOIN => the region where players should be when joining, see Configuration page, enforcement is disabled by default - SPAWN => a spawn region where players are randomly placed in when spawning or respawning -- BL_INV => blacklist inventory access -- WL_INV => whitelist inventory access +- BL_INV => block chest access to any team which name is included in the region name, same for classes +- WL_INV => restrict chest access to each team which name is included in the region name, same for classes + +#### Usage of BL_INV and WL_INV + +For these regions types, the name of the region is important. It is read by the plugin to understand access restrictions. + +Example: +* Region name is `RedBlueRanger` and region type is `WL_INV` => allows Red or Blue teams or Ranger class to access chests. +* Region name is `xxblueyy` and region type is `BL_INV`=> disallow chest access to the blue team ## Region Flags -Further customisation of region functionality with `/pa !rf [regionname] [regionflag]` +You can enable special player interactions with players by using regions flags. +Just use the command [`/pa !rf [regionname] [regionflag]`](commands/regionflags.md). + Those are valid Region Flags: - NOCAMP - players that don't move inside this region will be hurt @@ -52,7 +62,10 @@ Those are valid Region Flags: ## Region Protection -The BATTLE Region parses region protection flags (other regions can assigned protections, too, but atm they don't really use them). Set them via `/pa !p [regionname] [protection]` - you can add on, off, yes, no, true, false to specify a setting, or just as just told to toggle the state. Note that there is an "ALL" protection node that triggers/sets all protection nodes +The BATTLE Region parses region protection flags (other regions can assigned protections, too, but atm they don't +really use them). Set them via [`/pa !p [regionname] [protection]`](commands/protection.md) - you can add on, off, yes, +no, true, false to specify a setting, or just as just told to toggle the state. + Valid protections are: - BREAK - prevent player block breaking @@ -69,3 +82,7 @@ Valid protections are: - PICKUP - prevent player item pickup - TELEPORT - prevent player teleportation +Example: `/pa !p main break on` - disallow players to break blocks in "main" region of your arena + +> 🚩 **Tip:** +> There is an "ALL" protection argument that toggle all protections diff --git a/doc/update-checker.md b/doc/update-checker.md new file mode 100644 index 000000000..3c03d5b48 --- /dev/null +++ b/doc/update-checker.md @@ -0,0 +1,15 @@ +# Update Checker + +If you want you can be informed of plugin or modules updates. Each release version was pushed on github since 1.14.0. +The update checker will call the github APIs and announce an update to OPs on login. You can configure it to +automatically download updates. + +```yaml + update: + plugin: announce + modules: announce + # valid values: + # download: download updates and announce when update is installed + # announce: only announce, do not download + # everything else will disable the update check +``` diff --git a/readme.md b/readme.md index 37c5363a8..60a6bdcdf 100644 --- a/readme.md +++ b/readme.md @@ -9,7 +9,7 @@ *** [What is PVP Arena?](#What-is-PVP-Arena?) | [Dependencies](#Dependencies) | [Downloads](#Downloads) | -[Installation](#Installation) | [Documentation](#Documentation) | [Update Checker](#Update-Checker) | +[Installation](#Installation) | [Documentation](#Documentation) | [Support](#Support) | [Telemetry](#Telemetry) | [Credits](#Credits) ***
@@ -72,26 +72,21 @@ Place PVP Arena `.jar` file in the plugin repository of your server and restart. - [Regions](doc/regions.md) - [Goals](doc/goals.md) - [Modules](doc/modules.md) -- [Items](doc/items.md) +- [Items in config files](doc/items.md) - [Languages](doc/languages.md) - [Configuration](doc/configuration.md) +- [Update checker](doc/update-checker.md) +- [FAQ](doc/faq.md) *** -## Update Checker -If you wan't you can be informed of plugin or modules updates. Each release version was pushed on github since 1.14.0. -The update checker will call the github APIs and announce an update to OPs on login. You can configure it to -automatically download updates. - -```yaml - update: - plugin: announce - modules: announce - # valid values: - # download: download updates and announce when update is installed - # announce: only announce, do not download - # everything else will disable the update check -``` +## Support + +You can contact us to ask your questions or just discuss, you can go here: +- [Spigot Forums](https://www.spigotmc.org/threads/pvp-arena.113406/) +- [Discord server](https://discord.gg/KsXG2By) + +To report issues and make suggestion, please use our [Github issues page](https://github.com/Eredrim/pvparena/issues). *** From 8e44f3034b454114310f677a275a3107c77b75ff Mon Sep 17 00:00:00 2001 From: Eredrim Date: Fri, 14 Aug 2020 15:12:15 +0200 Subject: [PATCH 081/115] v1.15 - update bstats dependency --- pom.xml | 3 +-- src/net/slipcor/pvparena/PVPArena.java | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index ad8f4de22..c0b519f93 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ org.bstats bstats-bukkit - 1.5 + 1.7 compile @@ -81,7 +81,6 @@ org.bstats - net.slipcor.pvparena diff --git a/src/net/slipcor/pvparena/PVPArena.java b/src/net/slipcor/pvparena/PVPArena.java index 1ea210cde..54f419bbb 100644 --- a/src/net/slipcor/pvparena/PVPArena.java +++ b/src/net/slipcor/pvparena/PVPArena.java @@ -51,6 +51,7 @@ public class PVPArena extends JavaPlugin { public static PVPArena instance; private static Debug debugger; + private static final int BSTATS_PLUGIN_ID = 5067; private ArenaGoalManager agm; private ArenaModuleManager amm; @@ -372,7 +373,7 @@ public void onEnable() { debugger = new Debug(1); //Enable bStats - Metrics metrics = new Metrics(this); + Metrics metrics = new Metrics(this, BSTATS_PLUGIN_ID); saveDefaultConfig(); if (!getConfig().contains("shortcuts")) { From 0e30ff29418a47378469be5f61bc28276c629071 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Fri, 14 Aug 2020 22:15:54 +0200 Subject: [PATCH 082/115] v1.15 - edit only the flag block in CTF when a flag is caught --- src/net/slipcor/pvparena/goals/GoalFlags.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/goals/GoalFlags.java b/src/net/slipcor/pvparena/goals/GoalFlags.java index d6f106994..ddb16dd35 100644 --- a/src/net/slipcor/pvparena/goals/GoalFlags.java +++ b/src/net/slipcor/pvparena/goals/GoalFlags.java @@ -333,9 +333,8 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block } this.applyEffects(player); - this.takeFlag(new PABlockLocation(block.getLocation())); - this.getFlagMap().put(aTeam, player.getName()); // TODO move to - // "commit" ? + this.takeFlag(new PABlockLocation(vFlag.toLocation(block.getWorld()))); + this.getFlagMap().put(aTeam, player.getName()); return res; } From da985625a9da2b1d5ee44d03517b9df9b29e8c86 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Sat, 15 Aug 2020 16:33:26 +0200 Subject: [PATCH 083/115] v1.15 - release --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c0b519f93..7977927a7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ net.slipcor pvparena - 1.15.0-SNAPSHOT + 1.15.0 PVP Arena https://github.com/Eredrim/pvparena From 5f965cba2fbfadbba244263aac47299869567c73 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 20 Aug 2020 22:28:14 +0200 Subject: [PATCH 084/115] v1.15 - update potion effects documentation reference --- doc/items.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/items.md b/doc/items.md index 1c1eab366..6743dc126 100644 --- a/doc/items.md +++ b/doc/items.md @@ -96,7 +96,7 @@ You can set a potion type like in the following example : potion-type: minecraft:long_invisibilty ``` -You can get potion effects on this page : [Minecraft effect list](https://www.digminecraft.com/lists/effect_list_pc.php) +You can get potion effects on this page : [Potion type list](https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionType.html) Be careful to prefix the effect with "minecraft:". You can give level 2 potions (like heath II) prefixing the effect with **strong_** or long duration potions with the **long_** From 6982803465fccb5d5c878b93838d10d6b9f35426 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Fri, 28 Aug 2020 21:54:42 +0200 Subject: [PATCH 085/115] v1.15.1 - fix FIRE protection for arena regions --- pom.xml | 2 +- readme.md | 2 +- src/net/slipcor/pvparena/listeners/BlockListener.java | 10 +++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 7977927a7..67a5647bb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ net.slipcor pvparena - 1.15.0 + 1.15.1-SNAPSHOT PVP Arena https://github.com/Eredrim/pvparena diff --git a/readme.md b/readme.md index 60a6bdcdf..f656c976b 100644 --- a/readme.md +++ b/readme.md @@ -84,7 +84,7 @@ Place PVP Arena `.jar` file in the plugin repository of your server and restart. You can contact us to ask your questions or just discuss, you can go here: - [Spigot Forums](https://www.spigotmc.org/threads/pvp-arena.113406/) -- [Discord server](https://discord.gg/KsXG2By) +- [Discord server](https://discord.gg/43nZYXZ) To report issues and make suggestion, please use our [Github issues page](https://github.com/Eredrim/pvparena/issues). diff --git a/src/net/slipcor/pvparena/listeners/BlockListener.java b/src/net/slipcor/pvparena/listeners/BlockListener.java index f5fffc778..b5c4f526b 100644 --- a/src/net/slipcor/pvparena/listeners/BlockListener.java +++ b/src/net/slipcor/pvparena/listeners/BlockListener.java @@ -23,6 +23,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; +import org.bukkit.block.data.type.Fire; import org.bukkit.entity.EntityType; import org.bukkit.event.*; import org.bukkit.event.block.*; @@ -462,7 +463,14 @@ public void run() { .getBlockReplacedState().getType()); event.setCancelled(false); arena.getDebugger().i("we do not block TNT, so just return if it is TNT"); - return; + } else if (arena.isFightInProgress() + && !isProtected(event.getBlock().getLocation(), event, RegionProtection.FIRE) + && event.getBlock().getBlockData() instanceof Fire) { + + ArenaModuleManager.onBlockPlace(arena, event.getBlock(), event + .getBlockReplacedState().getType()); + event.setCancelled(false); + arena.getDebugger().i("we do not block FIRE, so just return if it is FIRE"); } return; } From 466fbd24cb2c85c55754ba1bb561c7ea559da8cc Mon Sep 17 00:00:00 2001 From: Eredrim Date: Mon, 14 Sep 2020 23:00:45 +0200 Subject: [PATCH 086/115] v1.15.1 - add config and API for "projectiles" mod --- src/net/slipcor/pvparena/core/Config.java | 5 ++++ .../pvparena/listeners/EntityListener.java | 26 +++++++++++++++++++ .../pvparena/loadables/ArenaModule.java | 13 +++++++++- .../loadables/ArenaModuleManager.java | 6 +++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java index 51e29ea01..844fc4178 100644 --- a/src/net/slipcor/pvparena/core/Config.java +++ b/src/net/slipcor/pvparena/core/Config.java @@ -359,6 +359,11 @@ public enum CFG { MODULES_POWERUPS_DROPSPAWN("modules.powerups.dropspawn", false, "Powerups"), MODULES_POWERUPS_USAGE("modules.powerups.usage", "off", "Powerups"), + MODULES_PROJECTILES_SNOWBALL("modules.projectiles.snowball", true, "Projectiles"), + MODULES_PROJECTILES_EGG("modules.projectiles.egg", true, "Projectiles"), + MODULES_PROJECTILES_FISHHOOK("modules.projectiles.fishHook", false, "Projectiles"), + MODULES_PROJECTILES_ENDERPEARL("modules.projectiles.enderPearl", false, "Projectiles"), + MODULES_SKINS_VANILLA("modules.skins.vanilla", false, "Skins"), MODULES_SPECIALJOIN_SHOWPLAYERS("modules.specialjoin.showplayers", true, "SpecialJoin"), diff --git a/src/net/slipcor/pvparena/listeners/EntityListener.java b/src/net/slipcor/pvparena/listeners/EntityListener.java index bae90cb13..d19a722dd 100644 --- a/src/net/slipcor/pvparena/listeners/EntityListener.java +++ b/src/net/slipcor/pvparena/listeners/EntityListener.java @@ -317,6 +317,32 @@ public void onEntityDamageByEntity(final EntityDamageByEntityEvent event) { } } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void onProjectileHitEvent(final ProjectileHitEvent event) { + ProjectileSource eDamager = event.getEntity().getShooter(); + final Entity eDamagee = event.getHitEntity(); + + + if (eDamager instanceof Player && ArenaPlayer.parsePlayer(((Player) eDamager).getName()).getStatus() == Status.LOST) { + return; + } + + if(eDamager instanceof Player && eDamagee instanceof Player) { + final Player attacker = (Player) eDamager; + final Player defender = (Player) eDamagee; + final ArenaPlayer apDefender = ArenaPlayer.parsePlayer(defender.getName()); + final ArenaPlayer apAttacker = ArenaPlayer.parsePlayer(attacker.getName()); + final Arena arena = apDefender.getArena(); + + if (arena == null || apAttacker.getArena() == null || apDefender.getStatus() == Status.LOST || !arena.isFightInProgress()) { + return; + } + + arena.getDebugger().i("onProjectileHitEvent: fighting player"); + ArenaModuleManager.onProjectileHit(arena, attacker, defender, event); + } + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEntityDamage(final EntityDamageEvent event) { final Entity entity = event.getEntity(); diff --git a/src/net/slipcor/pvparena/loadables/ArenaModule.java b/src/net/slipcor/pvparena/loadables/ArenaModule.java index 965827374..4c4e3842c 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaModule.java +++ b/src/net/slipcor/pvparena/loadables/ArenaModule.java @@ -40,7 +40,7 @@ * @author slipcor */ -public class ArenaModule extends NCBLoadable implements IArenaCommandHandler { +public abstract class ArenaModule extends NCBLoadable implements IArenaCommandHandler { protected static Debug debug = new Debug(32); protected Arena arena; @@ -288,6 +288,17 @@ public void onEntityDamageByEntity(final Player attacker, final Player defender, final EntityDamageByEntityEvent event) { } + /** + * hook into a player throwing projectile + * + * @param attacker the attacking player + * @param defender the attacked player + * @param event the projectileHit event + */ + public void onProjectileHit(final Player attacker, final Player defender, final ProjectileHitEvent event) { + + } + /** * hook into an exploding entity * diff --git a/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java b/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java index 0c380e757..55ab50da5 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java +++ b/src/net/slipcor/pvparena/loadables/ArenaModuleManager.java @@ -173,6 +173,12 @@ public static void onEntityDamageByEntity(final Arena arena, final Player attack } } + public static void onProjectileHit(final Arena arena, final Player attacker, final Player defender, final ProjectileHitEvent event) { + for (final ArenaModule mod : arena.getMods()) { + mod.onProjectileHit(attacker, defender, event); + } + } + public static void onEntityExplode(final Arena arena, final EntityExplodeEvent event) { for (final ArenaModule mod : arena.getMods()) { mod.onEntityExplode(event); From c3a455adcaac213c695d7d8259a75926f8bd61d6 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 17 Sep 2020 21:26:15 +0200 Subject: [PATCH 087/115] v1.15.1 - refresh some modules docs --- doc/mods/blockdissolve.md | 36 ++++++++++----------------------- doc/mods/blockrestore.md | 33 ++++++++++++++---------------- doc/mods/worldedit.md | 42 ++++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 63 deletions(-) diff --git a/doc/mods/blockdissolve.md b/doc/mods/blockdissolve.md index 62b3ccd39..9dc6b608c 100644 --- a/doc/mods/blockdissolve.md +++ b/doc/mods/blockdissolve.md @@ -1,34 +1,20 @@ # BlockDissolve -## Description +## About -This mod adds another layer of tension. Blocks under the player will dissolve, great addition to spleef arenas! - -## Installation - -Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via - -- `/pa install [modname]`, activate per arena via -- `/pa [arenaname] !tm [modname]` - -## Setup - -\- +Blocks under the player will dissolve just few milliseconds after they walk on it. +Use it with [PlayerLives](../goals/playerlives.md) goal to create TNT Run arenas or +spice up your spleef games ! ## Config settings -- modules.blockdissolve.materials \- the material to dissolve data value / color is ignored -- modules.blockdissolve.startseconds \- the seconds to count down before the match starts +- modules.blockdissolve.materials \- the material to dissolve (default: SNOW and each kind of WOOL) +- modules.blockdissolve.startseconds \- the seconds to count down before the match starts (default: 10) - modules.blockdissolve.ticks \- the ticks after what time the block under the player should dissolve (20 ticks = 1 second) + (default: 40). -## Commands - -\- - -## Warnings - -\- - -## Dependencies +
-\- +> **🚩 Tips:** +>- BlockDissolve is compatible with [BlockRestore](./blockrestore.md), so you can use it to regen the floor after each game. +>- If you want to create a TNT Run arena, set ticks parameter to **8** diff --git a/doc/mods/blockrestore.md b/doc/mods/blockrestore.md index 12527e797..78a169677 100644 --- a/doc/mods/blockrestore.md +++ b/doc/mods/blockrestore.md @@ -1,23 +1,12 @@ # BlockRestore -## Description +## About -This mod activates BATTLE region restoring, after the match. - -## Installation - -Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via - -- `/pa install [modname]`, activate per arena via -- `/pa [arenaname] !tm [modname]` - -## Setup - -\- +This mod activates BATTLE [region](../regions.md) restoring after the match. ## Config settings -- hard \- should the mod restore EVERY block, regardless of a known chaged state? (default: false) +- hard \- the mod will restore EVERY block of your battle region, regardless of a known changed state (default: false) - offset \- the time in TICKS (1/20 second) that the scheduler waits for the next block to be replaced (default: 1) - restoreblocks \- restore blocks (default: true) - restorechests \- restore chest content (default: false) @@ -29,10 +18,18 @@ Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files f - `/pa [arena] !br clearinv` \- clear saved chest locations - `/pa [arena] !br offset X` \- set the restore offset in TICKS! -## Warnings +
+ +> **🚩 Tips:** +> - If you add new chests to your map, don't forget to register them with `/pa [arena] !br clearinv`. +> - BlockRestore is designed for simple block destruction and small areas. For other usages, please prefer +> [WorldEdit](./worldedit.md) mod. + +
+ +> ⚙ **Technical precision:** +> Chest restoring lags badly for the first time, because it searches the BATTLE region(s) for chests and saves location +> of each of them. -Chest restoring lags badly for the first time, because it searches the BATTLE region(s) for chests, saves the locations and from then on it's simple. If you add more chests or remove some, you will want to run the clearinv command so chests are not forgotten or blocks are treated as chests -## Dependencies -\- diff --git a/doc/mods/worldedit.md b/doc/mods/worldedit.md index f9fae1e58..71af2dd23 100644 --- a/doc/mods/worldedit.md +++ b/doc/mods/worldedit.md @@ -1,15 +1,10 @@ # WorldEdit -## Description +## About -This module adds WorldEdit hooking for BATTLE region backup, restoring, even automatically +This module adds WorldEdit hooking for BATTLE [region](../regions.md) backup, restoring, even automatically. -## Installation - -Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via - -- `/pa install [modname]`, activate per arena via -- `/pa [arenaname] !tm [modname]` +You can also use this module to design your arena [regions](../regions.md) with a WorldEdit selection (cuboid shape only). ## Setup @@ -17,25 +12,32 @@ This module needs a full server restart to hook into WorldEdit properly, for the ## Config settings -- autoload \- automatically load the arena's BATTLE regions after fight -- autosave \- automatically save the arena's BATTLE regions before fight -- regions \- specify individual regions rather than all BATTLE regions +- autoload - automatically load the arena's BATTLE regions after fight (default: false) +- autosave - automatically save the arena's BATTLE regions before fight (default: false) +- regions - specify individual regions rather than all BATTLE regions (default: empty) +- schematicpath - the path where worldedit schematic files will be stored (default: root path) +- replaceair - if true, air blocks will be pasted on restore (default: true) ## Commands - -- `/pa [arena] regload [regionname] {filename}` \- load the region -- `/pa [arena] regsave [regionname] {filename}` \- save the region +- `/pa [arena] regload [regionname]` \- load the region +- `/pa [arena] regsave [regionname]` \- save the region - `/pa [arena] regcreate [regionname]` \- create a region based on an active WorldEdit selection - `/pa [arena] !we autoload` \- toggle general automatic loading - `/pa [arena] !we autosave` \- toggle general automatic saving -- `/pa [arena] !we create [regionname]` \- create a region based on an active WorldEdit selection -(using this command creates a list of arena regions that will be saved/loaded) -## Warnings -\- +## Use case + +You just want to restore your arena after the match ? Just follow these instructions: +- Check the `schematicpath` setting to correspond to your directory tree +- Save your BATTLE region with command `/pa [arena] regsave [regionname]` +- Add the previously saved region name to `regions` setting (directly in your config file or via +[`/pa set`](../commands/set.md) command). +- Enable autoload with `/pa [arena] !we autoload` -## Dependencies +
-\- +> ⚙ **Technical precision:** +> Worldedit pasting may freeze your server due to its working way. +> So be sure to regen only destroyable/buildable areas to reduce reloading time. From 1e7e61f79194f704acc5dd86f8da1052f13e35b6 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Thu, 17 Sep 2020 22:33:59 +0200 Subject: [PATCH 088/115] v1.15.1 - correctly handle edit mode for command completion and allow leaving of edit mode with /pa leave --- src/net/slipcor/pvparena/commands/PAG_Leave.java | 7 +++++-- src/net/slipcor/pvparena/managers/TabManager.java | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/commands/PAG_Leave.java b/src/net/slipcor/pvparena/commands/PAG_Leave.java index 1cef43aa1..501eb4ff7 100644 --- a/src/net/slipcor/pvparena/commands/PAG_Leave.java +++ b/src/net/slipcor/pvparena/commands/PAG_Leave.java @@ -54,8 +54,11 @@ public void commit(final Arena arena, final CommandSender sender, final String[] } if (!arena.hasPlayer(aPlayer.get())) { - - arena.msg(sender, Language.parse(arena, MSG.ERROR_NOT_IN_ARENA)); + if(PAA_Edit.activeEdits.containsKey(sender.getName())) { + new PAA_Edit().commit(arena, sender, args); + } else { + arena.msg(sender, Language.parse(arena, MSG.ERROR_NOT_IN_ARENA)); + } return; } arena.callLeaveEvent(aPlayer.get()); diff --git a/src/net/slipcor/pvparena/managers/TabManager.java b/src/net/slipcor/pvparena/managers/TabManager.java index b2d7dd7be..3bab4489a 100644 --- a/src/net/slipcor/pvparena/managers/TabManager.java +++ b/src/net/slipcor/pvparena/managers/TabManager.java @@ -7,6 +7,7 @@ import net.slipcor.pvparena.commands.AbstractArenaCommand; import net.slipcor.pvparena.commands.AbstractGlobalCommand; import net.slipcor.pvparena.commands.CommandTree; +import net.slipcor.pvparena.commands.PAA_Edit; import net.slipcor.pvparena.core.StringParser; import net.slipcor.pvparena.loadables.ArenaRegion; import org.bukkit.Bukkit; @@ -31,7 +32,11 @@ public static List getMatches(final CommandSender sender, final List Date: Fri, 2 Oct 2020 22:27:44 +0200 Subject: [PATCH 089/115] v1.15.1 - Fix TNT autoignite --- .../pvparena/listeners/BlockListener.java | 97 +++++++------------ 1 file changed, 34 insertions(+), 63 deletions(-) diff --git a/src/net/slipcor/pvparena/listeners/BlockListener.java b/src/net/slipcor/pvparena/listeners/BlockListener.java index b5c4f526b..45153c49b 100644 --- a/src/net/slipcor/pvparena/listeners/BlockListener.java +++ b/src/net/slipcor/pvparena/listeners/BlockListener.java @@ -12,6 +12,7 @@ import net.slipcor.pvparena.core.Debug; import net.slipcor.pvparena.core.Language; import net.slipcor.pvparena.core.Language.MSG; +import net.slipcor.pvparena.core.Utils; import net.slipcor.pvparena.loadables.ArenaGoalManager; import net.slipcor.pvparena.loadables.ArenaModuleManager; import net.slipcor.pvparena.loadables.ArenaRegion.RegionProtection; @@ -21,10 +22,10 @@ import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; -import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.data.type.Fire; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; import org.bukkit.event.*; import org.bukkit.event.block.*; import org.bukkit.event.entity.ExplosionPrimeEvent; @@ -32,11 +33,12 @@ import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.world.StructureGrowEvent; -import org.bukkit.inventory.ItemStack; import java.util.ArrayList; import java.util.List; +import static java.util.Arrays.asList; + /** *
  * Block Listener class
@@ -396,79 +398,54 @@ public void onBlockPistonExtend(final BlockPistonExtendEvent event) {
 
     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
     public void onBlockPlace(final BlockPlaceEvent event) {
-        DEBUG.i("BlockPlace", event.getPlayer());
-        if (willBeSkipped(event, event.getBlock().getLocation(),
-                RegionProtection.PLACE)) {
+        final Player player = event.getPlayer();
+        final Block block = event.getBlock();
+
+        DEBUG.i("BlockPlace", player);
+
+        if (willBeSkipped(event, block.getLocation(), RegionProtection.PLACE)) {
             return;
         }
 
-        if (ArenaPlayer.parsePlayer(event.getPlayer().getName()).getStatus() == Status.LOST
-                || ArenaPlayer.parsePlayer(event.getPlayer().getName()).getStatus() == Status.WATCH
-                || ArenaPlayer.parsePlayer(event.getPlayer().getName()).getStatus() == Status.LOUNGE
-                || ArenaPlayer.parsePlayer(event.getPlayer().getName()).getStatus() == Status.READY) {
+        final ArenaPlayer arenaPlayer = ArenaPlayer.parsePlayer(player.getName());
+        if (asList(Status.LOST, Status.WATCH, Status.LOUNGE, Status.READY).contains(arenaPlayer.getStatus())) {
             event.setCancelled(true);
             return;
         }
 
-        final Arena arena = ArenaManager.getArenaByRegionLocation(new PABlockLocation(event
-                .getBlock().getLocation()));
-
-        if (event.getBlock().getType() == Material.TNT && arena.getArenaConfig().getBoolean(CFG.PLAYER_AUTOIGNITE)) {
-            event.setCancelled(true);
-            arena.getDebugger().i("autoignite false");
-
-            class RunLater implements Runnable {
+        final Arena arena = ArenaManager.getArenaByRegionLocation(new PABlockLocation(block.getLocation()));
+        final Block placedBlock = event.getBlockPlaced();
 
-                @Override
-                public void run() {
-                    event.getPlayer().getInventory().remove(new ItemStack(Material.TNT, 1));
-                }
-
-            }
-
-            Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RunLater(), 1L);
-
-            event.getBlock().getLocation().getWorld().spawnEntity(
-                    event.getBlock().getRelative(BlockFace.UP).getLocation(), EntityType.PRIMED_TNT);
+        if (block.getType() == Material.TNT && arena.getArenaConfig().getBoolean(CFG.PLAYER_AUTOIGNITE)) {
+            arena.getDebugger().i("autoignite tnt");
+            placedBlock.setType(Material.AIR);
+            block.getWorld().spawnEntity(Utils.getCenteredLocation(block.getLocation()), EntityType.PRIMED_TNT);
             return;
         }
 
 
         List list = arena.getArenaConfig().getStringList(
                 CFG.LISTS_WHITELIST.getNode() + ".place",
-                new ArrayList());
+                new ArrayList<>());
 
-        if (!list.isEmpty()
-                && !list.contains(String.valueOf(event.getBlockPlaced()
-                .getType().name()))
-                && !list.contains(String.valueOf(event.getBlockPlaced()
-                .getType().name()))) {
-            arena.msg(
-                    event.getPlayer(),
-                    Language.parse(arena, MSG.ERROR_WHITELIST_DISALLOWED,
-                            Language.parse(arena, MSG.GENERAL_PLACE)));
+        if (!list.isEmpty() && !list.contains(placedBlock.getType().name())) {
+            arena.msg(player, Language.parse(arena, MSG.ERROR_WHITELIST_DISALLOWED, Language.parse(arena, MSG.GENERAL_PLACE)));
             event.setCancelled(true);
             arena.getDebugger().i("not on whitelist. DENY!");
             return;
         }
 
-        if (isProtected(event.getBlock().getLocation(), event,
-                RegionProtection.PLACE)) {
-            if (arena.isFightInProgress()
-                    && !isProtected(event.getBlock().getLocation(), event,
-                    RegionProtection.TNT)
-                    && event.getBlock().getType() == Material.TNT) {
-
-                ArenaModuleManager.onBlockPlace(arena, event.getBlock(), event
-                        .getBlockReplacedState().getType());
+        if (isProtected(block.getLocation(), event, RegionProtection.PLACE)) {
+            if (arena.isFightInProgress() && !isProtected(block.getLocation(), event, RegionProtection.TNT)
+                    && block.getType() == Material.TNT) {
+
+                ArenaModuleManager.onBlockPlace(arena, block, event.getBlockReplacedState().getType());
                 event.setCancelled(false);
                 arena.getDebugger().i("we do not block TNT, so just return if it is TNT");
-            } else if (arena.isFightInProgress()
-                    && !isProtected(event.getBlock().getLocation(), event, RegionProtection.FIRE)
-                    && event.getBlock().getBlockData() instanceof Fire) {
+            } else if (arena.isFightInProgress() && !isProtected(block.getLocation(), event, RegionProtection.FIRE)
+                    && block.getBlockData() instanceof Fire) {
 
-                ArenaModuleManager.onBlockPlace(arena, event.getBlock(), event
-                        .getBlockReplacedState().getType());
+                ArenaModuleManager.onBlockPlace(arena, block, event.getBlockReplacedState().getType());
                 event.setCancelled(false);
                 arena.getDebugger().i("we do not block FIRE, so just return if it is FIRE");
             }
@@ -477,15 +454,10 @@ public void run() {
 
         list = arena.getArenaConfig().getStringList(
                 CFG.LISTS_BLACKLIST.getNode() + ".place",
-                new ArrayList());
+                new ArrayList<>());
 
-        if (list.contains(String.valueOf(event.getBlockPlaced().getType().name()))
-                || list.contains(String.valueOf(event.getBlockPlaced()
-                .getType().name()))) {
-            arena.msg(
-                    event.getPlayer(),
-                    Language.parse(arena, MSG.ERROR_BLACKLIST_DISALLOWED,
-                            Language.parse(arena, MSG.GENERAL_PLACE)));
+        if (list.contains(placedBlock.getType().name())) {
+            arena.msg(player, Language.parse(arena, MSG.ERROR_BLACKLIST_DISALLOWED, Language.parse(arena, MSG.GENERAL_PLACE)));
             event.setCancelled(true);
             arena.getDebugger().i("on blacklist. DENY!");
             return;
@@ -494,13 +466,12 @@ public void run() {
         PACheck res = ArenaGoalManager.checkPlace(arena, event);
 
         if (res.hasError()) {
-            DEBUG.i("onBlockPlace cancelled by goal: " + res.getModName(), event.getPlayer());
+            DEBUG.i("onBlockPlace cancelled by goal: " + res.getModName(), player);
             return;
         }
         arena.getDebugger().i("BlockPlace not cancelled!");
 
-        ArenaModuleManager.onBlockPlace(arena, event.getBlock(), event
-                .getBlockReplacedState().getType());
+        ArenaModuleManager.onBlockPlace(arena, block, event.getBlockReplacedState().getType());
     }
 
     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)

From 5f945dc21d5d63ae0c175f746e36765db6f621f0 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Fri, 2 Oct 2020 22:36:57 +0200
Subject: [PATCH 090/115] v1.15.1 - Add regen question to FAQ

---
 doc/faq.md | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/doc/faq.md b/doc/faq.md
index 903143c1b..7ca448298 100644
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -44,6 +44,25 @@ an arena, use the command `sudo @p pa leave`.
 
 
+## How to regen my battlefield after a game? + +Currently, there are two ways to regen battlefield after a match. You can use either +[BlockRestore](mods/blockrestore.md) module or [WorldEdit](mods/worldedit.md) module. + +Here is a quick list of precisions to support your choice: +* BlockRestore: + * Reset only blocks broken by players + * Asynchronous + * Perfect for arena where few blocks are destroyed (like spleef) +* WorldEdit: + * Needs WorldEdit plugin (obviously) + * Regenerates everything + * Can regen large areas but is synchronous + +Check dedicated documentation pages to get more information. + +
+ ## Still have questions? Don't hesitate to [get in touch](../readme.md#support) with us 😉 \ No newline at end of file From fdf73677020029e66c651cbc62c3068fdfc65591 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 6 Oct 2020 22:29:18 +0200 Subject: [PATCH 091/115] v1.15.1 - remove deprecated module API --- src/net/slipcor/pvparena/loadables/ArenaModule.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/net/slipcor/pvparena/loadables/ArenaModule.java b/src/net/slipcor/pvparena/loadables/ArenaModule.java index 4c4e3842c..b6999d904 100644 --- a/src/net/slipcor/pvparena/loadables/ArenaModule.java +++ b/src/net/slipcor/pvparena/loadables/ArenaModule.java @@ -425,18 +425,6 @@ public Integer parseStartCountDown(Integer seconds, String message, Boolean glob public void reset(final boolean force) { } - /** - * hook into an arena player being reset - * - * @deprecated use {@link #resetPlayer(Player, boolean, boolean)} - * - * @param player the player being reset - * @param force if the arena is forcefully reset - */ - @Deprecated - public void resetPlayer(final Player player, final boolean force) { - } - /** * hook into an arena player being reset * From a7889dc08076f1da79219406da2bac06bca0cc11 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 6 Oct 2020 22:44:30 +0200 Subject: [PATCH 092/115] v1.15.1 - fix region removing --- src/net/slipcor/pvparena/commands/PAA_Region.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/net/slipcor/pvparena/commands/PAA_Region.java b/src/net/slipcor/pvparena/commands/PAA_Region.java index 3903cfc4b..376f3ebcf 100644 --- a/src/net/slipcor/pvparena/commands/PAA_Region.java +++ b/src/net/slipcor/pvparena/commands/PAA_Region.java @@ -90,11 +90,11 @@ public void commit(final Arena arena, final CommandSender sender, final String[] return; } if (args.length == 2 && args[1].equalsIgnoreCase("remove")) { - // usage: /pa {arenaname} region remove [regionname] | remove a region - final ArenaRegion region = arena.getRegion(args[1]); + // usage: /pa {arenaname} region [regionname] remove | remove a region + final ArenaRegion region = arena.getRegion(args[0]); if (region == null) { - arena.msg(sender, Language.parse(arena, MSG.ERROR_REGION_NOTFOUND, args[1])); + arena.msg(sender, Language.parse(arena, MSG.ERROR_REGION_NOTFOUND, args[0])); return; } arena.getArenaConfig().setManually("arenaregion." + region.getRegionName(), null); From 18cdc9e8fed82fbd1674f4deebddc3eb26c0bf37 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 13 Oct 2020 21:46:07 +0200 Subject: [PATCH 093/115] v1.15.1 - refactor ArenaClass and fix armor checks --- .../slipcor/pvparena/arena/ArenaClass.java | 134 ++++++------------ 1 file changed, 42 insertions(+), 92 deletions(-) diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java index 89e6ff9fd..4299b541b 100644 --- a/src/net/slipcor/pvparena/arena/ArenaClass.java +++ b/src/net/slipcor/pvparena/arena/ArenaClass.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.*; +import static java.util.Arrays.asList; import static net.slipcor.pvparena.core.ItemStackUtils.getItemStacksFromConfig; /** @@ -40,66 +41,8 @@ public final class ArenaClass { private static final Map globals = new HashMap<>(); - // private statics: item definitions - private static final List ARMORS_TYPE = new LinkedList<>(); - private static final List HELMETS_TYPE = new LinkedList<>(); - private static final List CHESTPLATES_TYPE = new LinkedList<>(); - private static final List LEGGINGS_TYPE = new LinkedList<>(); - private static final List BOOTS_TYPE = new LinkedList<>(); - - // static filling of the items array - static { - HELMETS_TYPE.add(Material.LEATHER_HELMET); - HELMETS_TYPE.add(Material.GOLDEN_HELMET); - HELMETS_TYPE.add(Material.CHAINMAIL_HELMET); - HELMETS_TYPE.add(Material.IRON_HELMET); - HELMETS_TYPE.add(Material.DIAMOND_HELMET); - - HELMETS_TYPE.add(Material.BLACK_WOOL); - HELMETS_TYPE.add(Material.BLUE_WOOL); - HELMETS_TYPE.add(Material.BROWN_WOOL); - HELMETS_TYPE.add(Material.CYAN_WOOL); - HELMETS_TYPE.add(Material.GRAY_WOOL); - HELMETS_TYPE.add(Material.GREEN_WOOL); - HELMETS_TYPE.add(Material.LIGHT_BLUE_WOOL); - HELMETS_TYPE.add(Material.LIGHT_GRAY_WOOL); - HELMETS_TYPE.add(Material.LIME_WOOL); - HELMETS_TYPE.add(Material.MAGENTA_WOOL); - HELMETS_TYPE.add(Material.ORANGE_WOOL); - HELMETS_TYPE.add(Material.PINK_WOOL); - HELMETS_TYPE.add(Material.PURPLE_WOOL); - HELMETS_TYPE.add(Material.RED_WOOL); - HELMETS_TYPE.add(Material.WHITE_WOOL); - HELMETS_TYPE.add(Material.YELLOW_WOOL); - - HELMETS_TYPE.add(Material.PUMPKIN); - HELMETS_TYPE.add(Material.JACK_O_LANTERN); - HELMETS_TYPE.add(Material.PLAYER_HEAD); - - CHESTPLATES_TYPE.add(Material.LEATHER_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.GOLDEN_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.CHAINMAIL_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.IRON_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.DIAMOND_CHESTPLATE); - CHESTPLATES_TYPE.add(Material.ELYTRA); - - LEGGINGS_TYPE.add(Material.LEATHER_LEGGINGS); - LEGGINGS_TYPE.add(Material.GOLDEN_LEGGINGS); - LEGGINGS_TYPE.add(Material.CHAINMAIL_LEGGINGS); - LEGGINGS_TYPE.add(Material.IRON_LEGGINGS); - LEGGINGS_TYPE.add(Material.DIAMOND_LEGGINGS); - - BOOTS_TYPE.add(Material.LEATHER_BOOTS); - BOOTS_TYPE.add(Material.GOLDEN_BOOTS); - BOOTS_TYPE.add(Material.CHAINMAIL_BOOTS); - BOOTS_TYPE.add(Material.IRON_BOOTS); - BOOTS_TYPE.add(Material.DIAMOND_BOOTS); - - ARMORS_TYPE.addAll(HELMETS_TYPE); - ARMORS_TYPE.addAll(CHESTPLATES_TYPE); - ARMORS_TYPE.addAll(LEGGINGS_TYPE); - ARMORS_TYPE.addAll(BOOTS_TYPE); - } + private static final List OTHER_HELMET_LIST = asList(Material.PUMPKIN, Material.JACK_O_LANTERN, Material.PLAYER_HEAD); + public static void addGlobalClasses() { globals.clear(); @@ -164,7 +107,7 @@ public static void addGlobalClasses(final Arena arena) { public static void equip(final Player player, final ItemStack[] items) { int i = 0; for (final ItemStack item : items) { - if (ARMORS_TYPE.contains(item.getType())) { + if (isArmorItem(item.getType())) { equipArmor(item, player.getInventory()); } else { if (i == items.length - 1) { @@ -205,18 +148,14 @@ public static void equip(final Player player, final ItemStack[][] itemArray) { } for (final ItemStack item : itemArray[0]) { - if (item.hasItemMeta() && item.getItemMeta().hasDisplayName() && "SPAWN".equals(item.getItemMeta().getDisplayName())) { + if (item.getType().name().endsWith("_SPAWN_EGG")) { final String eggType = item.getType().name().replace("_SPAWN_EGG", ""); try { - Bukkit.getScheduler().runTaskLater(PVPArena.instance, new Runnable(){ - @Override - public void run() { + Bukkit.getScheduler().runTaskLater(PVPArena.instance, () -> ArenaPlayer.parsePlayer(player.getName()).getArena().addEntity( - player, player.getWorld().spawnEntity(player.getLocation(), EntityType.valueOf(eggType))); - } - }, 20L); - } catch(final IllegalPluginAccessException e) { + player, player.getWorld().spawnEntity(player.getLocation(), EntityType.valueOf(eggType))), 20L); + } catch(final IllegalPluginAccessException ignored) { } } else { @@ -227,45 +166,45 @@ public void run() { public void equip(final Player player) { debug.i("Equipping player " + player.getName() + " with items!", player); - for (ItemStack item : armors) { + for (ItemStack item : this.armors) { if (item != null) { equipArmor(item, player.getInventory()); } } - for (final ItemStack item : items) { + for (final ItemStack item : this.items) { if (item == null) { continue; } - if (ARMORS_TYPE.contains(item.getType())) { + if (isArmorItem(item.getType())) { equipArmor(item, player.getInventory()); } else { player.getInventory().addItem(item); } } - player.getInventory().setItemInOffHand(offHand); + player.getInventory().setItemInOffHand(this.offHand); } private static void equipArmor(final ItemStack stack, final PlayerInventory inv) { final Material type = stack.getType(); - if (HELMETS_TYPE.contains(type)) { + if (isHelmetItem(type)) { if (inv.getHelmet() != null && inv.getHelmet().getType() != Material.AIR) { inv.addItem(stack); } else { inv.setHelmet(stack); } - } else if (CHESTPLATES_TYPE.contains(type)) { + } else if (isChestplateItem(type)) { if (inv.getChestplate() != null && inv.getChestplate().getType() != Material.AIR) { inv.addItem(stack); } else { inv.setChestplate(stack); } - } else if (LEGGINGS_TYPE.contains(type)) { + } else if (isLeggingsItem(type)) { if (inv.getLeggings() != null && inv.getLeggings().getType() != Material.AIR) { inv.addItem(stack); } else { inv.setLeggings(stack); } - } else if (BOOTS_TYPE.contains(type)) { + } else if (isBootsItem(type)) { if (inv.getBoots() != null && inv.getBoots().getType() != Material.AIR) { inv.addItem(stack); } else { @@ -274,32 +213,43 @@ private static void equipArmor(final ItemStack stack, final PlayerInventory inv) } } - /** - * Backwards compatible offhand-less implementation of the constructor - * - * @deprecated use {@link #ArenaClass(String, ItemStack[], ItemStack, ItemStack[])} } instead. - */ - @Deprecated - public ArenaClass(final String className, final ItemStack[] classItems, final ItemStack[] armors) { - this(className, classItems, null, armors); - } - public ArenaClass(final String className, final ItemStack[] classItems, final ItemStack offHand, final ItemStack[] armors) { - name = className; + this.name = className; this.offHand = offHand; - items = classItems.clone(); + this.items = classItems.clone(); this.armors = armors.clone(); } public String getName() { - return name; + return this.name; } public ItemStack[] getArmors() { - return armors.clone(); + return this.armors.clone(); } public ItemStack[] getItems() { - return items.clone(); + return this.items.clone(); + } + + private static boolean isHelmetItem(Material material) { + return material.name().endsWith("_HELMET") || material.name().endsWith("_WOOL") || + OTHER_HELMET_LIST.contains(material); + } + + private static boolean isChestplateItem(Material material) { + return material.name().endsWith("_CHESTPLATE"); + } + + private static boolean isLeggingsItem(Material material) { + return material.name().endsWith("_LEGGINGS"); + } + + private static boolean isBootsItem(Material material) { + return material.name().endsWith("_BOOTS"); + } + + private static boolean isArmorItem(Material material) { + return isBootsItem(material) || isLeggingsItem(material) || isChestplateItem(material) || isHelmetItem(material); } } \ No newline at end of file From 57c8f11af5c736afc3c22c552a21775d805f015a Mon Sep 17 00:00:00 2001 From: Eredrim Date: Tue, 24 Nov 2020 23:01:44 +0100 Subject: [PATCH 094/115] [doc] improve modules documentation --- doc/mods/tempperms.md | 63 ++++++++++++++++++++++--------------------- doc/modules.md | 34 ++++++++++++++++++++--- 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/doc/mods/tempperms.md b/doc/mods/tempperms.md index b5f0edfde..12f86edb1 100644 --- a/doc/mods/tempperms.md +++ b/doc/mods/tempperms.md @@ -1,50 +1,53 @@ # TempPerms -## Description +## About -This module activates temporary permissins during a match. +This module activates temporary permission system during a match. You can set specific permissions to any player in the +arena or more specifically to a team or a class. -## Installation - -Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via +## Config settings -- `/pa install [modname]`, activate per arena via -- `/pa [arenaname] !tm [modname]` +There is no dedicated config setting for TempPerms, every permission you set are written in the perms part of your arena +configuration file. ## Setup -Either administrate via command OR create a config block inside the arena config, like this: +Either administrate via commands (recommended) OR complete the `perms` config block inside the arena config, like this: +```yaml perms: -- default: - - everyone.has.this - - ^everyone.doesnt.have.this -- blue: - - only.blue.has.this - - blue.does.not.have.this -- tank: - - tank.has.this - - ^tank.does.not.have.this - -Note that "-node" and "^node" are the same, just to clarify that you can use both :) - -## Config settings - -\- + - default: + - everyone.has.this + - -everyone.doesnt.have.this + - blue: + - only.blue.has.this + - -blue.does.not.have.this + - tank: + - tank.has.this + - -tank.does.not.have.this +``` + +
+ +> ⚙ **Technical precision:** +> * For negative permissions, you can use either `-node` or `^node` syntax, it's the same thing. However when the config +> is saved, every negative permissions are rewritten with `-node` syntax. +> * `default` block contains permissions applied to every player ## Commands - `/pa [arena] !tps` \- list perms -- `/pa [arena] !tps add [perm]` \- add permission +- `/pa [arena] !tps add [perm]` \- add permission (normal or negative) - `/pa [arena] !tps rem [perm]` \- remove permission -- `/pa [arena] !tps [name]` \- list perms for class/team -- `/pa [arena] !tps [name] add [perm]` \- add permission for class/team -- `/pa [arena] !tps [name] rem [perm]` \- remove permission from class/team +- `/pa [arena] !tps [name]` \- list perms for a class/team +- `/pa [arena] !tps [name] add [perm]` \- add permission for a class/team +- `/pa [arena] !tps [name] rem [perm]` \- remove permission from a class/team -## Warnings +## Troubleshooting -Your permissions plugin needs to properly handle PermissionAttachments. If you experience this not working, double check if you GAVE superior permissions or SUB permissions that you didnt take away (explicitly), to be sure, add/remove eventual .* nodes and all subnodes. +If you experience this not working, double check if you GAVE superior permissions or SUB permissions that you didn't +take away (explicitly), to be sure, add/remove eventual .* nodes and all subnodes. ## Dependencies -Any superperms compatible permissions plugin +Any superperms compatible permissions plugin (like GroupManager, LuckyPerms, etc) diff --git a/doc/modules.md b/doc/modules.md index 9f9ea4b31..25ea71a81 100644 --- a/doc/modules.md +++ b/doc/modules.md @@ -8,8 +8,6 @@ or spectating... To manage your arena mods (download, install, remove, etc), please check [documentation](commands/modules.md) of `/pa modules` command. -To enable a module for an arena, use [`/pa togglemod`](commands/togglemod.md) command. - ## PVP Arena Mods Hook into many different aspects of the game! @@ -54,7 +52,7 @@ Mod | Description | Status [StartFreeze](mods/startfreeze.md) | freeze players at start | ⚠ [TeamSizeRestrict](mods/teamsizerestrict.md) | a small mod to restrict the size of specific teams | ⚠ [Titles](mods/titles.md) | send messages to players as the "title" command would do | ✔ -[TempPerms](mods/tempperms.md) | add temporary perms | ⚠ +[TempPerms](mods/tempperms.md) | add temporary perms | ✔ [Turrets](mods/turrets.md) | add turrets where players fire projectiles | ⚠ [Vault](mods/vault.md) | add economy | ✔ [Walls](mods/walls.md) | define wall regions to simulate "The Walls" | ⚠ @@ -69,4 +67,32 @@ PVP Arena exists since 2011 and Minecraft servers evolution make modules follow- updates will be to make a great check-up of all of them and fix all eventual issues. Anyway, don't hesitate to test legacy modules by yourself, a big part of them work normally or have trivial issues. Obviously -if you encounter one, you can [report it](https://github.com/Eredrim/pvparena/issues) 😉 \ No newline at end of file +if you encounter one, you can [report it](https://github.com/Eredrim/pvparena/issues) 😉 + +## Installing a module + +### Download the module pack + +> ℹ This has to be done only once + +Use the [`/pa modules download`](commands/modules.md) command to download the release version of modules. If you want to +install a dev build version, download the zip archive on [jenkins](https://ci.craftyn.com/job/PVP%20Arena%20Modules/) +and deflate it in the `/files` directory of pvparena. + +After this step, if you type [`/pa modules list`](commands/modules.md), you will show the list of all installable +modules. + +### Installing a module + +> ℹ This has to be done for each module you want to install + +Modules aren't loaded by default, a quick installation is required. +Type [`/pa modules install [moduleName]`](commands/modules.md) to install one of them. + + +### Enable a module for an arena + +> ℹ This has to be done for each arena + +Last step: your module is installed and you want to use it in some of your arenas. +Type [`/pa [arena] !tm [moduleName]`](commands/togglemod.md) to enable it in your arena. \ No newline at end of file From c3ed7fa0ef9391613dc2d441e746469f7f1614c8 Mon Sep 17 00:00:00 2001 From: Eredrim Date: Wed, 25 Nov 2020 21:31:19 +0100 Subject: [PATCH 095/115] v1.15.1 - refactor and fix playerDeathEvent NPE --- src/net/slipcor/pvparena/goals/GoalFood.java | 19 ++------- .../slipcor/pvparena/goals/GoalInfect.java | 24 ++--------- .../pvparena/goals/GoalLiberation.java | 35 +++++----------- .../pvparena/goals/GoalPlayerDeathMatch.java | 35 ++++------------ .../pvparena/goals/GoalPlayerLives.java | 22 +++------- src/net/slipcor/pvparena/goals/GoalTank.java | 20 +++------ .../pvparena/goals/GoalTeamDeathConfirm.java | 23 +++------- .../pvparena/goals/GoalTeamDeathMatch.java | 40 ++++-------------- .../slipcor/pvparena/goals/GoalTeamLives.java | 42 +++++++------------ .../slipcor/pvparena/loadables/ArenaGoal.java | 30 +++++++++++++ 10 files changed, 94 insertions(+), 196 deletions(-) diff --git a/src/net/slipcor/pvparena/goals/GoalFood.java b/src/net/slipcor/pvparena/goals/GoalFood.java index fc2e2c1ac..42fa66c15 100644 --- a/src/net/slipcor/pvparena/goals/GoalFood.java +++ b/src/net/slipcor/pvparena/goals/GoalFood.java @@ -277,17 +277,8 @@ public void commitEnd(final boolean force) { public void commitPlayerDeath(final Player respawnPlayer, final boolean doesRespawn, final String error, final PlayerDeathEvent event) { - final ArenaTeam respawnTeam = ArenaPlayer - .parsePlayer(respawnPlayer.getName()).getArenaTeam(); - - if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { - arena.broadcast(Language.parse(arena, - MSG.FIGHT_KILLED_BY, - respawnTeam.colorizePlayer(respawnPlayer) - + ChatColor.YELLOW, arena.parseDeathCause( - respawnPlayer, event.getEntity() - .getLastDamageCause().getCause(), event - .getEntity().getKiller()))); + if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { + this.broadcastSimpleDeathMessage(respawnPlayer, event); } final List returned; @@ -297,12 +288,10 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp returned = InventoryManager.drop(respawnPlayer); event.getDrops().clear(); } else { - returned = new ArrayList<>(); - returned.addAll(event.getDrops()); + returned = new ArrayList<>(event.getDrops()); } - PACheck.handleRespawn(arena, - ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned); + PACheck.handleRespawn(this.arena, ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned); } diff --git a/src/net/slipcor/pvparena/goals/GoalInfect.java b/src/net/slipcor/pvparena/goals/GoalInfect.java index 8284f4d8f..30df95a23 100644 --- a/src/net/slipcor/pvparena/goals/GoalInfect.java +++ b/src/net/slipcor/pvparena/goals/GoalInfect.java @@ -484,12 +484,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, } if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { - this.arena.broadcast(Language.parse(this.arena, - MSG.FIGHT_KILLED_BY, - respawnTeam.colorizePlayer(player) + ChatColor.YELLOW, - this.arena.parseDeathCause(player, event.getEntity() - .getLastDamageCause().getCause(), - player.getKiller()), String.valueOf(iLives))); + this.broadcastSimpleDeathMessage(player, event); } final List returned; @@ -519,12 +514,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, final ArenaTeam respawnTeam = aPlayer .getArenaTeam(); if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { - this.arena.broadcast(Language.parse(this.arena, - MSG.FIGHT_KILLED_BY_REMAINING, - respawnTeam.colorizePlayer(player) + ChatColor.YELLOW, - this.arena.parseDeathCause(player, event.getEntity() - .getLastDamageCause().getCause(), - player.getKiller()), String.valueOf(iLives))); + this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING, player, event, iLives); } final List returned; @@ -534,8 +524,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, returned = InventoryManager.drop(player); event.getDrops().clear(); } else { - returned = new ArrayList<>(); - returned.addAll(event.getDrops()); + returned = new ArrayList<>(event.getDrops()); } PACheck.handleRespawn(this.arena, @@ -551,12 +540,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn, final ArenaTeam respawnTeam = aPlayer .getArenaTeam(); if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) { - this.arena.broadcast(Language.parse(this.arena, - MSG.FIGHT_KILLED_BY_REMAINING, - respawnTeam.colorizePlayer(player) + ChatColor.YELLOW, - this.arena.parseDeathCause(player, event.getEntity() - .getLastDamageCause().getCause(), - player.getKiller()), String.valueOf(iLives))); + this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING, player, event, iLives); } final List returned; diff --git a/src/net/slipcor/pvparena/goals/GoalLiberation.java b/src/net/slipcor/pvparena/goals/GoalLiberation.java index 09d751046..9c69998e8 100644 --- a/src/net/slipcor/pvparena/goals/GoalLiberation.java +++ b/src/net/slipcor/pvparena/goals/GoalLiberation.java @@ -28,12 +28,15 @@ import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; import java.util.*; +import static java.util.Optional.ofNullable; + /** *
  * Arena Goal class "Liberation"
@@ -413,12 +416,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                 final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
                         .getArenaTeam();
                 if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY,
-                            respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                            arena.parseDeathCause(player, event.getEntity()
-                                            .getLastDamageCause().getCause(),
-                                    player.getKiller()), String.valueOf(lives)));
+                    this.broadcastSimpleDeathMessage(player, event);
                 }
                 final List returned;
 
@@ -427,8 +425,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                     returned = InventoryManager.drop(player);
                     event.getDrops().clear();
                 } else {
-                    returned = new ArrayList<>();
-                    returned.addAll(event.getDrops());
+                    returned = new ArrayList<>(event.getDrops());
                 }
                 new InventoryRefillRunnable(arena, aPlayer.get(), returned);
 
@@ -436,7 +433,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
 
                 Bukkit.getScheduler().runTaskLater(PVPArena.instance, new RespawnRunnable(arena, aPlayer, teamName + "jail"), 1L);
 
-                arena.unKillPlayer(aPlayer.get(), aPlayer.get().getLastDamageCause() == null ? null : aPlayer.get().getLastDamageCause().getCause(), aPlayer.get().getKiller());
+                this.arena.unKillPlayer(aPlayer.get(), ofNullable(aPlayer.get().getLastDamageCause()).map(EntityDamageEvent::getCause).orElse(null), aPlayer.get().getKiller());
 
                 if (arena.getArenaConfig().getBoolean(CFG.GOAL_LIBERATION_JAILEDSCOREBOARD)) {
                     aPlayer.get().getScoreboard().getObjective("lives").getScore(aPlayer.getName()).setScore(101);
@@ -450,8 +447,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                     returned = InventoryManager.drop(player);
                     event.getDrops().clear();
                 } else {
-                    returned = new ArrayList<>();
-                    returned.addAll(event.getDrops());
+                    returned = new ArrayList<>(event.getDrops());
                 }
 
                 PACheck.handleRespawn(arena,
@@ -462,12 +458,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                 final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
                         .getArenaTeam();
                 if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY,
-                            respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                            arena.parseDeathCause(player, event.getEntity()
-                                            .getLastDamageCause().getCause(),
-                                    player.getKiller()), String.valueOf(lives)));
+                    this.broadcastSimpleDeathMessage(player, event);
                 }
 
                 PACheck.handleEnd(arena, false);
@@ -480,12 +471,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
                     .getArenaTeam();
             if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                arena.broadcast(Language.parse(arena,
-                        MSG.FIGHT_KILLED_BY_REMAINING,
-                        respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, event.getEntity()
-                                        .getLastDamageCause().getCause(),
-                                player.getKiller()), String.valueOf(lives)));
+                this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING, player, event, lives);
             }
 
             final List returned;
@@ -495,8 +481,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                 returned = InventoryManager.drop(player);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
             PACheck.handleRespawn(arena,
diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerDeathMatch.java b/src/net/slipcor/pvparena/goals/GoalPlayerDeathMatch.java
index db50dc2e7..1bfd6208c 100644
--- a/src/net/slipcor/pvparena/goals/GoalPlayerDeathMatch.java
+++ b/src/net/slipcor/pvparena/goals/GoalPlayerDeathMatch.java
@@ -18,7 +18,6 @@
 import net.slipcor.pvparena.managers.InventoryManager;
 import net.slipcor.pvparena.runnables.EndRunnable;
 import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.PlayerDeathEvent;
@@ -170,13 +169,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             Bukkit.getPluginManager().callEvent(gEvent);
 
             if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
-                        .getArenaTeam();
-                arena.broadcast(Language.parse(arena,
-                        MSG.FIGHT_KILLED_BY,
-                        respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, event.getEntity()
-                                .getLastDamageCause().getCause(), player)));
+                this.broadcastSimpleDeathMessage(player, event);
             }
 
             final List returned;
@@ -186,8 +179,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
                 returned = InventoryManager.drop(player);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
             PACheck.handleRespawn(arena, ArenaPlayer.parsePlayer(player.getName()), returned);
@@ -214,24 +206,12 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             return;
         }
 
-        final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
-                .getArenaTeam();
-        if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-            if (arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
-                arena.broadcast(Language.parse(arena,
-                        MSG.FIGHT_KILLED_BY_REMAINING_FRAGS,
-                        respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, player
-                                .getLastDamageCause().getCause(), killer),
-                        String.valueOf(iLives-1)));
+        if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
+                this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING_FRAGS, player, event, iLives-1);
             } else {
-                arena.broadcast(Language.parse(arena,
-                        MSG.FIGHT_KILLED_BY,
-                        respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, player
-                                .getLastDamageCause().getCause(), killer)));
+                this.broadcastSimpleDeathMessage(player, event);
             }
-
         }
 
         final List returned;
@@ -241,8 +221,7 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             returned = InventoryManager.drop(player);
             event.getDrops().clear();
         } else {
-            returned = new ArrayList<>();
-            returned.addAll(event.getDrops());
+            returned = new ArrayList<>(event.getDrops());
         }
 
         PACheck.handleRespawn(arena, ArenaPlayer.parsePlayer(player.getName()), returned);
diff --git a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java
index 42fd79e6d..051685c80 100644
--- a/src/net/slipcor/pvparena/goals/GoalPlayerLives.java
+++ b/src/net/slipcor/pvparena/goals/GoalPlayerLives.java
@@ -226,26 +226,14 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             pos--;
             getLifeMap().put(player.getName(), pos);
 
-            final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
-                    .getArenaTeam();
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                if (arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY_REMAINING,
-                            respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                            arena.parseDeathCause(player, event.getEntity()
-                                            .getLastDamageCause().getCause(),
-                                    player.getKiller()), String.valueOf(pos)));
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
+                    this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING, player, event, pos);
                 } else {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY,
-                            respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                            arena.parseDeathCause(player, event.getEntity()
-                                            .getLastDamageCause().getCause(),
-                                    player.getKiller())));
+                    this.broadcastSimpleDeathMessage(player, event);
                 }
-
             }
+
             final List returned;
 
             if (arena.getArenaConfig().getBoolean(CFG.PLAYER_DROPSINVENTORY)) {
diff --git a/src/net/slipcor/pvparena/goals/GoalTank.java b/src/net/slipcor/pvparena/goals/GoalTank.java
index 9cc37e0ed..2e9394080 100644
--- a/src/net/slipcor/pvparena/goals/GoalTank.java
+++ b/src/net/slipcor/pvparena/goals/GoalTank.java
@@ -22,7 +22,6 @@
 import net.slipcor.pvparena.managers.SpawnManager;
 import net.slipcor.pvparena.runnables.EndRunnable;
 import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
 import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@@ -232,29 +231,20 @@ public void commitPlayerDeath(final Player player, final boolean doesRespawn,
             iLives--;
             getLifeMap().put(player.getName(), iLives);
 
-            final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName())
-                    .getArenaTeam();
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                arena.broadcast(Language.parse(arena,
-                        MSG.FIGHT_KILLED_BY_REMAINING,
-                        respawnTeam.colorizePlayer(player) + ChatColor.YELLOW,
-                        arena.parseDeathCause(player, event.getEntity()
-                                        .getLastDamageCause().getCause(),
-                                player.getKiller()), String.valueOf(iLives)));
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING, player, event, iLives);
             }
             final List returned;
 
-            if (arena.getArenaConfig().getBoolean(
+            if (this.arena.getArenaConfig().getBoolean(
                     CFG.PLAYER_DROPSINVENTORY)) {
                 returned = InventoryManager.drop(player);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
-            PACheck.handleRespawn(arena,
-                    ArenaPlayer.parsePlayer(player.getName()), returned);
+            PACheck.handleRespawn(this.arena, ArenaPlayer.parsePlayer(player.getName()), returned);
         }
     }
 
diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
index c26f5cb40..5c756fac2 100644
--- a/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
+++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathConfirm.java
@@ -180,20 +180,12 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp
         }
 
 
-        final ArenaTeam respawnTeam = ArenaPlayer
-                .parsePlayer(respawnPlayer.getName()).getArenaTeam();
+        final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(respawnPlayer.getName()).getArenaTeam();
 
         drop(respawnPlayer, respawnTeam);
 
-        if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-
-            arena.broadcast(Language.parse(arena,
-                    MSG.FIGHT_KILLED_BY,
-                    respawnTeam.colorizePlayer(respawnPlayer)
-                            + ChatColor.YELLOW, arena.parseDeathCause(
-                            respawnPlayer, event.getEntity()
-                                    .getLastDamageCause().getCause(), event
-                                    .getEntity().getKiller())));
+        if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+            this.broadcastSimpleDeathMessage(respawnPlayer, event);
         }
 
         final List returned;
@@ -202,12 +194,10 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp
             returned = InventoryManager.drop(respawnPlayer);
             event.getDrops().clear();
         } else {
-            returned = new ArrayList<>();
-            returned.addAll(event.getDrops());
+            returned = new ArrayList<>(event.getDrops());
         }
 
-        PACheck.handleRespawn(arena,
-                ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned);
+        PACheck.handleRespawn(this.arena, ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned);
     }
 
     @Override
@@ -234,8 +224,7 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
                     this,
                     String.valueOf(arena.getArenaConfig()
                             .getInt(CFG.GOAL_TDC_LIVES) - (getLifeMap()
-                            .containsKey(aPlayer.getArenaTeam().getName()) ? getLifeMap()
-                            .get(aPlayer.getArenaTeam().getName()) : 0)));
+                            .getOrDefault(aPlayer.getArenaTeam().getName(), 0))));
         }
         return res;
     }
diff --git a/src/net/slipcor/pvparena/goals/GoalTeamDeathMatch.java b/src/net/slipcor/pvparena/goals/GoalTeamDeathMatch.java
index 51041742c..d9ee609c4 100644
--- a/src/net/slipcor/pvparena/goals/GoalTeamDeathMatch.java
+++ b/src/net/slipcor/pvparena/goals/GoalTeamDeathMatch.java
@@ -252,53 +252,30 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp
                 PACheck.handleRespawn(arena,
                         ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned);
                 ArenaPlayer.parsePlayer(respawnPlayer.getName()).setStatus(Status.LOST);
-
-
-//				arena.getDebugger().i("faking player death", respawnPlayer);
-//				PlayerListener.finallyKillPlayer(arena, respawnPlayer, event);
             }
             return;
 
 
         }
 
-        if (getLifeMap().get(killerTeam.getName()) != null) {
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-
+        if (this.getLifeMap().get(killerTeam.getName()) != null) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
                 if (killerTeam.equals(respawnTeam) || !arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY,
-                            respawnTeam.colorizePlayer(respawnPlayer)
-                                    + ChatColor.YELLOW, arena.parseDeathCause(
-                                    respawnPlayer, event.getEntity()
-                                            .getLastDamageCause().getCause(), event
-                                            .getEntity().getKiller())));
+                    this.broadcastSimpleDeathMessage(respawnPlayer, event);
                 } else {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY_REMAINING_TEAM_FRAGS,
-                            respawnTeam.colorizePlayer(respawnPlayer)
-                                    + ChatColor.YELLOW, arena.parseDeathCause(
-                                    respawnPlayer, event.getEntity()
-                                            .getLastDamageCause().getCause(), event
-                                            .getEntity().getKiller()), String
-                                    .valueOf(getLifeMap().get(killerTeam.getName())),
-                            killerTeam.getColoredName()));
+                    this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING_TEAM_FRAGS, respawnPlayer, event, this.getLifeMap().get(killerTeam.getName()));
                 }
             }
             final List returned;
 
-            if (arena.getArenaConfig().getBoolean(
-                    CFG.PLAYER_DROPSINVENTORY)) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.PLAYER_DROPSINVENTORY)) {
                 returned = InventoryManager.drop(respawnPlayer);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
-            PACheck.handleRespawn(arena,
-                    ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned);
-
+            PACheck.handleRespawn(this.arena, ArenaPlayer.parsePlayer(respawnPlayer.getName()), returned);
         }
 
     }
@@ -325,8 +302,7 @@ public PACheck getLives(final PACheck res, final ArenaPlayer aPlayer) {
                     this,
                     String.valueOf(arena.getArenaConfig()
                             .getInt(CFG.GOAL_TDM_LIVES) - (getLifeMap()
-                            .containsKey(aPlayer.getArenaTeam().getName()) ? getLifeMap()
-                            .get(aPlayer.getArenaTeam().getName()) : 0)));
+                            .getOrDefault(aPlayer.getArenaTeam().getName(), 0))));
         }
         return res;
     }
diff --git a/src/net/slipcor/pvparena/goals/GoalTeamLives.java b/src/net/slipcor/pvparena/goals/GoalTeamLives.java
index 5ead522dd..782f743ca 100644
--- a/src/net/slipcor/pvparena/goals/GoalTeamLives.java
+++ b/src/net/slipcor/pvparena/goals/GoalTeamLives.java
@@ -118,10 +118,10 @@ public PACheck checkPlayerDeath(final PACheck res, final Player player) {
             final ArenaTeam respawnTeam = ArenaPlayer
                     .parsePlayer(player.getName()).getArenaTeam();
 
-            if (getLifeMap().get(respawnTeam.getName()) != null) {
+            if (this.getTeamLives(respawnTeam) != null) {
                 return res;
             }
-            if (getLifeMap().get(respawnTeam.getName()) <= 1) {
+            if (this.getTeamLives(respawnTeam) <= 1) {
                 res.setError(this, "0");
             }
 
@@ -185,28 +185,14 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp
                 .parsePlayer(respawnPlayer.getName()).getArenaTeam();
         reduceLives(arena, respawnTeam);
 
-        if (getLifeMap().get(respawnTeam.getName()) != null) {
-            if (arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
-                if (arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY_REMAINING_TEAM,
-                            respawnTeam.colorizePlayer(respawnPlayer)
-                                    + ChatColor.YELLOW, arena.parseDeathCause(
-                                    respawnPlayer, event.getEntity()
-                                            .getLastDamageCause().getCause(), event
-                                            .getEntity().getKiller()), String
-                                    .valueOf(getLifeMap().get(respawnTeam.getName())),
-                            respawnTeam.getColoredName()));
+        if (this.getTeamLives(respawnTeam) != null) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.USES_DEATHMESSAGES)) {
+                if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_SHOWREMAININGLIVES)) {
+                    this.broadcastDeathMessage(MSG.FIGHT_KILLED_BY_REMAINING_TEAM, respawnPlayer, event,
+                            this.getTeamLives(respawnTeam));
                 } else {
-                    arena.broadcast(Language.parse(arena,
-                            MSG.FIGHT_KILLED_BY,
-                            respawnTeam.colorizePlayer(respawnPlayer)
-                                    + ChatColor.YELLOW, arena.parseDeathCause(
-                                    respawnPlayer, event.getEntity()
-                                            .getLastDamageCause().getCause(), event
-                                            .getEntity().getKiller())));
+                    this.broadcastSimpleDeathMessage(respawnPlayer, event);
                 }
-
             }
 
             final List returned;
@@ -216,8 +202,7 @@ public void commitPlayerDeath(final Player respawnPlayer, final boolean doesResp
                 returned = InventoryManager.drop(respawnPlayer);
                 event.getDrops().clear();
             } else {
-                returned = new ArrayList<>();
-                returned.addAll(event.getDrops());
+                returned = new ArrayList<>(event.getDrops());
             }
 
             PACheck.handleRespawn(arena,
@@ -288,7 +273,7 @@ public boolean isInternal() {
     }
 
     private void reduceLives(final Arena arena, final ArenaTeam team) {
-        final int iLives = getLifeMap().get(team.getName());
+        final int iLives = this.getTeamLives(team);
 
         if (iLives <= 1) {
             getLifeMap().remove(team.getName());
@@ -345,8 +330,7 @@ public void setDefaults(final YamlConfiguration config) {
     public Map timedEnd(final Map scores) {
 
         for (final ArenaTeam team : arena.getTeams()) {
-            double score = getLifeMap().containsKey(team.getName()) ? getLifeMap().get(team
-                    .getName()) : 0;
+            double score = this.getLifeMap().containsKey(team.getName()) ? this.getTeamLives(team) : 0;
             if (scores.containsKey(team.getName())) {
                 scores.put(team.getName(), scores.get(team.getName()) + score);
             } else {
@@ -356,4 +340,8 @@ public Map timedEnd(final Map scores) {
 
         return scores;
     }
+
+    private Integer getTeamLives(ArenaTeam respawnTeam) {
+        return this.getLifeMap().get(respawnTeam.getName());
+    }
 }
diff --git a/src/net/slipcor/pvparena/loadables/ArenaGoal.java b/src/net/slipcor/pvparena/loadables/ArenaGoal.java
index 50e4cf018..9dc01ab55 100644
--- a/src/net/slipcor/pvparena/loadables/ArenaGoal.java
+++ b/src/net/slipcor/pvparena/loadables/ArenaGoal.java
@@ -9,7 +9,9 @@
 import net.slipcor.pvparena.commands.CommandTree;
 import net.slipcor.pvparena.core.Config.CFG;
 import net.slipcor.pvparena.core.Debug;
+import net.slipcor.pvparena.core.Language;
 import net.slipcor.pvparena.ncloader.NCBLoadable;
+import org.bukkit.ChatColor;
 import org.bukkit.block.Block;
 import org.bukkit.command.CommandSender;
 import org.bukkit.configuration.file.YamlConfiguration;
@@ -25,6 +27,8 @@
 
 import java.util.*;
 
+import static java.util.Optional.ofNullable;
+
 /**
  * 
  * Arena Goal class
@@ -527,4 +531,30 @@ protected void updateLives(final Player player, final int value) {
             getLifeMap().put(player.getName(), value);
         }
     }
+
+    protected void broadcastSimpleDeathMessage(Player player, PlayerDeathEvent event) {
+        this.broadcastDeathMessage(Language.MSG.FIGHT_KILLED_BY, player, event, null);
+    }
+
+    protected void broadcastDeathMessage(Language.MSG deathMessage, Player player, PlayerDeathEvent event, Integer remainingLives) {
+        final ArenaTeam respawnTeam = ArenaPlayer.parsePlayer(player.getName()).getArenaTeam();
+
+        EntityDamageEvent.DamageCause damageCause = ofNullable(event.getEntity().getLastDamageCause())
+                .map(EntityDamageEvent::getCause)
+                .orElse(null);
+        String deathCause = this.arena.parseDeathCause(player, damageCause, event.getEntity().getKiller());
+        String coloredPlayerName = respawnTeam.colorizePlayer(player) + ChatColor.YELLOW;
+
+        if(deathMessage == Language.MSG.FIGHT_KILLED_BY_REMAINING || deathMessage == Language.MSG.FIGHT_KILLED_BY_REMAINING_FRAGS) {
+            this.arena.broadcast(Language.parse(this.arena, deathMessage,
+                    coloredPlayerName, deathCause, String.valueOf(remainingLives)));
+        } else if(deathMessage == Language.MSG.FIGHT_KILLED_BY_REMAINING_TEAM || deathMessage == Language.MSG.FIGHT_KILLED_BY_REMAINING_TEAM_FRAGS) {
+            this.arena.broadcast(Language.parse(this.arena, deathMessage,
+                    coloredPlayerName,deathCause, String.valueOf(remainingLives),
+                    respawnTeam.getColoredName()));
+        } else {
+            this.arena.broadcast(Language.parse(this.arena, Language.MSG.FIGHT_KILLED_BY,
+                    coloredPlayerName, deathCause));
+        }
+    }
 }

From f1b6f2e44fc841b041d28fcae46522379dadc6d6 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Sun, 13 Dec 2020 21:43:37 +0100
Subject: [PATCH 096/115] v1.15.1 - update modules and region documentation

---
 doc/mods/projectiles.md | 20 ++++++++++++++++++++
 doc/mods/worldedit.md   |  2 ++
 doc/modules.md          |  3 ++-
 doc/regions.md          |  5 +++++
 4 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 doc/mods/projectiles.md

diff --git a/doc/mods/projectiles.md b/doc/mods/projectiles.md
new file mode 100644
index 000000000..8b9aed5f1
--- /dev/null
+++ b/doc/mods/projectiles.md
@@ -0,0 +1,20 @@
+# Projectiles
+
+## About
+
+This module enables knockback effect for snowballs, eggs, fishing hooks and ender pearls in order to retrieve old spigot
+behavior.
+
+## Setup
+
+There is no special setup for this module, follow the [general module installation](../modules.md#installing-modules) 
+guide to enable it.
+
+## Config settings
+
+*These settings can be found under `mods.projectiles` node in your arena config file.*
+
+- snowball - enable knockback for snowballs (default: true)
+- egg - enable knockback for eggs (default: true)
+- fishHook - enable knockback for fishing hooks (default: false)
+- enderPearl - enable knockback for ender pearls (default: false)
diff --git a/doc/mods/worldedit.md b/doc/mods/worldedit.md
index 71af2dd23..5e5c3c133 100644
--- a/doc/mods/worldedit.md
+++ b/doc/mods/worldedit.md
@@ -12,6 +12,8 @@ This module needs a full server restart to hook into WorldEdit properly, for the
 
 ## Config settings
 
+*These settings can be found under `mods.worldedit` node in your arena config file.*
+
 - autoload - automatically load the arena's BATTLE regions after fight (default: false)
 - autosave - automatically save the arena's BATTLE regions before fight (default: false)
 - regions - specify individual regions rather than all BATTLE regions (default: empty)
diff --git a/doc/modules.md b/doc/modules.md
index 25ea71a81..3cfd23f7e 100644
--- a/doc/modules.md
+++ b/doc/modules.md
@@ -41,6 +41,7 @@ Mod | Description | Status
 [PlayerFinder](mods/playerfinder.md) | allow players to find others with a compass | ✔
 [Points](mods/points.md) | allow to restrict certain classes to require players to fight for better classes | ⚠
 [PowerUps](mods/powerups.md) | spawn items giving special powers | ✔
+[Projectiles](mods/projectiles.md) | add knockback to throwable items (snowballs, eggs, etc) | ✔
 [RealSpectate](mods/realspectate.md) | spectate the game, CounterStrike style! | ✔
 [RedstoneTriggers](mods/redstonetriggers.md) | add win/lose triggered by redstone | ⚠
 [RespawnRelay](mods/respawnrelay.md) | add a relay for respawning players | ⚠
@@ -69,7 +70,7 @@ updates will be to make a great check-up of all of them and fix all eventual iss
 Anyway, don't hesitate to test legacy modules by yourself, a big part of them work normally or have trivial issues. Obviously
 if you encounter one, you can [report it](https://github.com/Eredrim/pvparena/issues) 😉
 
-## Installing a module
+## Installing modules
 
 ### Download the module pack
 
diff --git a/doc/regions.md b/doc/regions.md
index 15a469d0e..228a73920 100644
--- a/doc/regions.md
+++ b/doc/regions.md
@@ -86,3 +86,8 @@ Example: `/pa !p main break on` - disallow players to break blocks in "main" reg
 
 > 🚩 **Tip:**  
 > There is an "ALL" protection argument that toggle all protections
+
+## Region Removal
+
+First, you need to know the region name. List regions with `/pa [arenaname] regions`.  
+Then, use `/pa [arenaName] region [regionname] remove` to remove the region.

From 5f40d8dbb23f418ac550d2c75d2a60dfe295c340 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Sun, 13 Dec 2020 22:58:22 +0100
Subject: [PATCH 097/115] v1.15.1 - add custom potion effect serialization
 issue#59

---
 .../slipcor/pvparena/core/ItemStackUtils.java | 32 +++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/net/slipcor/pvparena/core/ItemStackUtils.java b/src/net/slipcor/pvparena/core/ItemStackUtils.java
index 4a71c65b7..0f7abeec3 100644
--- a/src/net/slipcor/pvparena/core/ItemStackUtils.java
+++ b/src/net/slipcor/pvparena/core/ItemStackUtils.java
@@ -8,8 +8,14 @@
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.ItemMeta;
 import org.bukkit.inventory.meta.LeatherArmorMeta;
+import org.bukkit.inventory.meta.PotionMeta;
+import org.bukkit.potion.PotionEffect;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 import static org.bukkit.configuration.serialization.ConfigurationSerialization.deserializeObject;
 
@@ -82,9 +88,22 @@ public static Map getItemStackMap(ItemStack itemStack) {
             if(isAnHandledMetaType(metaMap.get("meta-type").toString())) {
                 metaMap.remove("meta-type");
 
+                // Simplify leather armor colors
                 if(meta instanceof LeatherArmorMeta) {
                     metaMap.put("color", ((LeatherArmorMeta) meta).getColor().serialize());
                 }
+
+                // Simplify custom potion effects
+                if(meta instanceof PotionMeta) {
+                    PotionMeta potionMeta = (PotionMeta) meta;
+
+                    if(potionMeta.hasCustomEffects()) {
+                        List> customEffectMeta = potionMeta.getCustomEffects().stream()
+                                .map(PotionEffect::serialize)
+                                .collect(Collectors.toList());
+                        metaMap.put("custom-effects", customEffectMeta);
+                    }
+                }
             }
             result.put("meta", metaMap);
         }
@@ -116,11 +135,20 @@ private static ItemStack deserialize(Map args) {
                 if(!metaMap.containsKey("meta-type")) {
                     metaMap.put("meta-type", getRightMetaType(metaMap.keySet()).name());
 
-                    //Simplify Leather Armour colors
+                    //Simplify Leather armor colors
                     if(metaMap.containsKey("color")) {
                         Color color = Color.deserialize((Map) metaMap.get("color"));
                         metaMap.put("color", color);
                     }
+
+                    // Simplify custom potion effects
+                    if(metaMap.containsKey("custom-effects")) {
+                        List effectList = ((List) metaMap.get("custom-effects")).stream()
+                                .map(serializedEffect -> new PotionEffect((Map) serializedEffect))
+                                .collect(Collectors.toList());
+
+                        metaMap.put("custom-effects", effectList);
+                    }
                 }
 
 

From 89616e25207d4d9a0ce7a47d6161b9bec5b74f97 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Sun, 13 Dec 2020 23:18:04 +0100
Subject: [PATCH 098/115] v1.15.1 - release [skip-ci]

---
 pom.xml | 196 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 98 insertions(+), 98 deletions(-)

diff --git a/pom.xml b/pom.xml
index 67a5647bb..0053ed617 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,99 +1,99 @@
-
-    4.0.0
-
-    net.slipcor
-    pvparena
-    1.15.1-SNAPSHOT
-    PVP Arena
-    https://github.com/Eredrim/pvparena
-
-    
-        
-        UTF-8
-    
-
-    
-        
-            spigot-repo
-            https://hub.spigotmc.org/nexus/content/groups/public/
-        
-        
-            CodeMC
-            https://repo.codemc.org/repository/maven-public
-        
-    
-
-    
-        
-            org.spigotmc
-            spigot-api
-            1.13.2-R0.1-SNAPSHOT
-            jar
-            provided
-        
-        
-            org.bstats
-            bstats-bukkit
-            1.7
-            compile
-        
-    
-
-    
-        clean package install
-        pvparena-${project.version}${buildVersion}
-        ${basedir}/src
-
-        
-            
-                .
-                true
-                ${basedir}/src
-                
-                    config.yml
-                    plugin.yml
-                
-            
-        
-
-        
-            
-                org.apache.maven.plugins
-                maven-compiler-plugin
-                3.8.1
-                
-                    8
-                    8
-                    UTF-8
-                
-            
-            
-                org.apache.maven.plugins
-                maven-jar-plugin
-                3.2.0
-            
-            
-                org.apache.maven.plugins
-                maven-shade-plugin
-                3.1.0
-                
-                    
-                        
-                            org.bstats
-                            net.slipcor.pvparena
-                        
-                    
-                
-                
-                    
-                        package
-                        
-                            shade
-                        
-                    
-                
-            
-        
-    
+
+    4.0.0
+
+    net.slipcor
+    pvparena
+    1.15.1
+    PVP Arena
+    https://github.com/Eredrim/pvparena
+
+    
+        
+        UTF-8
+    
+
+    
+        
+            spigot-repo
+            https://hub.spigotmc.org/nexus/content/groups/public/
+        
+        
+            CodeMC
+            https://repo.codemc.org/repository/maven-public/
+        
+    
+
+    
+        
+            org.spigotmc
+            spigot-api
+            1.13.2-R0.1-SNAPSHOT
+            jar
+            provided
+        
+        
+            org.bstats
+            bstats-bukkit
+            1.7
+            compile
+        
+    
+
+    
+        clean package install
+        pvparena-${project.version}${buildVersion}
+        ${basedir}/src
+
+        
+            
+                .
+                true
+                ${basedir}/src
+                
+                    config.yml
+                    plugin.yml
+                
+            
+        
+
+        
+            
+                org.apache.maven.plugins
+                maven-compiler-plugin
+                3.8.1
+                
+                    8
+                    8
+                    UTF-8
+                
+            
+            
+                org.apache.maven.plugins
+                maven-jar-plugin
+                3.2.0
+            
+            
+                org.apache.maven.plugins
+                maven-shade-plugin
+                3.1.0
+                
+                    
+                        
+                            org.bstats
+                            net.slipcor.pvparena
+                        
+                    
+                
+                
+                    
+                        package
+                        
+                            shade
+                        
+                    
+                
+            
+        
+    
 
\ No newline at end of file

From d39ced302f9ebc268f832a53b72f61e8b75333d4 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 14 Dec 2020 20:53:58 +0100
Subject: [PATCH 099/115] v1.15.2 - bump to new version

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 0053ed617..a71992e93 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 
     net.slipcor
     pvparena
-    1.15.1
+    1.15.2-SNAPSHOT
     PVP Arena
     https://github.com/Eredrim/pvparena
 

From 5d5162e42ce4df4b1dbf5ac1ffe4a0790391ecff Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Mon, 14 Dec 2020 21:04:34 +0100
Subject: [PATCH 100/115] Duel arena requires more spawns than the maximum
 players allowed. #43

---
 src/net/slipcor/pvparena/loadables/ArenaGoal.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/loadables/ArenaGoal.java b/src/net/slipcor/pvparena/loadables/ArenaGoal.java
index 9dc01ab55..98058df74 100644
--- a/src/net/slipcor/pvparena/loadables/ArenaGoal.java
+++ b/src/net/slipcor/pvparena/loadables/ArenaGoal.java
@@ -159,7 +159,8 @@ protected String checkForMissingSpawn(final Set list) {
                 count++;
             }
         }
-        return count > 3 ? null : "need more spawns! (" + count + "/4)";
+        int minPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MINPLAYERS);
+        return count >= minPlayers ? null : "need more spawns! (" + count + "/" + minPlayers + ")";
     }
 
     /**

From 9893b9a68f7250d2d3734c0e2625feb5b7c8eebe Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 15 Dec 2020 21:25:55 +0100
Subject: [PATCH 101/115] v1.15.2 - remove announce of modules update if they
 are absent

---
 src/net/slipcor/pvparena/updater/ModulesUpdater.java | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/net/slipcor/pvparena/updater/ModulesUpdater.java b/src/net/slipcor/pvparena/updater/ModulesUpdater.java
index 18c61dc84..e684fc3c3 100644
--- a/src/net/slipcor/pvparena/updater/ModulesUpdater.java
+++ b/src/net/slipcor/pvparena/updater/ModulesUpdater.java
@@ -46,7 +46,9 @@ protected void runUpdater() throws IOException {
         JsonObject versionJson = getVersionJson(connection.getInputStream());
         String onlineVersion = getOnlineVersionFromJson(versionJson);
 
-        if(isUpToDate(currentVersion, onlineVersion)) {
+        if(currentVersion == null) {
+            LOG.info("PVP Arena modules are not detected");
+        } else if(isUpToDate(currentVersion, onlineVersion)) {
             LOG.info("PVP Arena modules are up to date");
         } else {
             String updateInfo = getAnnounceMessage(MSG.UPDATER_MODULES.toString(), onlineVersion, currentVersion);
@@ -103,7 +105,7 @@ private String getModulesVersion() {
                 e.printStackTrace();
             }
         }
-        return "0.0.0";
+        return null;
     }
 
     /**

From ecfe880247b173b9e48c4bd45378580ca7d3a782 Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Sat, 19 Dec 2020 10:14:08 +0100
Subject: [PATCH 102/115] fix #69 NPE when killing player

---
 src/net/slipcor/pvparena/arena/ArenaPlayer.java | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/ArenaPlayer.java b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
index 056ad46aa..483ba0908 100644
--- a/src/net/slipcor/pvparena/arena/ArenaPlayer.java
+++ b/src/net/slipcor/pvparena/arena/ArenaPlayer.java
@@ -28,6 +28,8 @@
 import java.io.File;
 import java.util.*;
 
+import static java.util.Optional.ofNullable;
+
 /**
  * 
  * Arena Player class
@@ -100,6 +102,7 @@ public enum Status {
      */
     public enum PlayerPrevention {
         BREAK, PLACE, TNT, TNTBREAK, DROP, INVENTORY, PICKUP, CRAFT;
+
         public static boolean has(int value, PlayerPrevention s) {
             return (((int) Math.pow(2, s.ordinal()) & value) > 0);
         }
@@ -166,7 +169,8 @@ public static Player getLastDamagingPlayer(final Event eEvent, final Player dama
             }
         }
         debug.i("last damaging player is null", damagee);
-        debug.i("last damaging event: " + eEvent.getEventName(), damagee);
+        debug.i("last damaging event: " + ofNullable(eEvent).map(Event::getEventName)
+                .orElse("unknown cause"), damagee);
         return null;
     }
 
@@ -212,7 +216,7 @@ public static ArenaPlayer parsePlayer(final String name) {
                 return new ArenaPlayer(name);
             }
 
-            if(!totalPlayers.containsKey(name)) {
+            if (!totalPlayers.containsKey(name)) {
                 ArenaPlayer ap = new ArenaPlayer(player.getName());
                 totalPlayers.putIfAbsent(name, ap);
             }
@@ -315,15 +319,17 @@ public void run() {
         } else {
             class GiveLater implements Runnable {
                 final ItemStack[] inv;
+
                 GiveLater(final ItemStack[] inv) {
                     this.inv = inv.clone();
-                    }
+                }
+
                 @Override
                 public void run() {
                     debug.i("adding saved inventory",
                             player);
                     player.getInventory().setContents(inv);
-                    }
+                }
             }
             final GiveLater gl = new GiveLater(aPlayer.savedInventory);
             try {
@@ -468,6 +474,7 @@ public Arena getArena() {
     public ArenaClass getArenaClass() {
         return aClass;
     }
+
     public ArenaClass getNextArenaClass() {
         return naClass;
     }
@@ -828,7 +835,7 @@ public void setStatus(final Status status) {
      */
     public void setTelePass(final boolean canTeleport) {
         if (arena != null) {
-            arena.getDebugger().i("TelePass := "+canTeleport);
+            arena.getDebugger().i("TelePass := " + canTeleport);
         }
         telePass = canTeleport;
     }

From a7e2660078eca00dcd622904cf60ab291bfed2b7 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 22 Dec 2020 20:33:26 +0100
Subject: [PATCH 103/115] v1.15.2 - fix blockDestroy colorable issue #71

---
 src/net/slipcor/pvparena/core/ColorUtils.java   |  2 +-
 .../pvparena/goals/GoalBlockDestroy.java        | 17 ++++++-----------
 2 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/net/slipcor/pvparena/core/ColorUtils.java b/src/net/slipcor/pvparena/core/ColorUtils.java
index 3d409c14f..abe8b17c1 100644
--- a/src/net/slipcor/pvparena/core/ColorUtils.java
+++ b/src/net/slipcor/pvparena/core/ColorUtils.java
@@ -104,7 +104,7 @@ public static Material getColoredMaterial(DyeColor dyeColor, Material typeMateri
     }
 
     public static boolean isSubType(Material type, Material check) {
-        return isColorableMaterial(type) && getMaterialSuffix(type).equals(getMaterialSuffix(check));
+        return (type == check) || (isColorableMaterial(type) && getMaterialSuffix(type).equals(getMaterialSuffix(check)));
     }
 
     private static String getMaterialSuffix(Material material) {
diff --git a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
index 33da732e5..d941f51c5 100644
--- a/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
+++ b/src/net/slipcor/pvparena/goals/GoalBlockDestroy.java
@@ -539,17 +539,12 @@ public void unload(final Player player) {
     @EventHandler(priority = EventPriority.MONITOR)
     public void onBlockBreak(final BlockBreakEvent event) {
         final Player player = event.getPlayer();
-        if (!arena.hasPlayer(event.getPlayer())
-                || !event
-                .getBlock()
-                .getType()
-                .name()
-                .equals(arena.getArenaConfig().getString(
-                        CFG.GOAL_BLOCKDESTROY_BLOCKTYPE))) {
-
+        final Material blockToBreak = this.arena.getArenaConfig().getMaterial(CFG.GOAL_BLOCKDESTROY_BLOCKTYPE);
+        final Material brokenBlock = event.getBlock().getType();
+        if (!this.arena.hasPlayer(event.getPlayer()) || !ColorUtils.isSubType(brokenBlock, blockToBreak)) {
             arena.getDebugger().i("block destroy, ignoring", player);
             arena.getDebugger().i(String.valueOf(arena.hasPlayer(event.getPlayer())), player);
-            arena.getDebugger().i(event.getBlock().getType().name(), player);
+            arena.getDebugger().i(brokenBlock.name(), player);
             return;
         }
 
@@ -692,10 +687,10 @@ public void onEntityExplode(final EntityExplodeEvent event) {
                                 "[PVP Arena] team unknown/no lives: " + blockTeam);
                         e.printStackTrace();
                     }
-                    takeBlock(arena.getTeam(blockTeam).getColor(),
-                            pb.getLocation());
+                    takeBlock(arena.getTeam(blockTeam).getColor(), pb.getLocation());
 
                     reduceLivesCheckEndAndCommit(arena, blockTeam);
+                    break;
                 }
             }
         }

From f42332703d6319094d56c00edfca75d4281be73d Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Mon, 28 Dec 2020 12:26:49 +0100
Subject: [PATCH 104/115] fix Elytra not loading as chestplate

---
 src/net/slipcor/pvparena/arena/ArenaClass.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/net/slipcor/pvparena/arena/ArenaClass.java b/src/net/slipcor/pvparena/arena/ArenaClass.java
index 4299b541b..0a78c7397 100644
--- a/src/net/slipcor/pvparena/arena/ArenaClass.java
+++ b/src/net/slipcor/pvparena/arena/ArenaClass.java
@@ -238,7 +238,7 @@ private static boolean isHelmetItem(Material material) {
     }
 
     private static boolean isChestplateItem(Material material) {
-        return material.name().endsWith("_CHESTPLATE");
+        return material.name().endsWith("_CHESTPLATE") || material == Material.ELYTRA;
     }
 
     private static boolean isLeggingsItem(Material material) {
@@ -252,4 +252,4 @@ private static boolean isBootsItem(Material material) {
     private static boolean isArmorItem(Material material) {
         return isBootsItem(material) || isLeggingsItem(material) || isChestplateItem(material) || isHelmetItem(material);
     }
-}
\ No newline at end of file
+}

From 0d3ead1e9b4b74eb327f61a0959c53d94f8cd412 Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Sun, 3 Jan 2021 10:04:51 +0100
Subject: [PATCH 105/115] Add error specially for the world when loading region

---
 src/net/slipcor/pvparena/core/Config.java | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/core/Config.java b/src/net/slipcor/pvparena/core/Config.java
index 844fc4178..a6af40978 100644
--- a/src/net/slipcor/pvparena/core/Config.java
+++ b/src/net/slipcor/pvparena/core/Config.java
@@ -944,7 +944,13 @@ public static ArenaRegion parseRegion(final Arena arena,
         final Integer flags = parseInteger(parts[8]);
         final Integer prots = parseInteger(parts[9]);
 
-        if (Bukkit.getWorld(parts[0]) == null || x1 == null || y1 == null
+        if (Bukkit.getWorld(parts[0]) == null) {
+            PVPArena.instance.getLogger().severe(String.format("%s caused an error while loading region %s",
+                    arena.getName(), regionName));
+            throw new IllegalArgumentException(String.format("World %s not recognized. Is it loaded ?", parts[0]));
+        }
+
+        if (x1 == null || y1 == null
                 || z1 == null || x2 == null || y2 == null || z2 == null
                 || flags == null || prots == null) {
             PVPArena.instance.getLogger().severe(arena.getName() + " caused an error while loading region " + regionName);

From bea174b790dbc1f46080af1b39267b0622f28fa6 Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Sat, 9 Jan 2021 11:22:33 +0100
Subject: [PATCH 106/115] update with the new command modules

---
 doc/mods/powerups.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/mods/powerups.md b/doc/mods/powerups.md
index 8742aa829..88e8fb59b 100644
--- a/doc/mods/powerups.md
+++ b/doc/mods/powerups.md
@@ -8,8 +8,8 @@ This mod allows spawning of items that give special powers / bad things, fully c
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
-- `/pa [arenaname] !tm [modname]`
+- `/pa modules install powerups`, activate per arena via
+- `/pa [arenaname] !tm powerups`
 
 ## Setup
 

From ef8590ed784dfb2e94e256e71e5a2840d263a341 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Tue, 9 Feb 2021 00:24:10 +0100
Subject: [PATCH 107/115] v1.15.2 - replace /pa install command in modules doc

---
 doc/mods/aftermatch.md          | 2 +-
 doc/mods/announcements.md       | 2 +-
 doc/mods/arenaboards.md         | 2 +-
 doc/mods/arenamaps.md           | 2 +-
 doc/mods/autosneak.md           | 2 +-
 doc/mods/autovote.md            | 2 +-
 doc/mods/bankick.md             | 2 +-
 doc/mods/battlefieldguard.md    | 2 +-
 doc/mods/battlefieldmanager.md  | 2 +-
 doc/mods/betterclasses.md       | 2 +-
 doc/mods/betterfight.md         | 2 +-
 doc/mods/bettergears.md         | 2 +-
 doc/mods/betterkillstreaks.md   | 2 +-
 doc/mods/chestfiller.md         | 2 +-
 doc/mods/duel.md                | 2 +-
 doc/mods/eventactions.md        | 2 +-
 doc/mods/factions.md            | 2 +-
 doc/mods/fixinventoryloss.md    | 2 +-
 doc/mods/flyspectate.md         | 2 +-
 doc/mods/items.md               | 2 +-
 doc/mods/latelounge.md          | 2 +-
 doc/mods/matchresultstats.md    | 2 +-
 doc/mods/playerfinder.md        | 2 +-
 doc/mods/points.md              | 2 +-
 doc/mods/realspectate.md        | 2 +-
 doc/mods/redstonetriggers.md    | 2 +-
 doc/mods/respawnrelay.md        | 2 +-
 doc/mods/singleplayersupport.md | 2 +-
 doc/mods/skins.md               | 2 +-
 doc/mods/specialjoin.md         | 2 +-
 doc/mods/spectate.md            | 2 +-
 doc/mods/squads.md              | 2 +-
 doc/mods/startfreeze.md         | 2 +-
 doc/mods/teamsizerestrict.md    | 2 +-
 doc/mods/titles.md              | 2 +-
 doc/mods/turrets.md             | 2 +-
 doc/mods/vault.md               | 2 +-
 doc/mods/walls.md               | 2 +-
 doc/mods/worldguard.md          | 2 +-
 39 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/doc/mods/aftermatch.md b/doc/mods/aftermatch.md
index 3e95f6acf..5447f0b6d 100644
--- a/doc/mods/aftermatch.md
+++ b/doc/mods/aftermatch.md
@@ -5,7 +5,7 @@ This mod adds a special ending to the game. After a set amount of time / kills,
 ## Installation
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/announcements.md b/doc/mods/announcements.md
index 9c09a4d14..21c3c5967 100644
--- a/doc/mods/announcements.md
+++ b/doc/mods/announcements.md
@@ -5,7 +5,7 @@ Teach your arena how to talk! Every event can possibly trigger a global message
 ## Installation
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/arenaboards.md b/doc/mods/arenaboards.md
index 9abf6bf48..cfd0575a4 100644
--- a/doc/mods/arenaboards.md
+++ b/doc/mods/arenaboards.md
@@ -5,7 +5,7 @@ This mod adds possibility to add arena boards to the game!
 ## Installation
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/arenamaps.md b/doc/mods/arenamaps.md
index c4ecd99ae..ce427a421 100644
--- a/doc/mods/arenamaps.md
+++ b/doc/mods/arenamaps.md
@@ -8,7 +8,7 @@ This mod hands players a map of the arena. Optional display of lives and player/
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/autosneak.md b/doc/mods/autosneak.md
index 697b00800..d8c43ee68 100644
--- a/doc/mods/autosneak.md
+++ b/doc/mods/autosneak.md
@@ -7,7 +7,7 @@ This mod automatically sets players to sneak, in order for their nametags to be
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/autovote.md b/doc/mods/autovote.md
index f95d5c21d..9fa701964 100644
--- a/doc/mods/autovote.md
+++ b/doc/mods/autovote.md
@@ -8,7 +8,7 @@ This mod adds an automated arena managing system. Once started, the end of an ar
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/bankick.md b/doc/mods/bankick.md
index 837f5af4a..b0ed3787d 100644
--- a/doc/mods/bankick.md
+++ b/doc/mods/bankick.md
@@ -8,7 +8,7 @@ A fully functional kick/ban suite to get rid of derps that don't ready up or tro
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/battlefieldguard.md b/doc/mods/battlefieldguard.md
index 48c382d52..f923079fe 100644
--- a/doc/mods/battlefieldguard.md
+++ b/doc/mods/battlefieldguard.md
@@ -7,7 +7,7 @@ This mod guards your battlefield. Entering people will be kicked/killed. Fun!
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/battlefieldmanager.md b/doc/mods/battlefieldmanager.md
index 520e267ce..790e4f024 100644
--- a/doc/mods/battlefieldmanager.md
+++ b/doc/mods/battlefieldmanager.md
@@ -8,7 +8,7 @@ This mod allows to run one arena with several spawn setups. Save and load spawn
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/betterclasses.md b/doc/mods/betterclasses.md
index f60338a61..3f76d80ef 100644
--- a/doc/mods/betterclasses.md
+++ b/doc/mods/betterclasses.md
@@ -8,7 +8,7 @@ This mod adds more to your classes, POTION effects and maximum player count!
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/betterfight.md b/doc/mods/betterfight.md
index 531918aa9..19539bd7e 100644
--- a/doc/mods/betterfight.md
+++ b/doc/mods/betterfight.md
@@ -8,7 +8,7 @@ This mod enhances fighting, by adding one-hit-kill-items and kill streak announc
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/bettergears.md b/doc/mods/bettergears.md
index baa54f699..3cd78f415 100644
--- a/doc/mods/bettergears.md
+++ b/doc/mods/bettergears.md
@@ -8,7 +8,7 @@ This mod adds colored armor to keep track of teams more easily. The class armor
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/betterkillstreaks.md b/doc/mods/betterkillstreaks.md
index de513627f..0a54094bb 100644
--- a/doc/mods/betterkillstreaks.md
+++ b/doc/mods/betterkillstreaks.md
@@ -8,7 +8,7 @@ This mod enhances fighting, by adding kill streak potion effects or items
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/chestfiller.md b/doc/mods/chestfiller.md
index 5bc252aec..9116b4251 100644
--- a/doc/mods/chestfiller.md
+++ b/doc/mods/chestfiller.md
@@ -8,7 +8,7 @@ This mod adds random chest contents. It places stuff you can configure inside ch
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/duel.md b/doc/mods/duel.md
index 6ed0bdbc7..63d74ba1e 100644
--- a/doc/mods/duel.md
+++ b/doc/mods/duel.md
@@ -8,7 +8,7 @@ This turns your arena into a 1:1 arena if possible, and if a player dares anothe
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/eventactions.md b/doc/mods/eventactions.md
index b55c2e5ed..8e6e9e6c9 100644
--- a/doc/mods/eventactions.md
+++ b/doc/mods/eventactions.md
@@ -41,7 +41,7 @@ The following placeholders can be used to get dynamic output in your Commands/me
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/factions.md b/doc/mods/factions.md
index de97549ae..419666907 100644
--- a/doc/mods/factions.md
+++ b/doc/mods/factions.md
@@ -8,7 +8,7 @@ This is a module that tries to override pvp fail due to other plugins cancelling
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/fixinventoryloss.md b/doc/mods/fixinventoryloss.md
index b6a9eb4a4..85a351b31 100644
--- a/doc/mods/fixinventoryloss.md
+++ b/doc/mods/fixinventoryloss.md
@@ -8,7 +8,7 @@ Add methods to prevent ppl losing their stuff because other plugins mess around
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/flyspectate.md b/doc/mods/flyspectate.md
index 067f9b1bf..1f4cd8637 100644
--- a/doc/mods/flyspectate.md
+++ b/doc/mods/flyspectate.md
@@ -8,7 +8,7 @@ Have players joining into an arena, to the spectator spawn. They are invisible a
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/items.md b/doc/mods/items.md
index d11c3c719..88f6e0c9e 100644
--- a/doc/mods/items.md
+++ b/doc/mods/items.md
@@ -8,7 +8,7 @@ Add random items spawning at predefined spots!
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/latelounge.md b/doc/mods/latelounge.md
index c8a07a6f5..ce083c574 100644
--- a/doc/mods/latelounge.md
+++ b/doc/mods/latelounge.md
@@ -8,7 +8,7 @@ Let people announce a join to an arena, yet keep playing until the minimum playe
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/matchresultstats.md b/doc/mods/matchresultstats.md
index d357c49f6..4ecf8d8e5 100644
--- a/doc/mods/matchresultstats.md
+++ b/doc/mods/matchresultstats.md
@@ -10,7 +10,7 @@ A table will be created, but the database has to exist.
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/playerfinder.md b/doc/mods/playerfinder.md
index c45e193b7..8c60075a7 100644
--- a/doc/mods/playerfinder.md
+++ b/doc/mods/playerfinder.md
@@ -10,7 +10,7 @@ Left click to point to the nearest player, right click to show the distance
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/points.md b/doc/mods/points.md
index ff5baf1c1..d466c3ef5 100644
--- a/doc/mods/points.md
+++ b/doc/mods/points.md
@@ -8,7 +8,7 @@ This mod adds a little restriction to classes. Players have to choose lesser cla
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/realspectate.md b/doc/mods/realspectate.md
index 209706be6..50c96fb3f 100644
--- a/doc/mods/realspectate.md
+++ b/doc/mods/realspectate.md
@@ -8,7 +8,7 @@ Have players entering the arena and spectating the game from a player point of v
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/redstonetriggers.md b/doc/mods/redstonetriggers.md
index b029881a1..f66b7e05d 100644
--- a/doc/mods/redstonetriggers.md
+++ b/doc/mods/redstonetriggers.md
@@ -8,7 +8,7 @@ This mod adds a redstone current change listener to eventually do things when a
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/respawnrelay.md b/doc/mods/respawnrelay.md
index c0962ceba..e756b0f78 100644
--- a/doc/mods/respawnrelay.md
+++ b/doc/mods/respawnrelay.md
@@ -8,7 +8,7 @@ This mod puts respawns players in a "relay" spawn arena in order to respawn them
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/singleplayersupport.md b/doc/mods/singleplayersupport.md
index 999541ccf..8671ed2ca 100644
--- a/doc/mods/singleplayersupport.md
+++ b/doc/mods/singleplayersupport.md
@@ -10,7 +10,7 @@ This module can be used for non-pvp game modes like parcour, where a player join
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/skins.md b/doc/mods/skins.md
index 77dd44141..558b61d20 100644
--- a/doc/mods/skins.md
+++ b/doc/mods/skins.md
@@ -14,7 +14,7 @@ This module activates certain skins for teams / classes. IF you don't you disgui
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/specialjoin.md b/doc/mods/specialjoin.md
index 47d45835c..e47e48b90 100644
--- a/doc/mods/specialjoin.md
+++ b/doc/mods/specialjoin.md
@@ -15,7 +15,7 @@ If you use the join sign, the fourth line will represent the arena status and th
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/spectate.md b/doc/mods/spectate.md
index eba3494cb..da09656f7 100644
--- a/doc/mods/spectate.md
+++ b/doc/mods/spectate.md
@@ -10,7 +10,7 @@ Preventing interaction, damage, visibility, POV spectating and more :)
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/squads.md b/doc/mods/squads.md
index 5cc8c97f1..b2754492d 100644
--- a/doc/mods/squads.md
+++ b/doc/mods/squads.md
@@ -10,7 +10,7 @@ Squads are an addition to teams or even a replacement (in case of a FFA arena).
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Usage
diff --git a/doc/mods/startfreeze.md b/doc/mods/startfreeze.md
index ee728bcd8..82395bcdb 100644
--- a/doc/mods/startfreeze.md
+++ b/doc/mods/startfreeze.md
@@ -8,7 +8,7 @@ This module adds a timer that prevents people from moving at the start of a matc
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/teamsizerestrict.md b/doc/mods/teamsizerestrict.md
index aec0d0a5a..b6195edb6 100644
--- a/doc/mods/teamsizerestrict.md
+++ b/doc/mods/teamsizerestrict.md
@@ -8,7 +8,7 @@ This mod adds player limitations to specific team names.
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/titles.md b/doc/mods/titles.md
index 478ce8c90..f2d358521 100644
--- a/doc/mods/titles.md
+++ b/doc/mods/titles.md
@@ -5,7 +5,7 @@ Change the way how messages are sent, by adding the vanilla "title" command func
 ## Installation
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 ## Setup
 
diff --git a/doc/mods/turrets.md b/doc/mods/turrets.md
index bd3f3acef..deb4ffa84 100644
--- a/doc/mods/turrets.md
+++ b/doc/mods/turrets.md
@@ -10,7 +10,7 @@ To use the turret, step on the plate (during a match) and click. Aim where the p
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/vault.md b/doc/mods/vault.md
index d6dd6124e..0039f5d8f 100644
--- a/doc/mods/vault.md
+++ b/doc/mods/vault.md
@@ -8,7 +8,7 @@ The Vault module adds an economy hook to provide several things. Join fee, money
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/walls.md b/doc/mods/walls.md
index 4a742f998..816efc474 100644
--- a/doc/mods/walls.md
+++ b/doc/mods/walls.md
@@ -8,7 +8,7 @@ Yep. It's walls. Simple as can be. Make walls disappear ingame and reappear afte
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup
diff --git a/doc/mods/worldguard.md b/doc/mods/worldguard.md
index b7878837a..b243d90cb 100644
--- a/doc/mods/worldguard.md
+++ b/doc/mods/worldguard.md
@@ -8,7 +8,7 @@ This mod adds squads to the game, basically only showing players belonging toget
 
 Unzip the module files (files tab, "PA Files v*.*.*") into the /pvparena/files folder and install them via
 
-- `/pa install [modname]`, activate per arena via
+- `/pa modules install [modname]`, activate per arena via
 - `/pa [arenaname] !tm [modname]`
 
 ## Setup

From 7edee80eb85e0608b3d50e5394112e3e936a77b3 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 15 Feb 2021 22:25:39 +0100
Subject: [PATCH 108/115] v1.15.2 - implement new ci [skip ci]

---
 .github/workflows/deploy-release.yml  | 24 ++++++++++++
 .github/workflows/deploy-snapshot.yml | 55 +++++++++++++++++++++++++++
 readme.md                             |  6 +--
 3 files changed, 82 insertions(+), 3 deletions(-)
 create mode 100644 .github/workflows/deploy-release.yml
 create mode 100644 .github/workflows/deploy-snapshot.yml

diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml
new file mode 100644
index 000000000..2b42a1482
--- /dev/null
+++ b/.github/workflows/deploy-release.yml
@@ -0,0 +1,24 @@
+name: Maven deploy release
+on:
+  release:
+    types:
+      - published
+
+jobs:
+  deploy:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Set up Maven settings
+        uses: actions/setup-java@v1
+        with:
+          java-version: 1.8
+          server-id: eredrim
+          server-username: MAVEN_USERNAME
+          server-password: MAVEN_PASSWORD
+          
+      - name: Deploy the package
+        run: mvn --batch-mode deploy -DaltDeploymentRepository="eredrim::default::https://repo.eredrim.fr/repository/maven-releases/"
+        env:
+          MAVEN_USERNAME: ${{ secrets.MVN_USER }}
+          MAVEN_PASSWORD: ${{ secrets.MVN_PASSWORD }}
\ No newline at end of file
diff --git a/.github/workflows/deploy-snapshot.yml b/.github/workflows/deploy-snapshot.yml
new file mode 100644
index 000000000..33cb6b638
--- /dev/null
+++ b/.github/workflows/deploy-snapshot.yml
@@ -0,0 +1,55 @@
+name: Maven deploy snapshot
+on:
+  push:
+    branches:
+      - master
+
+jobs:
+  deploy:
+    if: "!contains(github.event.head_commit.message, '[release]') && !contains(github.event.head_commit.message, '[doc]')"
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Set up Maven settings
+        uses: actions/setup-java@v1
+        with:
+          java-version: 1.8
+          server-id: eredrim
+          server-username: MAVEN_USERNAME
+          server-password: MAVEN_PASSWORD
+          
+      - name: Get project version number
+        run: |
+          mvn_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
+          echo "mvn_version=${mvn_version}" >> $GITHUB_ENV
+          
+      - name: Check if version already exists on repository
+        run: |
+          http_code=$(curl -s -o /dev/null -w "%{http_code}" https://repo.eredrim.fr/repository/maven-snapshots/net/slipcor/pvparena/${{ env.mvn_version }}/maven-metadata.xml)
+          echo "version_http_code=${http_code}" >> $GITHUB_ENV
+          
+      - name: Calculate build version with metadata
+        if: ${{ env.version_http_code == 200 }}
+        run: |
+          curl https://repo.eredrim.fr/repository/maven-snapshots/net/slipcor/pvparena/${{ env.mvn_version }}/maven-metadata.xml -o metadata.xml
+          build_number=$(grep -oP '(?<=buildNumber>)[^<]+' "metadata.xml")
+          echo "build_version=$((build_number + 1))" >> $GITHUB_ENV
+          
+      - name: Generate a new build version
+        if: ${{ env.version_http_code != 200 }}
+        run: echo "build_version=1" >> $GITHUB_ENV
+        
+      - name: Deploy the package
+        run: mvn --batch-mode deploy -DbuildVersion=-b${{ env.build_version }} -DaltDeploymentRepository="eredrim::default::https://repo.eredrim.fr/repository/maven-snapshots/"
+        env:
+          MAVEN_USERNAME: ${{ secrets.MVN_USER }}
+          MAVEN_PASSWORD: ${{ secrets.MVN_PASSWORD }}
+          
+      - name: Post discord notification
+        run: |
+          commits="${{ join(github.event.commits.*.message, '\n - ') }}"
+          avatar_url=https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
+          bot_username="Build notification"
+          payload_json='{ "username": "'$bot_username'", "avatar_url": "'$avatar_url'", "content": "A new dev build of PVP arena is available! Download it by saving the attached file.", "embeds": [{"description": ":spiral_note_pad: **New commits:**\n\n - '$commits'"}] }'
+          curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} -F payload_json="${payload_json}"
+          curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} -F username="${bot_username}" -F avatar_url="${avatar_url}" -F file=@target/pvparena-${{ env.mvn_version }}-b${{ env.build_version }}.jar
\ No newline at end of file
diff --git a/readme.md b/readme.md
index f656c976b..235941f79 100644
--- a/readme.md
+++ b/readme.md
@@ -53,8 +53,8 @@ PVP Arena release version can be downloaded on following pages:
 - [PVP Arena - SpigotMC](https://www.spigotmc.org/resources/pvp-arena.16584/)
 - [Github releases page](https://github.com/Eredrim/pvparena/releases)
 
-Development builds (experimental) can be downloaded on Jenkins:
-- [Jenkins dev builds](https://ci.craftyn.com/view/Spigot%20PVP%20Arena/)
+Development builds (experimental) can be downloaded on our discord:
+- [Discord server](https://discord.gg/a8NhSsXKVQ) (channel #dev-builds)
 
 ***
 
@@ -84,7 +84,7 @@ Place PVP Arena `.jar` file in the plugin repository of your server and restart.
 
 You can contact us to ask your questions or just discuss, you can go here:
 -  [Spigot Forums](https://www.spigotmc.org/threads/pvp-arena.113406/)
--  [Discord server](https://discord.gg/43nZYXZ)
+-  [Discord server](https://discord.gg/a8NhSsXKVQ)
 
 To report issues and make suggestion, please use our [Github issues page](https://github.com/Eredrim/pvparena/issues).
 

From ec9120d7f1540ca003a3680fa10faefc01676e34 Mon Sep 17 00:00:00 2001
From: Ffaen 
Date: Mon, 22 Feb 2021 21:29:42 +0000
Subject: [PATCH 109/115] Fix discord ci notifications on multiline messages

---
 .github/workflows/deploy-snapshot.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/deploy-snapshot.yml b/.github/workflows/deploy-snapshot.yml
index 33cb6b638..585220e2f 100644
--- a/.github/workflows/deploy-snapshot.yml
+++ b/.github/workflows/deploy-snapshot.yml
@@ -44,10 +44,10 @@ jobs:
         env:
           MAVEN_USERNAME: ${{ secrets.MVN_USER }}
           MAVEN_PASSWORD: ${{ secrets.MVN_PASSWORD }}
-          
+
       - name: Post discord notification
         run: |
-          commits="${{ join(github.event.commits.*.message, '\n - ') }}"
+          commits=`echo "${{ join(github.event.commits.*.message, '\n - ') }}" | tr '\n' ' '`
           avatar_url=https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
           bot_username="Build notification"
           payload_json='{ "username": "'$bot_username'", "avatar_url": "'$avatar_url'", "content": "A new dev build of PVP arena is available! Download it by saving the attached file.", "embeds": [{"description": ":spiral_note_pad: **New commits:**\n\n - '$commits'"}] }'

From d19c8bb6bd491ebbd209e22e6520797dfc5a3ac9 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Thu, 25 Feb 2021 22:51:34 +0100
Subject: [PATCH 110/115] 1.15.2 - fix arenaclass command restrictions

---
 .../pvparena/commands/PAG_Arenaclass.java     | 44 +++++++++++--------
 1 file changed, 25 insertions(+), 19 deletions(-)

diff --git a/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java b/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java
index 8922c380d..429ff74db 100644
--- a/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java
+++ b/src/net/slipcor/pvparena/commands/PAG_Arenaclass.java
@@ -22,6 +22,8 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import static java.util.Arrays.asList;
+import static net.slipcor.pvparena.arena.ArenaPlayer.Status.FIGHT;
 import static net.slipcor.pvparena.arena.ArenaPlayer.Status.LOUNGE;
 
 /**
@@ -48,18 +50,6 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
             return;
         }
 
-        if (args.length < 1) {
-            Set classes = new TreeSet<>();
-            for (ArenaClass ac : arena.getClasses()) {
-                if (ac.getName().equals("custom")) {
-                    continue;
-                }
-                classes.add(ChatColor.GREEN + ac.getName() + ChatColor.WHITE);
-            }
-            arena.msg(sender, Language.parse(arena, MSG.CLASS_LIST, StringParser.joinSet(classes, ", ")));
-            return;
-        }
-
         if (!(sender instanceof Player)) {
             Arena.pmsg(sender, Language.parse(arena, MSG.ERROR_ONLY_PLAYERS));
             return;
@@ -67,8 +57,23 @@ public void commit(final Arena arena, final CommandSender sender, final String[]
 
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(sender.getName());
 
-        // Player can change arena class only in lounge or with ingameClassSwith parameter set to true
-        if(aPlayer.getStatus() != LOUNGE && !arena.getArenaConfig().getBoolean(CFG.USES_INGAMECLASSSWITCH)) {
+        ArenaPlayer.Status pStatus = aPlayer.getStatus();
+
+        // Player can change arena class only in lounge or in fight with ingameClassSwith parameter set to true
+        if(!arena.equals(aPlayer.getArena()) || !asList(LOUNGE, FIGHT).contains(pStatus) ||
+                (pStatus == FIGHT && !arena.getArenaConfig().getBoolean(CFG.USES_INGAMECLASSSWITCH))) {
+            return;
+        }
+
+        if (args.length < 1 || "custom".equalsIgnoreCase(args[0])) {
+            Set classes = new TreeSet<>();
+            for (ArenaClass ac : arena.getClasses()) {
+                if ("custom".equalsIgnoreCase(ac.getName())) {
+                    continue;
+                }
+                classes.add(ChatColor.GREEN + ac.getName() + ChatColor.WHITE);
+            }
+            arena.msg(sender, Language.parse(arena, MSG.CLASS_LIST, StringParser.joinSet(classes, ", ")));
             return;
         }
 
@@ -158,12 +163,13 @@ public List getShort() {
     @Override
     public CommandTree getSubs(final Arena arena) {
         final CommandTree result = new CommandTree<>(null);
-        if (arena == null) {
-            return result;
-        }
-        for (final ArenaClass aClass : arena.getClasses()) {
-            result.define(new String[]{aClass.getName()});
+
+        if (arena != null) {
+            arena.getClasses().stream()
+                    .filter(aClass -> !"custom".equalsIgnoreCase(aClass.getName()))
+                    .forEach(aClass -> result.define(new String[]{aClass.getName()}));
         }
+
         return result;
     }
 }

From a2ad45da8100bf2d206469dcb423e0b41fb2c0dc Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Sat, 6 Mar 2021 11:01:58 +0100
Subject: [PATCH 111/115] fix #79 Goal Sabotage is broken

---
 lang/lang_en.yml                              |   4 +-
 lang/lang_es-es.yml                           |   4 +-
 lang/lang_fr.yml                              |   5 +-
 lang/lang_ru.yml                              |   2 +-
 src/net/slipcor/pvparena/arena/ArenaTeam.java |  10 +-
 src/net/slipcor/pvparena/core/Language.java   |   5 +-
 .../slipcor/pvparena/goals/GoalSabotage.java  | 241 ++++++++++--------
 7 files changed, 152 insertions(+), 119 deletions(-)

diff --git a/lang/lang_en.yml b/lang/lang_en.yml
index e65ae4662..02d6902f2 100644
--- a/lang/lang_en.yml
+++ b/lang/lang_en.yml
@@ -300,7 +300,9 @@ nulang:
       tntignite: '%1% ignited the TNT of team %2%!'
       set: 'TNT set: %1%'
       toset: 'TNT to set: %1%'
-      youtnt: You now carry the sabotage materials!'
+      noselfdestroy: 'You can not ignite your own TNT!'
+      youtnt: 'You now carry the sabotage tool!'
+      notgooditem: 'You need sabotage tool to ignite the TNT.'
     tank:
       tankdown: The tank is down!
       tankmode: TANK MODE! Everyone kill %1%, the tank!
diff --git a/lang/lang_es-es.yml b/lang/lang_es-es.yml
index a0cc90fd8..637319c97 100644
--- a/lang/lang_es-es.yml
+++ b/lang/lang_es-es.yml
@@ -248,7 +248,7 @@ nulang:
       tntignite: '%1% encendió la TNT del Equipo %2%!'
       set: 'TNT añadida: %1%'
       toset: 'TNT por añadir: %1%'
-      youtnt: ¡Estas llevando los materiales de Sabotage!'
+      youtnt: '¡Estas llevando los materiales de Sabotage!'
     tank:
       tankdown: ¡El Tanque esta muerto!
       tankmode: Todos a matar a %1% ¡Él/Ella es el Tanque!
@@ -561,4 +561,4 @@ lang:
     Arenas Disponibles: %2%'
 log:
   tagapi: ¡Enganchando en la TagAPI!
-version: 0.9.0.0
\ No newline at end of file
+version: 0.9.0.0
diff --git a/lang/lang_fr.yml b/lang/lang_fr.yml
index dbe002ee7..d68a0aa4d 100644
--- a/lang/lang_fr.yml
+++ b/lang/lang_fr.yml
@@ -318,8 +318,9 @@ nulang:
       tntignite: '%1% a allumé la TNT de l''équipe %2% !'
       set: 'TNT configurée: %1%'
       toset: 'TNT a configurer: %1%'
-      youcannotselfdestroy: You can not ignite your own TNT!'
-      youtnt: Vous portez maintenant le matériel de sabotage !'
+      noselfdestroy: 'Vous ne pouvez pas faire exploser votre TNT!'
+      youtnt: 'Vous portez maintenant l''outil de sabotage !'
+      notgooditem: 'Vous avez besoin de l''outil de sabotage pour allumer la TNT.'
     tank:
       tankdown: Le tank est H.S. !
       tankmode: MODE TANK ! Tous le monde doit tuer %1%, le tank !
diff --git a/lang/lang_ru.yml b/lang/lang_ru.yml
index 1d3f3cc12..93737de63 100644
--- a/lang/lang_ru.yml
+++ b/lang/lang_ru.yml
@@ -234,7 +234,7 @@ nulang:
       tntignite: '%1% подожгли TNT команды %2%!'
       set: 'TNT выбрана: %1%'
       toset: 'TNT для выбора: %1%'
-      youtnt: У вас есть TNT для сабботажа!'
+      youtnt: 'У вас есть TNT для сабботажа!'
     tank:
       tankdown: Танк убит!
       tankmode: Режим танка! Все должны убить %1%, он танк!
diff --git a/src/net/slipcor/pvparena/arena/ArenaTeam.java b/src/net/slipcor/pvparena/arena/ArenaTeam.java
index 3c6a35eb6..d5d48c1d3 100644
--- a/src/net/slipcor/pvparena/arena/ArenaTeam.java
+++ b/src/net/slipcor/pvparena/arena/ArenaTeam.java
@@ -125,4 +125,12 @@ public boolean isEveryoneReady() {
     public void remove(final ArenaPlayer player) {
         players.remove(player);
     }
-}
\ No newline at end of file
+
+    @Override
+    public String toString() {
+        return "ArenaTeam{" +
+                "color=" + this.color +
+                ", name='" + this.name + '\'' +
+                '}';
+    }
+}
diff --git a/src/net/slipcor/pvparena/core/Language.java b/src/net/slipcor/pvparena/core/Language.java
index 09fbccf22..f48c20caa 100644
--- a/src/net/slipcor/pvparena/core/Language.java
+++ b/src/net/slipcor/pvparena/core/Language.java
@@ -531,8 +531,9 @@ public enum MSG {
         GOAL_SABOTAGE_IGNITED("nulang.goal.sabotage.tntignite", "%1% ignited the TNT of team %2%!"),
         GOAL_SABOTAGE_SETTNT("nulang.goal.sabotage.set", "TNT set: %1%"),
         GOAL_SABOTAGE_TOSETTNT("nulang.goal.sabotage.toset", "TNT to set: %1%"),
-        GOAL_SABOTAGE_YOUCANNOTSELFDESTROY("nulang.goal.sabotage.youcannotselfdestroy", "You can not ignite your own TNT!'"),
-        GOAL_SABOTAGE_YOUTNT("nulang.goal.sabotage.youtnt", "You now carry the sabotage materials!'"),
+        GOAL_SABOTAGE_NOSELFDESTROY("nulang.goal.sabotage.noselfdestroy", "You can not ignite your own TNT!"),
+        GOAL_SABOTAGE_NOTGOODITEM("nulang.goal.sabotage.notgooditem", "You need sabotage tool to ignite the TNT."),
+        GOAL_SABOTAGE_YOUTNT("nulang.goal.sabotage.youtnt", "You now carry the sabotage tool."),
 
         GOAL_TANK_TANKDOWN("nulang.goal.tank.tankdown", "The tank is down!"),
         GOAL_TANK_TANKMODE("nulang.goal.tank.tankmode", "TANK MODE! Everyone kill %1%, the tank!"),
diff --git a/src/net/slipcor/pvparena/goals/GoalSabotage.java b/src/net/slipcor/pvparena/goals/GoalSabotage.java
index 81e09ee96..8a6d71b59 100644
--- a/src/net/slipcor/pvparena/goals/GoalSabotage.java
+++ b/src/net/slipcor/pvparena/goals/GoalSabotage.java
@@ -19,9 +19,7 @@
 import net.slipcor.pvparena.managers.SpawnManager;
 import net.slipcor.pvparena.managers.StatisticsManager.Type;
 import net.slipcor.pvparena.runnables.EndRunnable;
-import org.bukkit.Bukkit;
-import org.bukkit.ChatColor;
-import org.bukkit.Material;
+import org.bukkit.*;
 import org.bukkit.block.Block;
 import org.bukkit.command.CommandSender;
 import org.bukkit.configuration.file.YamlConfiguration;
@@ -121,66 +119,100 @@ public PACheck checkInteract(final PACheck res, final Player player, final Block
         if (block == null || res.getPriority() > PRIORITY) {
             return res;
         }
-        arena.getDebugger().i("checking interact", player);
+        this.arena.getDebugger().i("checking interact", player);
 
         if (block.getType() != Material.TNT) {
-            arena.getDebugger().i("block, but not flag", player);
+            this.arena.getDebugger().i("block, but not flag", player);
             return res;
         }
-        arena.getDebugger().i("flag click!", player);
-
-        if (player.getEquipment().getItemInMainHand() == null
-                || player.getEquipment().getItemInMainHand().getType() != Material.FLINT_AND_STEEL) {
-            arena.getDebugger().i("block, but no sabotage items", player);
-            return res;
-        }
-
+        this.arena.getDebugger().i("tnt clicked. Checking if it's a flag", player);
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
-
         final ArenaTeam pTeam = aPlayer.getArenaTeam();
+
         if (pTeam == null) {
+            this.arena.getDebugger().i("Player is not in team. Cancelled", player);
             return res;
         }
+
         Vector vFlag = null;
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             final String aTeam = team.getName();
-            if (team.getTeamMembers().size() < 1) {
+            if (team.getTeamMembers().isEmpty()) {
                 continue; // dont check for inactive teams
             }
-            arena.getDebugger().i("checking for tnt of team " + aTeam, player);
+            this.arena.getDebugger().i("checking for tnt of team " + aTeam, player);
             Vector vLoc = block.getLocation().toVector();
-            arena.getDebugger().i("block: " + vLoc, player);
-            if (!SpawnManager.getBlocksStartingWith(arena, aTeam + "tnt").isEmpty()) {
+            this.arena.getDebugger().i("block: " + vLoc, player);
+            if (!SpawnManager.getBlocksStartingWith(this.arena, aTeam + "tnt").isEmpty()) {
+                vFlag = SpawnManager
+                        .getBlockNearest(
+                                SpawnManager.getBlocksStartingWith(this.arena, aTeam + "tnt"),
+                                new PABlockLocation(player.getLocation()))
+                        .toLocation().toVector();
+            }
+
+            if (vFlag != null && vLoc.distance(vFlag) < 2) {
+                this.arena.getDebugger().i("flag found!", player);
+                this.arena.getDebugger().i("vFlag: " + vFlag, player);
+
+                res.setPriority(this, PRIORITY);
+            }
+        }
+        return res;
+    }
+
+    @Override
+    public void commitInteract(final Player player, final Block clickedBlock) {
+        final ArenaPlayer arenaPlayer = ArenaPlayer.parsePlayer(player.getName());
+        final ArenaTeam playerTeam = arenaPlayer.getArenaTeam();
+
+        if (player.getEquipment().getItemInMainHand().getType() == Material.AIR
+                || player.getEquipment().getItemInMainHand().getType() != Material.FLINT_AND_STEEL) {
+            this.arena.getDebugger().i("block, but no sabotage items", player);
+            this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_SABOTAGE_NOTGOODITEM));
+            return;
+        }
+
+        Vector vFlag = null;
+        for (final ArenaTeam team : this.arena.getTeams()) {
+            final String aTeam = team.getName();
+            if (team.getTeamMembers().isEmpty()) {
+                continue; // dont check for inactive teams
+            }
+            this.arena.getDebugger().i("checking for tnt of team " + aTeam, player);
+            Vector vLoc = clickedBlock.getLocation().toVector();
+            this.arena.getDebugger().i("block: " + vLoc, player);
+            if (!SpawnManager.getBlocksStartingWith(this.arena, aTeam + "tnt").isEmpty()) {
                 vFlag = SpawnManager
                         .getBlockNearest(
-                                SpawnManager.getBlocksStartingWith(arena, aTeam + "tnt"),
+                                SpawnManager.getBlocksStartingWith(this.arena, aTeam + "tnt"),
                                 new PABlockLocation(player.getLocation()))
                         .toLocation().toVector();
             }
 
             if (vFlag != null && vLoc.distance(vFlag) < 2) {
-                arena.getDebugger().i("flag found!", player);
-                arena.getDebugger().i("vFlag: " + vFlag, player);
+                this.arena.getDebugger().i("flag found!", player);
+                this.arena.getDebugger().i("vFlag: " + vFlag, player);
+
+                this.arena.getDebugger().i("aTeam: " + aTeam + " pTeam: " + playerTeam);
 
-                if (aTeam.equals(pTeam.getName())) {
-                    res.setError(this, Language.parse(MSG.GOAL_SABOTAGE_YOUCANNOTSELFDESTROY));
+                if (aTeam.equals(playerTeam.getName())) {
+                    this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_SABOTAGE_NOSELFDESTROY));
                     continue;
                 }
 
-                arena.broadcast(Language.parse(arena, MSG.GOAL_SABOTAGE_IGNITED,
-                        pTeam.colorizePlayer(player) + ChatColor.YELLOW,
+                this.arena.broadcast(Language.parse(this.arena, MSG.GOAL_SABOTAGE_IGNITED,
+                        playerTeam.colorizePlayer(player) + ChatColor.YELLOW,
                         team.getColoredName() + ChatColor.YELLOW));
 
-                final PAGoalEvent gEvent = new PAGoalEvent(arena, this, "trigger:" + player.getName());
+                final PAGoalEvent gEvent = new PAGoalEvent(this.arena, this, "trigger:" + player.getName());
                 Bukkit.getPluginManager().callEvent(gEvent);
                 takeFlag(team.getName(), true,
-                        new PABlockLocation(block.getLocation()));
-                res.setPriority(this, PRIORITY);
-                return res;
+                        new PABlockLocation(clickedBlock.getLocation()));
+
+                break;
             }
         }
-
-        return res;
     }
 
     @Override
@@ -189,12 +221,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        final int maxPlayers = arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
-        final int maxTeamPlayers = arena.getArenaConfig().getInt(
+        final int maxPlayers = this.arena.getArenaConfig().getInt(CFG.READY_MAXPLAYERS);
+        final int maxTeamPlayers = this.arena.getArenaConfig().getInt(
                 CFG.READY_MAXTEAMPLAYERS);
 
-        if (maxPlayers > 0 && arena.getFighters().size() >= maxPlayers) {
-            res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_ARENA_FULL));
+        if (maxPlayers > 0 && this.arena.getFighters().size() >= maxPlayers) {
+            res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_ARENA_FULL));
             return res;
         }
 
@@ -202,12 +234,12 @@ public PACheck checkJoin(final CommandSender sender, final PACheck res, final St
             return res;
         }
 
-        if (!arena.isFreeForAll()) {
-            final ArenaTeam team = arena.getTeam(args[0]);
+        if (!this.arena.isFreeForAll()) {
+            final ArenaTeam team = this.arena.getTeam(args[0]);
 
             if (team != null && maxTeamPlayers > 0
                     && team.getTeamMembers().size() >= maxTeamPlayers) {
-                res.setError(this, Language.parse(arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
+                res.setError(this, Language.parse(this.arena, MSG.ERROR_JOIN_TEAM_FULL, team.getName()));
                 return res;
             }
         }
@@ -228,7 +260,7 @@ public PACheck checkSetBlock(final PACheck res, final Player player, final Block
         }
 
         if (!PVPArena.hasAdminPerms(player)
-                && !PVPArena.hasCreatePerms(player, arena)) {
+                && !PVPArena.hasCreatePerms(player, this.arena)) {
             return res;
         }
         res.setPriority(this, PRIORITY); // success :)
@@ -263,12 +295,8 @@ private void commit(final Arena arena, final String sTeam) {
             }
         }
         for (final ArenaTeam team : arena.getTeams()) {
-            for (final ArenaPlayer ap : team.getTeamMembers()) {
-                if (ap.getStatus() != Status.FIGHT) {
-                    continue;
-                }
+            if (team.getTeamMembers().stream().anyMatch(ap -> ap.getStatus() == Status.FIGHT)) {
                 winteam = team.getName();
-                break;
             }
         }
 
@@ -293,14 +321,14 @@ private void commit(final Arena arena, final String sTeam) {
     @Override
     public void commitCommand(final CommandSender sender, final String[] args) {
         if (args[0].contains("tnt")) {
-            for (final ArenaTeam team : arena.getTeams()) {
+            for (final ArenaTeam team : this.arena.getTeams()) {
                 final String sTeam = team.getName();
                 if (args[0].contains(sTeam + "tnt")) {
-                    flagName = args[0];
-                    PAA_Region.activeSelections.put(sender.getName(), arena);
+                    this.flagName = args[0];
+                    PAA_Region.activeSelections.put(sender.getName(), this.arena);
 
-                    arena.msg(sender, Language.parse(arena,
-                            MSG.GOAL_SABOTAGE_TOSETTNT, flagName));
+                    this.arena.msg(sender, Language.parse(this.arena,
+                            MSG.GOAL_SABOTAGE_TOSETTNT, this.flagName));
                 }
             }
         }
@@ -308,15 +336,15 @@ public void commitCommand(final CommandSender sender, final String[] args) {
 
     @Override
     public void commitEnd(final boolean force) {
-        if (arena.realEndRunner != null) {
-            arena.getDebugger().i("[SABOTAGE] already ending");
+        if (this.arena.realEndRunner != null) {
+            this.arena.getDebugger().i("[SABOTAGE] already ending");
             return;
         }
-        arena.getDebugger().i("[SABOTAGE]");
+        this.arena.getDebugger().i("[SABOTAGE]");
 
         ArenaTeam aTeam = null;
 
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             for (final ArenaPlayer ap : team.getTeamMembers()) {
                 if (ap.getStatus() == Status.FIGHT) {
                     aTeam = team;
@@ -327,43 +355,39 @@ public void commitEnd(final boolean force) {
 
         if (aTeam != null && !force) {
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+                    this.arena,
+                    Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                             + aTeam.getName() + ChatColor.YELLOW), "END");
             ArenaModuleManager.announce(
-                    arena,
-                    Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+                    this.arena,
+                    Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                             + aTeam.getName() + ChatColor.YELLOW), "WINNER");
-            arena.broadcast(Language.parse(arena, MSG.TEAM_HAS_WON, aTeam.getColor()
+            this.arena.broadcast(Language.parse(this.arena, MSG.TEAM_HAS_WON, aTeam.getColor()
                     + aTeam.getName() + ChatColor.YELLOW));
         }
 
-        if (ArenaModuleManager.commitEnd(arena, aTeam)) {
+        if (ArenaModuleManager.commitEnd(this.arena, aTeam)) {
             return;
         }
-        new EndRunnable(arena, arena.getArenaConfig().getInt(
+        new EndRunnable(this.arena, this.arena.getArenaConfig().getInt(
                 CFG.TIME_ENDCOUNTDOWN));
     }
 
-    @Override
-    public void commitInteract(final Player player, final Block clickedBlock) {
-    }
-
     @Override
     public boolean commitSetFlag(final Player player, final Block block) {
 
-        arena.getDebugger().i("trying to set a tnt", player);
+        this.arena.getDebugger().i("trying to set a tnt", player);
 
         // command : /pa redtnt1
         // location: red1tnt:
 
-        SpawnManager.setBlock(arena, new PABlockLocation(block.getLocation()),
-                flagName);
+        SpawnManager.setBlock(this.arena, new PABlockLocation(block.getLocation()),
+                this.flagName);
 
-        arena.msg(player, Language.parse(arena, MSG.GOAL_SABOTAGE_SETTNT, flagName));
+        this.arena.msg(player, Language.parse(this.arena, MSG.GOAL_SABOTAGE_SETTNT, this.flagName));
 
         PAA_Region.activeSelections.remove(player.getName());
-        flagName = "";
+        this.flagName = "";
         return true;
     }
 
@@ -377,7 +401,7 @@ public void disconnect(final ArenaPlayer aPlayer) {
 
         final String flag = getHeldFlagTeam(aPlayer.getName());
         if (flag != null) {
-            final ArenaTeam flagTeam = arena.getTeam(flag);
+            final ArenaTeam flagTeam = this.arena.getTeam(flag);
             getFlagMap().remove(flag);
             distributeFlag(aPlayer, flagTeam);
         }
@@ -389,7 +413,7 @@ private void distributeFlag(final ArenaPlayer player, final ArenaTeam team) {
         int pos = new Random().nextInt(players.size());
 
         for (final ArenaPlayer ap : players) {
-            arena.getDebugger().i("distributing sabotage: " + ap.getName(), ap.getName());
+            this.arena.getDebugger().i("distributing sabotage: " + ap.getName(), ap.getName());
             if (ap.equals(player)) {
                 continue;
             }
@@ -397,7 +421,7 @@ private void distributeFlag(final ArenaPlayer player, final ArenaTeam team) {
                 getFlagMap().put(team.getName(), ap.getName());
                 ap.get().getInventory()
                         .addItem(new ItemStack(Material.FLINT_AND_STEEL, 1));
-                arena.msg(ap.get(), Language.parse(arena, MSG.GOAL_SABOTAGE_YOUTNT));
+                this.arena.msg(ap.get(), Language.parse(this.arena, MSG.GOAL_SABOTAGE_YOUTNT));
                 return;
             }
         }
@@ -408,9 +432,9 @@ private String getHeldFlagTeam(final String player) {
             return null;
         }
 
-        arena.getDebugger().i("getting held TNT of player " + player, player);
+        this.arena.getDebugger().i("getting held TNT of player " + player, player);
         for (final String sTeam : getFlagMap().keySet()) {
-            arena.getDebugger().i("team " + sTeam + "'s sabotage is carried by "
+            this.arena.getDebugger().i("team " + sTeam + "'s sabotage is carried by "
                     + getFlagMap().get(sTeam) + "s hands", player);
             if (player.equals(getFlagMap().get(sTeam))) {
                 return sTeam;
@@ -420,31 +444,31 @@ private String getHeldFlagTeam(final String player) {
     }
 
     private Map getFlagMap() {
-        if (teamFlags == null) {
-            teamFlags = new HashMap<>();
+        if (this.teamFlags == null) {
+            this.teamFlags = new HashMap<>();
         }
-        return teamFlags;
+        return this.teamFlags;
     }
 
     private Map getTNTmap() {
-        if (teamTNTs == null) {
-            teamTNTs = new HashMap<>();
+        if (this.teamTNTs == null) {
+            this.teamTNTs = new HashMap<>();
         }
-        return teamTNTs;
+        return this.teamTNTs;
     }
 
     @Override
     public boolean hasSpawn(final String string) {
-        for (final String teamName : arena.getTeamNames()) {
-            if (string.toLowerCase().equals(teamName.toLowerCase() + "tnt")) {
+        for (final String teamName : this.arena.getTeamNames()) {
+            if (string.equalsIgnoreCase(teamName + "tnt")) {
                 return true;
             }
             if (string.toLowerCase().startsWith(
                     teamName.toLowerCase() + "spawn")) {
                 return true;
             }
-            if (arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
-                for (final ArenaClass aClass : arena.getClasses()) {
+            if (this.arena.getArenaConfig().getBoolean(CFG.GENERAL_CLASSSPAWN)) {
+                for (final ArenaClass aClass : this.arena.getClasses()) {
                     if (string.toLowerCase().startsWith(teamName.toLowerCase() +
                             aClass.getName().toLowerCase() + "spawn")) {
                         return true;
@@ -460,10 +484,10 @@ public void initate(final Player player) {
         final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
         final ArenaTeam team = aPlayer.getArenaTeam();
         takeFlag(team.getName(), false,
-                SpawnManager.getBlockByExactName(arena, team.getName() + "tnt"));
+                SpawnManager.getBlockByExactName(this.arena, team.getName() + "tnt"));
         //TODO: allow multiple TNTs?
         if (!getFlagMap().containsKey(team.getName())) {
-            arena.getDebugger().i("adding team " + team.getName(), player);
+            this.arena.getDebugger().i("adding team " + team.getName(), player);
             distributeFlag(null, team);
         }
     }
@@ -476,7 +500,7 @@ public boolean isInternal() {
     @Override
     public void parsePlayerDeath(final Player player, final EntityDamageEvent event) {
         final String teamName = getHeldFlagTeam(player.getName());
-        final ArenaTeam team = arena.getTeam(teamName);
+        final ArenaTeam team = this.arena.getTeam(teamName);
         if (teamName != null && team != null) {
             final ArenaPlayer aPlayer = ArenaPlayer.parsePlayer(player.getName());
             getFlagMap().remove(teamName);
@@ -486,14 +510,14 @@ public void parsePlayerDeath(final Player player, final EntityDamageEvent event)
 
     @Override
     public void parseStart() {
-        arena.getDebugger().i("initiating arena");
+        this.arena.getDebugger().i("initiating arena");
         getFlagMap().clear();
-        for (final ArenaTeam team : arena.getTeams()) {
+        for (final ArenaTeam team : this.arena.getTeams()) {
             takeFlag(team.getName(), false,
-                    SpawnManager.getBlockByExactName(arena, team.getName() + "tnt"));
+                    SpawnManager.getBlockByExactName(this.arena, team.getName() + "tnt"));
             // TODO: allow multiple TNTs?
             if (!getFlagMap().containsKey(team.getName())) {
-                arena.getDebugger().i("adding team " + team.getName());
+                this.arena.getDebugger().i("adding team " + team.getName());
                 distributeFlag(null, team);
             }
         }
@@ -510,14 +534,14 @@ public void reset(final boolean force) {
 
     @Override
     public void setDefaults(final YamlConfiguration config) {
-        if (arena.isFreeForAll()) {
+        if (this.arena.isFreeForAll()) {
             return;
         }
         if (config.get("teams.free") != null) {
             config.set("teams", null);
         }
         if (config.get("teams") == null) {
-            arena.getDebugger().i("no teams defined, adding custom red and blue!");
+            this.arena.getDebugger().i("no teams defined, adding custom red and blue!");
             config.addDefault("teams.red", ChatColor.RED.name());
             config.addDefault("teams.blue", ChatColor.BLUE.name());
         }
@@ -531,13 +555,15 @@ public void setDefaults(final YamlConfiguration config) {
      * @param paBlockLocation the location to take/reset
      */
     void takeFlag(final String teamName, final boolean take, final PABlockLocation paBlockLocation) {
+        this.arena.getDebugger().i(String.format("Take flag for team %s, take: %s, location: %s", teamName, take, paBlockLocation.toString()));
         paBlockLocation.toLocation().getBlock()
                 .setType(take ? Material.AIR : Material.TNT);
         if (take) {
             final TNTPrimed tnt = (TNTPrimed) Bukkit.getWorld(
                     paBlockLocation.getWorldName())
                     .spawnEntity(paBlockLocation.toLocation(), EntityType.PRIMED_TNT);
-            getTNTmap().put(arena.getTeam(teamName), tnt);
+
+            getTNTmap().put(this.arena.getTeam(teamName), tnt);
         }
     }
 
@@ -555,24 +581,19 @@ public void onTNTExplode(final EntityExplodeEvent event) {
         final TNTPrimed tnt = (TNTPrimed) event.getEntity();
 
         for (final ArenaTeam team : getTNTmap().keySet()) {
+            this.arena.getDebugger().i(String.format("Checking tnt %s for team %s", tnt.getUniqueId(), team.getName()));
             if (tnt.getUniqueId().equals(getTNTmap().get(team).getUniqueId())) {
                 event.setCancelled(true);
-                tnt.remove();
-                commit(arena, team.getName());
-            }
-        }
-
-        final PABlockLocation tLoc = new PABlockLocation(event.getEntity()
-                .getLocation());
-
-        for (final String sTeam : arena.getTeamNames()) {
-            final Set locs = SpawnManager.getBlocksStartingWith(arena, sTeam + "tnt");
-
-            final PABlockLocation nearest = SpawnManager.getBlockNearest(locs, tLoc);
 
-            if (nearest.getDistanceSquared(tLoc) < 4) {
-                event.setCancelled(true);
-                return;
+                commit(this.arena, team.getName());
+                World world = event.getEntity().getLocation().getWorld();
+                Location location = event.getEntity().getLocation();
+                tnt.remove();
+                world.spawnParticle(Particle.EXPLOSION_LARGE, location.getX(), location.getY() + 1, location.getZ(), 25);
+                world.playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 20, 2);
+                break;
+            } else {
+                this.arena.getDebugger().i(String.format("Tnt  %s is not the team %s tnt. next.", tnt.getUniqueId(), team.getName()));
             }
         }
     }

From 6a42291b5ac44c9146558a1df9e2e3963c60e5dd Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Mon, 29 Mar 2021 22:13:03 +0200
Subject: [PATCH 112/115] v1.15.2 - fix spectators in scoreboard

---
 src/net/slipcor/pvparena/arena/Arena.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/arena/Arena.java b/src/net/slipcor/pvparena/arena/Arena.java
index 53de2f5ed..7aa3a1ea5 100644
--- a/src/net/slipcor/pvparena/arena/Arena.java
+++ b/src/net/slipcor/pvparena/arena/Arena.java
@@ -2333,7 +2333,7 @@ public void updateScoreboards() {
                 if (this.isFreeForAll()) {
                     for (ArenaPlayer ap : this.getEveryone()) {
                         int value = PACheck.handleGetLives(this, ap);
-                        if (value >= 0) {
+                        if (value >= 0 && ap.getStatus() != Status.WATCH) {
                             currentScoreboard.getObjective("lives").getScore(ap.getName()).setScore(value);
                         }
                         Player player = ap.get();

From 437eb5737953d1e8b0098ad601b30a7b5a54ad06 Mon Sep 17 00:00:00 2001
From: Eredrim 
Date: Wed, 31 Mar 2021 22:25:05 +0200
Subject: [PATCH 113/115] v1.15.2 - fix custom potion deserialization & add
 custom color - issue #59

---
 src/net/slipcor/pvparena/core/ItemStackUtils.java | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/net/slipcor/pvparena/core/ItemStackUtils.java b/src/net/slipcor/pvparena/core/ItemStackUtils.java
index 0f7abeec3..87cef1960 100644
--- a/src/net/slipcor/pvparena/core/ItemStackUtils.java
+++ b/src/net/slipcor/pvparena/core/ItemStackUtils.java
@@ -42,7 +42,7 @@ private static boolean isAnHandledMetaType(String metaTypeString) {
      * @return Right "meta-type" value
      */
     private static HandledMetaType getRightMetaType(Collection keySet) {
-        if(keySet.contains("potion-type")) {
+        if(keySet.contains("potion-type") || keySet.contains("custom-effects")) {
             return HandledMetaType.POTION;
         }
         if(keySet.contains("stored-enchants")) {
@@ -102,6 +102,10 @@ public static Map getItemStackMap(ItemStack itemStack) {
                                 .map(PotionEffect::serialize)
                                 .collect(Collectors.toList());
                         metaMap.put("custom-effects", customEffectMeta);
+
+                        if(potionMeta.hasColor()) {
+                            metaMap.put("custom-color", potionMeta.getColor().serialize());
+                        }
                     }
                 }
             }
@@ -148,6 +152,12 @@ private static ItemStack deserialize(Map args) {
                                 .collect(Collectors.toList());
 
                         metaMap.put("custom-effects", effectList);
+
+                        // handle custom-color only if item is a custom potion
+                        if(metaMap.containsKey("custom-color")) {
+                            Color color = Color.deserialize((Map) metaMap.get("custom-color"));
+                            metaMap.put("custom-color", color);
+                        }
                     }
                 }
 

From cb6da9a2004e173e0f9cb2075fcf4727c3e3f246 Mon Sep 17 00:00:00 2001
From: Oruss7 <4788317+Oruss7@users.noreply.github.com>
Date: Mon, 26 Apr 2021 19:49:13 +0200
Subject: [PATCH 114/115] Add tp.death spectator question

---
 doc/faq.md | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/doc/faq.md b/doc/faq.md
index 7ca448298..1585f4211 100644
--- a/doc/faq.md
+++ b/doc/faq.md
@@ -63,6 +63,13 @@ Check dedicated documentation pages to get more information.
 
 
+## Is there a way to automatically put a player into spectator mode on death instead of them having to leave the match and then rejoin as a spectator? + + +Just set `tp.death` to `spectator` in your arena config file (or with [`/pa [arena] set`](commands/set.md) command). + +
+ ## Still have questions? -Don't hesitate to [get in touch](../readme.md#support) with us 😉 \ No newline at end of file +Don't hesitate to [get in touch](../readme.md#support) with us 😉 From 59f8bcf16225466a3bcfdc4245ecd328e58e2fb9 Mon Sep 17 00:00:00 2001 From: Oruss7 <4788317+Oruss7@users.noreply.github.com> Date: Wed, 12 May 2021 18:50:52 +0200 Subject: [PATCH 115/115] fix NPE on painting break --- .../slipcor/pvparena/listeners/BlockListener.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/net/slipcor/pvparena/listeners/BlockListener.java b/src/net/slipcor/pvparena/listeners/BlockListener.java index 45153c49b..f7ad96b45 100644 --- a/src/net/slipcor/pvparena/listeners/BlockListener.java +++ b/src/net/slipcor/pvparena/listeners/BlockListener.java @@ -512,11 +512,11 @@ public void onBlockBreak(final HangingBreakEvent event) { return; } if (arena == null) { - DEBUG.i("painting break inside the arena"); - } else { - arena.getDebugger().i("painting break inside the arena"); + DEBUG.i("painting break outside an arena"); + return; } - ArenaModuleManager.onPaintingBreak(arena, event.getEntity(), event - .getEntity().getType()); + + arena.getDebugger().i("painting break inside an arena"); + ArenaModuleManager.onPaintingBreak(arena, event.getEntity(), event.getEntity().getType()); } -} \ No newline at end of file +}