Compare commits

..

122 commits

Author SHA1 Message Date
d46adfd957
Fix custom charts
Probably
2021-02-21 02:15:10 +01:00
12a8ccf3ce
Use bStats for metrics and remove Piwik integration
#4
2021-02-21 01:39:51 +01:00
dcd3ff31db
Fix WorldEdit integration stopping edits
It's been only more than a year, it's fine
2021-02-21 00:04:56 +01:00
e4548069dc
Update dependencies 2020-07-27 16:24:42 +02:00
3f9c2b99f9
Version update 2019-09-21 16:28:47 +02:00
6d5f42b2a5
Added ReflectionStorage (mostly version-independent)
(Started on 2019.08.29.)
This means it supports 1.14.4
It automatically falls back to the previous storage if the newer version is not found
2019-09-21 16:14:58 +02:00
14bdf0ebe0
Updated WorldEdit and WorldGuard to 7.0.0
It doesn't work without them atm because it tries to load a class from them
2019-08-28 23:29:40 +02:00
24ed3393d3
Giving 30 seconds max for the thread
The plugin will wait 30 seconds and if the thread is still alive then it interrupts the thread which should instantly end the loop.
Also other fixes
Also notifying all threads that could wait on the queue, though it should be the only 1 BS thread
2018-10-04 00:34:00 +02:00
cd7b7a550d
Might have fixed the stop delay
The theory is the following: multiple BS threads were created, one for each chunk, which caused long locks. If this isn't the case, I don't know what is.
#2
2018-08-31 17:08:06 +02:00
b84ecf8545
Added conversion in DB 2018-06-30 16:28:32 +02:00
ecaecd4136
Added name to UUID conversion 2018-06-27 21:59:12 +02:00
362d1d823c
Small fixes, ready to go 2018-06-27 17:53:04 +02:00
b8d21657ce
Merge remote-tracking branch 'remotes/origin/spigot-1.9'
# Conflicts:
#	pom.xml
#	src/main/java/de/jaschastarke/minecraft/limitedcreative/FeatureMetrics.java
#	src/main/java/de/jaschastarke/minecraft/limitedcreative/blockstate/worldedit/LCEditSession_LogBlock.java
#	src/main/java/de/jaschastarke/minecraft/limitedcreative/limits/PlayerListener.java
2018-06-27 13:42:29 +02:00
d7e4eafc4d
Fixed thread stop & metrics fix
The thread will be restarted automatically after an error
2018-06-27 00:14:09 +02:00
f2af77b9b7
Resolved compile errors, LB removed
LogBlock support removed
2018-06-26 21:28:36 +02:00
pickernickel
8c1240cc24 Use UUID instead of player name. 2016-05-23 22:42:52 -05:00
pickernickel
05d37326e0 Circumvented some deprecated API usage. 2016-05-22 04:35:52 -05:00
pickernickel
b2e154be45 Slime block compatibility. 2016-05-18 03:34:19 -05:00
Jascha Starke
8cfc3b7f01 Spigot 1.9 Update 2016-03-02 22:47:46 +01:00
Jascha Starke
1efdf717b5 Incomplete Spectator-Support 2016-03-02 19:57:25 +01:00
Jascha Starke
256f165622 Spectator, chestOpen ^ Inventory
* Support for Spectator-Mode (always gets creative Inventory)
* Prevent Attack across Region borders
* chestOpen now allows Inventory again, to make /inv addons possible
* Placing into creative regions should now be handled again (survival regions may bugged? but no one uses them at all, or?)
2015-05-11 20:15:11 +02:00
Jascha Starke
d010249107 Spigot 1.8: Armor Stand Support (Somehow. Spigot Implementation is Buggy) 2015-04-11 14:09:41 +02:00
Jascha Starke
7b72e1d5cf WorldEdit 6.0 2015-04-11 01:47:40 +02:00
Jascha Starke
87cde8e182 WorldEdit 6.0 2015-04-11 01:36:58 +02:00
Jascha Starke
acb0717644 Spigot 1.8: More deprecation 2015-04-11 00:03:42 +02:00
Jascha Starke
648ef2070e Spigot 1.8.3-Update
+ Moved Metrics
+ Temporary disabled Worldedit-Integration
2015-04-10 23:02:32 +02:00
Jascha Starke
c387bcbf55 Spigot 1.8 compatibility
* 1.8 Spigot API
* 6.0 WorldGuard
2014-12-01 22:18:54 +01:00
Jascha Starke
47fb0e137a Quick-Hack: Disable WorldEdit-Integration for Performance-Reason 2014-01-04 21:03:31 +01:00
Jascha Starke
06e08c630e BlockState Hanging Punch in 1.7.2 2013-12-09 23:07:44 +01:00
Jascha Starke
8a76616969 Config Reload of cached lists 2013-12-09 22:14:17 +01:00
Jascha Starke
8c9be4f1f4 WorldEdit in transaction. (Better WE Performance with BlockState)
A special cookie for LordSaad, yummi.
2013-11-08 11:57:36 +01:00
Jascha Starke
aba6bf354d NPE-Fix for syncronized explosions 2013-11-07 08:43:35 +01:00
Jascha Starke
010c0434c4 Added /lc reload to command list 2013-11-06 09:44:40 +01:00
Jascha Starke
dfb289fdd9 Removed temporary sysouts 2013-11-04 16:45:20 +01:00
Jascha Starke
808b50fb61 CoreProtect WE-Integration support 2013-10-29 13:09:17 +01:00
Jascha Starke
fcb1e92f90 Give blockstate thread more time before warning 2013-10-26 20:33:54 +02:00
Jascha Starke
f545debb97 ItemFrame (Hanging) Handling 2013-10-26 18:19:35 +02:00
Jascha Starke
2477ec8f81 Workaround PlayerInteract with Air Event Bukkit-issue (eye of ender, etc.) 2013-10-26 14:49:26 +02:00
Jascha Starke
a1a041fc36 Add Eye of Ender to default use block 2013-10-26 11:00:41 +02:00
Jascha Starke
135fd5d9f8 Fixed config Defaults 2013-10-21 15:40:33 +02:00
Jascha Starke
31e5d5d6db Version-Number-Increase 2013-10-21 08:58:35 +02:00
Jascha Starke
e060fd359e Removed AuthMe3-Integration on Xephis explicit wish...
.. as everything now is handled by AuthMe without issues
2013-10-21 08:49:42 +02:00
Jascha Starke
175d399384 Give threaded startup 30s before warning about queue size 2013-10-19 18:11:16 +02:00
Jascha Starke
4498d8343f Slimmer BlockState-Database
- Default logSurvival to false
 - "/lcbs cleanup" command to delete survival items, with logSurvival: false

Rename TabCompletion
2013-10-19 16:29:40 +02:00
Jascha Starke
814c848e53 Official md5 LogBlock-Repository 2013-10-17 23:00:42 +02:00
Jascha Starke
57453ffce1 MethodContainer-TabCompletion, README-Update 2013-10-17 21:57:48 +02:00
Jascha Starke
9b3617ecba AuthMe 3.0 Support 2013-10-17 20:29:21 +02:00
Jascha Starke
18b90dedc9 TabCompletion for commands 2013-10-17 16:50:32 +02:00
Jascha Starke
2957233fbf BlockState-DB Migration: Import from CreativeControl
Limit-Config: Remove button/level default
2013-10-15 23:09:28 +02:00
Jascha Starke
9eba342758 Syncronized Update non-cached state fixed 2013-10-15 22:59:35 +02:00
Jascha Starke
65a50d30c0 Release 2.1
- Prevent Drops of Killed Mobs
 - Prevent Minecart-Drops (when TrainCarts is installed)
2013-10-13 23:04:57 +02:00
Jascha Starke
8e3b771d61 Fix of pickup-Permission 2013-10-05 14:16:00 +02:00
Jascha Starke
9275b9b4a5 Module reload fix, Better Thread-Performance-Warning 2013-10-01 16:58:01 +02:00
Jascha Starke
4b345cf880 Use of reworked Module-System. Dependend submodules 2013-10-01 15:57:04 +02:00
Jascha Starke
9061e18db9 Fixed: blockbreak in threaded mode requires cached value... 2013-09-30 19:35:43 +02:00
Jascha Starke
bd83e5b7cd Small Chunk loaded workaround, mabye 2013-09-29 22:29:37 +02:00
Jascha Starke
5fb285d0db Documentation-Update 2013-09-29 15:41:06 +02:00
Jascha Starke
b9e2da1b82 Use of new configuration styles 2013-09-29 13:15:08 +02:00
Jascha Starke
c7abaa7444 Armory load fix
use "current" to set InventoryArmor from ingame command
2013-09-28 23:53:43 +02:00
Jascha Starke
fd3c9da9ff 2 NPE fix 2013-09-28 17:25:06 +02:00
Jascha Starke
6db1664a7e BlockState Migration-Command 2013-09-26 20:29:43 +02:00
Jascha Starke
0a05ac75a4 Handle Fast falling replacement 2013-09-26 11:13:24 +02:00
Jascha Starke
23525692e1 Handle falling Blocks (Sand/Gravel) 2013-09-26 10:02:29 +02:00
Jascha Starke
49b528e352 Annotation instead of pom registration, with Configuration-Default generation 2013-09-25 23:52:43 +02:00
Jascha Starke
ea1921935e Per world disable of BlockState module 2013-09-25 19:25:24 +02:00
Jascha Starke
a704d9bc57 Fix/Reimplement removeDrops 2013-09-25 17:23:09 +02:00
Jascha Starke
f46f183dc5 Infinite Loop fix 2013-09-25 17:07:10 +02:00
Jascha Starke
e32bbbd105 Threaded BlockState DB-Connection 2013-09-25 16:35:41 +02:00
Jascha Starke
7506a7f1c1 ignoreCancelled via annotation 2013-09-24 17:47:02 +02:00
Jascha Starke
775ef40b1a Empty file hint 2013-09-22 14:27:57 +02:00
Jascha Starke
a3ab1fed16 additional debug-message 2013-09-22 13:32:35 +02:00
Jascha Starke
d53929a1b9 BlockState for breaking blocks by Water 2013-09-22 13:02:53 +02:00
Jascha Starke
c2ac988439 Scheduler Debug-Messages 2013-09-22 11:04:09 +02:00
Jascha Starke
c4fffc9059 Merge branch 'master' of ssh://git@github.com/possi/LimitedCreative.git 2013-09-22 00:08:19 +02:00
Jascha Starke
55a9b490a1 AuthMe downloaded repo version 2013-09-22 00:08:09 +02:00
Jascha Starke
1e24c18c6e WorldGuard Repo missing dependency 2013-09-21 23:26:33 +02:00
Jascha Starke
6101a62918 AuthMe correct API-Hook 2013-09-21 23:23:40 +02:00
Jascha Starke
f322468d40 Usage of AttachedBlock CustomEvents to prevent drop of torches and co
Disabled MultiWorld-GameMode-Hook (as MW-GameMode dosn't work at all)
plib 1.3 compatibilty to prevent NPE
Region-Command and Flag-Storage fixes
Creative-World-Suicide fix
2013-09-21 22:12:40 +02:00
Jascha Starke
d8cc4f2412 dow 2013-09-21 10:23:55 +02:00
Jascha Starke
ed809b5b18 Fix: NPE when moving non-saved-survival-state 2013-09-21 10:23:04 +02:00
Jascha Starke
acbe6838b7 Rely on the new inventory blocking, so that placing against chests while crouching is possible 2013-09-19 19:41:10 +02:00
Jascha Starke
2bb077f94f PistonGlitch Fixes
Ticket #147
2013-09-19 17:17:05 +02:00
Jascha Starke
9a6d57f2e2 Better Border-Check for collapsed regions 2013-09-15 18:35:56 +02:00
Jascha Starke
64eda8f1bd CommandBlocker ignore case 2013-09-15 15:04:59 +02:00
Jascha Starke
58742ee775 Permission node description line breaks 2013-09-14 23:10:23 +02:00
Jascha Starke
727b4914f3 Release 2013-09-14 16:25:44 +02:00
Jascha Starke
8e9dcd59f8 Reintegrated AuthMe Inventory-Events 2013-09-14 15:13:53 +02:00
Jascha Starke
57ad7aaa8d Fixed #146 by reverting event priority f*ckup 2013-09-14 14:30:09 +02:00
Jascha Starke
db97f869d7 Ticket #146 (possible fix)
- MultiWorld World GameMode support
 - EventPriority onGameModeChange fix
2013-09-14 13:53:49 +02:00
Jascha Starke
7385478e13 Small-Improvements
- Better .command-Permission documentation
 - JUKEBOX blocked by default
 - ignoreCancelled PlayerInteractEvent
2013-08-29 14:20:57 +02:00
Jascha Starke
b32b0109f0 BlockState-Improvements:
- Performance by using Metadata
 - Explosion checks
 - Disable Survival Database store.
2013-08-29 14:19:59 +02:00
Jascha Starke
23983ea6ad Missing file causing startup error 2013-08-17 00:32:48 +02:00
Jascha Starke
df373ab64c Fixed BlockState-Command documentation 2013-08-12 16:27:02 +02:00
Jascha Starke
77713a64ba plib 1.1 2013-08-12 15:57:02 +02:00
Jascha Starke
4d7507c557 ItemFrame support in BlockState
Reworked DocComments for plib-1.1
2013-08-12 15:50:05 +02:00
Jascha Starke
cdcf18cda5 Added entityInteract-limitation on region border 2013-07-31 14:27:04 +02:00
Jascha Starke
a622d4e405 WorldGaurd Typo-Fix (/lcr command) 2013-07-30 21:34:22 +02:00
Jascha Starke
93ee72e2c6 Fixed maxFallingHeight-Configuration Setting and added -1 to disable 2013-07-30 08:44:22 +02:00
Jascha Starke
aab42fcdca German Translation
and en. Localization fix
2013-07-29 12:25:24 +02:00
Jascha Starke
a33c4d4c51 New Inventory-Blocking, that doesn't require horse blocking any longer.
Can be bypassed with a dynamic permission (see http://dev.bukkit.org/bukkit-plugins/limited-creative/pages/permissions/#w-additional-dynamic-permissions)
2013-07-29 10:22:39 +02:00
Jascha Starke
58a092267a Riding animals buck off the player now on gamemode change 2013-07-29 08:47:25 +02:00
Jascha Starke
5d7dee727b Reworked DocComments for Better LineEnding parsing 2013-07-29 00:12:47 +02:00
Jascha Starke
cf028eb2dd Added XP-removing on drop prevention 2013-07-28 21:13:14 +02:00
Jascha Starke
b823dc24a1 BlockState-Command
BlockState loading fix
BlockState piston bypass prevention
Loading without WorldEdit dependency fix
2013-07-28 20:23:43 +02:00
Jascha Starke
86eeceb450 Added MCStats Metrics. Can be disabled together with Piwik,
or like descriped at http://mcstats.org/learn-more/
2013-07-28 11:07:27 +02:00
Jascha Starke
e7a794add7 WorldEdit Intergration for remember BlockState
(Should work with LogBlock, untested)
2013-07-27 17:44:30 +02:00
Jascha Starke
614a3e9007 Readded BlockState-Permission to plugin.yml 2013-07-27 00:28:59 +02:00
Jascha Starke
61cb058575 BlockState: Module Load fixed
BlockState: Config default disabled
2013-07-27 00:25:39 +02:00
Jascha Starke
1ef29ff8e6 Readded EXPERIMENTAL BlockState Feature with reworked DB. Merged from
branch 'remember_blocks'
2013-07-27 00:01:26 +02:00
Jascha Starke
54a0eb2224 Fixed Possible config updrade NPE 2013-07-26 18:21:26 +02:00
Jascha Starke
3cc2d3999f Fixed bukkit-version difference to plib 2013-07-26 17:34:16 +02:00
Jascha Starke
40233364aa Fixed ItemStack as Creative-Armor 2013-07-26 17:02:01 +02:00
Jascha Starke
52dea4a793 Horse added to default config 2013-07-23 15:22:46 +02:00
Jascha Starke
0f2a978f75 New Limitation Features
to fix: #108/#121
Fixed #125
2013-07-02 11:43:13 +02:00
Jascha Starke
a013db180e removed block perm state 2013-04-27 11:15:41 +02:00
Jascha Starke
328929fb3f Removed not usable experimental feature 2013-04-20 10:35:53 +02:00
Jascha Starke
3a4f8a844b Default disabled experimental broken feature 2013-04-20 10:11:00 +02:00
Jascha Starke
73285de3c7 BlockState config description 2013-04-01 22:47:38 +02:00
Jascha Starke
d7280f6d69 Fix for #110 (NPE for empty BlackList-String-Entry) 2013-04-01 22:42:21 +02:00
Jascha Starke
76147c3c52 Merge branch 'remember_blocks' 2013-04-01 22:20:31 +02:00
Jascha Starke
7be648f552 Late loading/unloading of conflicting/depended plugins now disables the related modules
The opposite (if dependency are fixed again) is not implemented. A full server reload is required to re-enable the modules. (A reload with PluginManager works to, but is not recommended)
2013-03-29 11:14:10 +01:00
Jascha Starke
467653891f reverted chest recognition for beacon and enderchest 2013-03-28 09:46:03 +01:00
92 changed files with 5165 additions and 1362 deletions

4
.gitignore vendored
View file

@ -1,11 +1,13 @@
/bin
# Eclipse stuff
# IDE stuff
/.project
/.classpath
/.settings
/.buildpath
/.checkstyle
/.idea
/LimitedCreative.iml
# maven
/target

View file

@ -10,16 +10,19 @@ Required dependencies
Dependencies for optional integrations
--------------------------------------
* [WorldGuard](https://github.com/sk89q/worldguard)
* [xAuth](http://dev.bukkit.org/server-mods/xauth/)
* [AuthMe](http://dev.bukkit.org/server-mods/authme-reloaded/) ([GitSource](https://github.com/Multiplayer-italia/AuthMe-Reloaded))
* [Multiverse-Core](http://dev.bukkit.org/server-mods/multiverse-core/)
* [WorldGuard](http://dev.bukkit.org/bukkit-plugins/worldguard/)
* [WorldEdit](http://dev.bukkit.org/bukkit-plugins/worldedit/)
* [xAuth](http://dev.bukkit.org/bukkit-plugins/xauth/)
* [AuthMe](http://dev.bukkit.org/bukkit-plugins/authme-reloaded/)
* [Multiverse-Core](http://dev.bukkit.org/bukkit-plugins/multiverse-core/)
* [Vault](http://dev.bukkit.org/bukkit-plugins/vault/)
* [Multiworld](http://dev.bukkit.org/bukkit-plugins/multiworld-v-2-0/)
* [LogBlock](http://dev.bukkit.org/bukkit-plugins/logblock/)
----
Building
--------
Download and install xAuth and Multiworld into the local `repo` repository with a command like so:
To use Maven packaging
----------------------
For required development snapshots, that aren't found by maven, you have to clone the project and do:
$ mvn install
in the directory of the project
```bash
mvn install:install-file -Dfile=xAuth-2.0.26.jar -Dpackaging=jar -DlocalRepositoryPath=repo -DgroupId=de.luricos.bukkit -DartifactId=xAuth -Dversion=2.0.26
```

View file

@ -1,4 +0,0 @@
- cleanup localize-messages
- region command descriptions
- rework german localization
- fix DocComment formatting for config and permissions

146
pom.xml
View file

@ -1,14 +1,16 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.jaschastarke</groupId>
<artifactId>LimitedCreative</artifactId>
<name>LimitedCreative</name>
<version>2.0-SNAPSHOT</version>
<version>2.5</version>
<url>https://github.com/possi/LimitedCreative</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plib.version>1.0-SNAPSHOT</plib.version>
<plib.version>1.4-SNAPSHOT</plib.version>
<bukkit.version>1.12.2-R0.1-SNAPSHOT</bukkit.version>
</properties>
<scm>
@ -35,20 +37,25 @@
<!-- Possible public Maven Repository, containing LimitedCreative builds and other dependencies without own rep.
like AuthMe, etc.
Supports http only -->
<repository>
<!-- <repository> - offline
<id>de-jas-rep</id>
<url>http://repo.ja-s.de/mvn</url>
</repository> -->
<!-- Local repository for plugins without a repo -->
<repository>
<id>localRepo</id>
<url>file://${project.basedir}/repo</url>
</repository>
<!-- Official (Craft-)Bukkit repository -->
<repository>
<id>bukkit-repo</id>
<url>http://repo.bukkit.org/content/groups/public</url>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<!-- Official WorldGuard and WorldEdit repository -->
<repository>
<id>sk89q-mvn2</id>
<url>http://mvn2.sk89q.com/repo</url>
<url>https://maven.enginehub.org/repo/</url>
</repository>
<!-- Official Multiverse repository -->
<repository>
@ -58,27 +65,73 @@
<!-- Official xAuth repository; it is no good! we keep our own dep-files of it - ->
<repository>
<id>luricos.de-repo</id>
<url>http://repo.luricos.de/bukkit-plugins/</url>
</repository><!- - -->
<url>http://repo.luricos.de/repository/bukkit-plugins/</url>
</repository><!- - It points to dependencies that don't exist anymore -->
<!-- Official LogBlock repository -->
<repository>
<id>md5</id>
<url>http://repo.md-5.net/content/groups/public/</url>
</repository>
<!-- Official AuthMe Reloaded repository -->
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<!-- Official CoreProtect repository -->
<repository>
<id>coreprotect-repo</id>
<url>http://maven.playpro.com/</url>
</repository>
<!-- Official PermissionsEx repository -->
<repository>
<id>pex-repo</id>
<url>https://repo.glaremasters.me/repository/permissionsex/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>de-jas-rep</id>
<url>http://repo.ja-s.de/mvn</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>de.jaschastarke</groupId>
<artifactId>plib</artifactId>
<version>${plib.version}</version>
</dependency>
<dependency>
<!-- http://dl.bukkit.org/ -->
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkit.version}</version>
</dependency>
<dependency>
<!-- http://dl.bukkit.org/ -->
<groupId>org.bukkit.</groupId> <!-- Needed for WE integration -->
<artifactId>bukkit</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/server-mods/worldguard/ -->
<groupId>com.sk89q</groupId>
<artifactId>worldguard</artifactId>
<version>5.7.3</version>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.0</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/server-mods/worldguard/ -->
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.0.0</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/server-mods/authme-reloaded/ -->
<groupId>uk.org.whoami</groupId>
<groupId>fr.xephi</groupId>
<artifactId>authme</artifactId>
<version>2.7.12</version>
<version>5.6.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/server-mods/multiverse-core/ -->
@ -86,12 +139,36 @@
<artifactId>Multiverse-Core</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/bukkit-plugins/multiworld-v-2-0/ -->
<groupId>multiworld</groupId>
<artifactId>multiworld</artifactId>
<version>5.2.8</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/server-mods/xauth/ -->
<groupId>com.cypherx</groupId>
<artifactId>xauth</artifactId>
<groupId>de.luricos.bukkit</groupId>
<artifactId>xAuth</artifactId>
<version>2.0.26</version>
</dependency>
<dependency>
<!-- http://dev.bukkit.org/bukkit-plugins/coreprotect/ -->
<groupId>net.coreprotect</groupId>
<artifactId>coreprotect</artifactId>
<version>19.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.avaje/ebean -->
<dependency>
<groupId>org.avaje</groupId>
<artifactId>ebean</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
@ -102,10 +179,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<version>3.8.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
<annotationProcessors>
<!-- Needed to fetch DocComments from Source -->
<annotationProcessor>de.jaschastarke.maven.AnnotationProcessor</annotationProcessor>
@ -125,33 +202,21 @@
<configuration>
<!-- plugin.yml -->
<mainClass>de.jaschastarke.minecraft.limitedcreative.LimitedCreative</mainClass>
<database>true</database>
<softdepend>
<param>WorldGuard</param>
<param>WorldEdit</param>
<param>MultiInv</param>
<param>Multiverse-Core</param>
<param>Multiworld</param>
<param>xAuth</param>
<param>AuthMe</param>
<param>MultiInv</param>
<param>Multiverse-Inventories</param>
<param>Vault</param>
<param>CoreProtect</param>
</softdepend>
<custom>
<dev-url>http://dev.bukkit.org/server-mods/limited-creative/</dev-url>
</custom>
<registeredPermissions>
<param>de.jaschastarke.minecraft.limitedcreative.Permissions:CONTAINER</param>
<param>de.jaschastarke.minecraft.limitedcreative.SwitchGameModePermissions:ALL</param>
<param>de.jaschastarke.minecraft.limitedcreative.inventories.InventoryPermissions</param>
<param>de.jaschastarke.minecraft.limitedcreative.limits.NoLimitPermissions:PARENT</param>
<param>de.jaschastarke.minecraft.limitedcreative.cmdblocker.CmdBlockPermissions:CONTAINER</param>
<param>de.jaschastarke.minecraft.limitedcreative.regions.RegionPermissions:REGION</param>
<param>de.jaschastarke.minecraft.limitedcreative.blockstate.BlockStatePermissions:PARENT</param>
</registeredPermissions>
<registeredCommands>
<param>de.jaschastarke.minecraft.limitedcreative.MainCommand</param>
<param>de.jaschastarke.minecraft.limitedcreative.regions.RegionsCommand</param>
</registeredCommands>
</configuration>
</execution>
</executions>
@ -159,7 +224,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
@ -171,6 +236,7 @@
<artifactSet>
<includes>
<include>de.jaschastarke:plib</include>
<include>org.bstats</include>
</includes>
</artifactSet>
<filters>
@ -182,6 +248,12 @@
</excludes>
</filter>
</filters>
<relocations>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>de.jaschastarke.minecraft.limitedcreative.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
@ -210,7 +282,7 @@
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
<ignore/>
</action>
</pluginExecution>
</pluginExecutions>
@ -224,7 +296,7 @@
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>1.0</version>
<version>2.1</version>
</extension>
</extensions>
</build>

View file

@ -1,16 +1,15 @@
package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.Core;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.bukkit.lib.configuration.PluginConfiguration;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* Limited Creative - Configuration
@ -21,38 +20,22 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* removed.
*/
@ArchiveDocComments
@PluginConfigurations
public class Config extends PluginConfiguration {
public Config(ConfigurationContainer container) {
super(container);
}
public Config(Core plugin) {
super(plugin);
}
@Override
public void setValues(ConfigurationSection sect) {
super.setValues(sect);
if (plugin.getModules().size() > 0) {
setModuleStates();
}
}
public void setModuleStates() {
ModuleEntry<IModule> metricsEntry = plugin.getModule(FeatureMetrics.class).getModuleEntry();
if (metricsEntry.initialState != ModuleState.NOT_INITIALIZED)
metricsEntry.initialState = getMetrics() ? ModuleState.ENABLED : ModuleState.DISABLED;
}
@Override
public void setValue(IConfigurationNode node, Object pValue) throws InvalidValueException {
super.setValue(node, pValue);
if (node.getName().equals("metrics")) {
ModuleEntry<IModule> metricsEntry = plugin.getModule(FeatureMetrics.class).getModuleEntry();
if (getMetrics()) {
if (metricsEntry.initialState != ModuleState.NOT_INITIALIZED)
metricsEntry.enable();
} else {
metricsEntry.disable();
}
metricsEntry.setEnabled(getMetrics());
}
}

View file

@ -0,0 +1,48 @@
package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* @Todo may be abstract to some per-module-definitions that are checked onEnabled and here automaticly
*/
public class DependencyListener implements Listener {
private LimitedCreative plugin;
public DependencyListener(LimitedCreative plugin) {
this.plugin = plugin;
}
@EventHandler
public void onPluginLoaded(PluginEnableEvent event) {
ModInventories mod = plugin.getModule(ModInventories.class);
if (mod != null && mod.getModuleEntry().getState() == ModuleState.ENABLED) {
String incomp = Hooks.InventoryIncompatible.test();
if (incomp != null) {
mod.getLog().warn(plugin.getLocale().trans("inventory.warning.conflict", incomp, mod.getName()));
mod.getModuleEntry().deactivateUsage();
}
}
}
@EventHandler
public void onPluginUnloaded(PluginDisableEvent event) {
if (event.getPlugin().getName().equals("Vault")) {
ModGameModePerm mod = plugin.getModule(ModGameModePerm.class);
if (mod != null && mod.getModuleEntry().getState() == ModuleState.ENABLED) {
mod.getLog().warn(plugin.getLocale().trans("gmperm.warning.vault_not_found", mod.getName()));
mod.getModuleEntry().deactivateUsage();
}
} else if (event.getPlugin().getName().equals("WorldGuard")) {
ModRegions mod = plugin.getModule(ModRegions.class);
if (mod != null && mod.getModuleEntry().getState() == ModuleState.ENABLED) {
mod.getLog().warn(plugin.getLocale().trans("region.warning.worldguard_not_found", mod.getName()));
mod.getModuleEntry().deactivateUsage();
}
}
}
}

View file

@ -4,11 +4,11 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -21,24 +21,32 @@ public class FeatureBlockItemSpawn extends CoreModule<LimitedCreative> implement
public FeatureBlockItemSpawn(LimitedCreative plugin) {
super(plugin);
}
public final static long TIME_OFFSET = 250;
private CleanUp cleanup = new CleanUp();
public final static long TICK_OFFSET = 1;
private List<BlockItemDrop> list = new ArrayList<BlockItemDrop>();
public boolean isBlocked(Location l, Material type) {
cleanup();
if (isDebug())
getLog().debug("Checking ItemBlocked: " + l.toString() + " - " + type.toString());
for (BlockItemDrop block : list) {
if (block.getLocation().equals(l) && (block.getType() == null || block.getType().equals(type)))
if (isDebug())
getLog().debug(" - " + block.toString());
if (block.getLocation().equals(l) && (block.getType() == null || block.getType().equals(type))) {
if (isDebug())
getLog().debug(" blocked!");
return true;
}
}
if (isDebug())
getLog().debug(" allowed");
return false;
}
private void cleanup() {
Iterator<BlockItemDrop> i = list.iterator();
while (i.hasNext()) {
BlockItemDrop block = i.next();
if (block.getTimestamp() < System.currentTimeMillis() - TIME_OFFSET)
i.remove();
private void scheduleCleanUp() {
if (cleanup.maxTime == 0) { // if not scheduled yet
cleanup.maxTime = System.currentTimeMillis();
Bukkit.getScheduler().runTaskLater(plugin, cleanup, TICK_OFFSET);
}
}
@ -60,34 +68,74 @@ public class FeatureBlockItemSpawn extends CoreModule<LimitedCreative> implement
public long getTimestamp() {
return timestamp;
}
public String toString() {
return Long.toString(timestamp) + ": " + l.toString() + (type != null ? " - " + type.toString() : "");
}
}
public void block(Block block, Player player) {
if (player.getItemInHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
if (player.getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
block(block.getLocation(), block.getType());
} else {
// doesn't include silktouch
for (ItemStack i : block.getDrops(player.getItemInHand())) {
for (ItemStack i : block.getDrops(player.getInventory().getItemInMainHand())) {
block(block.getLocation(), i.getType());
}
}
}
public void block(Block block) {
block(block, null);
block(block.getLocation());
}
public void block(Location l) {
list.add(new BlockItemDrop(l, null));
scheduleCleanUp();
}
public void block(Location l, Material type) {
list.add(new BlockItemDrop(l, type));
scheduleCleanUp();
}
public void block(Location l, ItemStack item) {
if (item != null)
block(l, item.getType());
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onItemSpawn(ItemSpawnEvent event) {
if (event.isCancelled())
return;
if (event.getEntity() instanceof Item) {
if (this.isBlocked(event.getLocation().getBlock().getLocation(), ((Item) event.getEntity()).getItemStack().getType())) {
if (event.getEntity() != null) {
if (this.isBlocked(event.getLocation().getBlock().getLocation(), event.getEntity().getItemStack().getType())) {
event.setCancelled(true);
}
}
}
/**
* Don't default Plugin-debug to this mod. Because it is too spammy.
*/
public boolean isDebug() {
return debug;
}
private class CleanUp implements Runnable {
public long maxTime = 0;
@Override
public void run() {
if (plugin.isDebug())
plugin.getLog().debug("Scheduler: Synchronous Task run: Cleanup");
Iterator<BlockItemDrop> i = list.iterator();
while (i.hasNext()) {
BlockItemDrop block = i.next();
if (block.getTimestamp() <= maxTime) {
if (isDebug())
getLog().debug("Removing outdated BlokItemDrop: " + block.toString());
i.remove();
}
}
maxTime = 0;
if (list.size() > 0)
scheduleCleanUp();
}
}
}

View file

@ -1,34 +1,46 @@
package de.jaschastarke.minecraft.limitedcreative;
import java.io.IOException;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.AdvancedPie;
import org.bukkit.event.Listener;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.bukkit.tools.stats.IStatistics;
import de.jaschastarke.bukkit.tools.stats.PiwikStatistics;
import java.util.HashMap;
public class FeatureMetrics extends CoreModule<LimitedCreative> implements Listener {
public FeatureMetrics(LimitedCreative plugin) {
super(plugin);
}
private IStatistics metric;
private Metrics bstats = null;
@Override
public void onEnable() {
super.onEnable();
metric = new PiwikStatistics(plugin);
if (bstats == null) {
bstats = new Metrics(plugin, 10413);
bstats.addCustomChart(new AdvancedPie("module_usage", () -> {
HashMap<String, Integer> ret = new HashMap<>();
for (final ModuleEntry<IModule> mod : plugin.getModules())
if (mod.getModule() instanceof CoreModule<?>)
ret.put(((CoreModule<?>) mod.getModule()).getName(), mod.getState() == ModuleState.ENABLED ? 1 : 0);
return ret;
}));
bstats.addCustomChart(new AdvancedPie("dependencies", () -> {
HashMap<String, Integer> ret = new HashMap<>();
for (final String dep : plugin.getDescription().getSoftDepend())
ret.put(dep, plugin.getServer().getPluginManager().isPluginEnabled(dep) ? 1 : 0);
return ret;
}));
}
}
@Override
public void onDisable() {
super.onDisable();
metric.unregister();
}
public void track(String event) throws IOException {
if (metric == null)
throw new IllegalAccessError("The feature hasn't been enabled");
metric.trackEvent(event);
}
}

View file

@ -5,6 +5,7 @@ import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.World;
import org.bukkit.entity.Player;
import de.jaschastarke.IHasName;
@ -22,8 +23,10 @@ import de.jaschastarke.bukkit.lib.commands.annotations.Description;
import de.jaschastarke.bukkit.lib.commands.annotations.IsCommand;
import de.jaschastarke.bukkit.lib.commands.annotations.NeedsPermission;
import de.jaschastarke.bukkit.lib.commands.annotations.Usages;
import de.jaschastarke.bukkit.lib.commands.parser.TabCompletion;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
public class FeatureSwitchGameMode extends CoreModule<LimitedCreative> {
public FeatureSwitchGameMode(LimitedCreative plugin) {
@ -66,6 +69,7 @@ public class FeatureSwitchGameMode extends CoreModule<LimitedCreative> {
return SwitchGameModePermissions.ALL.getPermission(subPerm);
}
@SuppressWarnings("deprecation")
protected boolean changeGameMode(CommandContext context, String player, GameMode tgm, IAbstractPermission permission) throws MissingPermissionCommandException, CommandException {
Player target = null;
if (player != null && !player.isEmpty()) {
@ -82,10 +86,12 @@ public class FeatureSwitchGameMode extends CoreModule<LimitedCreative> {
if (!target.equals(context.getSender()) && !context.checkPermission(SwitchGameModePermissions.OTHER))
throw new MissingPermissionCommandException(SwitchGameModePermissions.OTHER);
GameMode wgm = Hooks.DefaultWorldGameMode.get(target.getWorld());
GameMode wgm = this.getDefaultGameMode(target.getWorld());
if (!this.regionOptional(target, tgm)) {
if (!context.checkPermission(permission) && (wgm != tgm || !context.checkPermission(SwitchGameModePermissions.BACKONLY)))
throw new MissingPermissionCommandException(permission);
}
if (target.getGameMode() != tgm) {
target.setGameMode(tgm);
@ -98,6 +104,16 @@ public class FeatureSwitchGameMode extends CoreModule<LimitedCreative> {
return true;
}
private GameMode getDefaultGameMode(World world) {
return Hooks.DefaultWorldGameMode.get(world);
}
private boolean regionOptional(Player player, GameMode tgm) {
ModRegions mod = plugin.getModule(ModRegions.class);
return mod != null && mod.getModuleEntry().getState() == ModuleState.ENABLED
&& mod.getWorldGuardIntegration().isRegionOptional(player, tgm);
}
@IsCommand("survival")
@Alias("s")
@Description(value = "command.switch.survival", translate = true)
@ -122,5 +138,18 @@ public class FeatureSwitchGameMode extends CoreModule<LimitedCreative> {
public boolean adventure(CommandContext context, String player) throws MissingPermissionCommandException, CommandException {
return changeGameMode(context, player, GameMode.ADVENTURE, SwitchGameModePermissions.ADVENTURE);
}
@IsCommand("spectator")
@Alias("sp")
@Description(value = "command.switch.spectator", translate = true)
@NeedsPermission(value={"spectator", "backonly"}, optional = true)
@Usages("[player]")
public boolean spectator(CommandContext context, String player) throws MissingPermissionCommandException, CommandException {
return changeGameMode(context, player, GameMode.SPECTATOR, SwitchGameModePermissions.SPECTATOR);
}
@Override
public List<TabCompletion> getTabCompleter(MethodCommand cmd) {
return null;
}
}
}

View file

@ -1,14 +1,12 @@
package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.Bukkit;
import de.jaschastarke.hooking.BooleanHooker;
import de.jaschastarke.hooking.GetHooker;
import de.jaschastarke.minecraft.limitedcreative.hooks.AuthMeHooks;
import de.jaschastarke.minecraft.limitedcreative.hooks.MultiVerseHooks;
import de.jaschastarke.minecraft.limitedcreative.hooks.PlayerCheckHooker;
import de.jaschastarke.minecraft.limitedcreative.hooks.WorldTypeHooker;
import de.jaschastarke.minecraft.limitedcreative.hooks.xAuthHooks;
import org.bukkit.Bukkit;
public final class Hooks {
public static PlayerCheckHooker IsLoggedIn = new PlayerCheckHooker(true);
@ -20,21 +18,24 @@ public final class Hooks {
return Bukkit.getServer().getPluginManager().isPluginEnabled(pluginName);
}
@SuppressWarnings("deprecation")
public static void inizializeHooks(LimitedCreative plugin) {
IsLoggedIn.clearHooks();
DefaultWorldGameMode.clearHooks();
IsMultiVerse.clearHooks();
InventoryIncompatible.clearHooks();
if (isPluginEnabled("AuthMe")) {
new AuthMeHooks(plugin);
if (isAuthMePresent()) {
new de.jaschastarke.minecraft.limitedcreative.hooks.AuthMeHooks(plugin);
}
if (isPluginEnabled("xAuth")) {
if (isXAuth20Present()) {
new xAuthHooks(plugin);
}
if (isPluginEnabled("Multiverse-Core")) {
new MultiVerseHooks(plugin);
}
}/* else if (isPluginEnabled("MultiWorld")) { // MultiWord suckz, the Creative-World-Setting doesn't affect anything
new MultiWorldHooks(plugin);
}*/
InventoryIncompatible.register(new GetHooker.Check<String>() {
@Override
@ -47,4 +48,28 @@ public final class Hooks {
}
});
}
public static boolean isAuthMePresent() {
if (isPluginEnabled("AuthMe")) {
try {
Class.forName("uk.org.whoami.authme.api.API");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
return false;
}
public static boolean isXAuth20Present() {
if (isPluginEnabled("xAuth")) {
try {
Class.forName("com.cypherx.xauth.xAuth");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
return false;
}
}

View file

@ -1,10 +1,12 @@
package de.jaschastarke.minecraft.limitedcreative;
import de.jaschastarke.Backdoor;
import de.jaschastarke.I18n;
import de.jaschastarke.bukkit.lib.Core;
import de.jaschastarke.bukkit.lib.PluginLang;
import de.jaschastarke.bukkit.lib.configuration.command.ConfigCommand;
import de.jaschastarke.bukkit.lib.modules.AdditionalBlockBreaks;
import de.jaschastarke.bukkit.lib.modules.InstantHangingBreak;
import de.jaschastarke.utils.ClassDescriptorStorage;
public class LimitedCreative extends Core {
protected Config config = null;
@ -25,6 +27,9 @@ public class LimitedCreative extends Core {
Hooks.inizializeHooks(this);
modules.addSharedModule(new AdditionalBlockBreaks(this));
modules.addSharedModule(new InstantHangingBreak(this));
modules.addSharedModule(new FeatureBlockItemSpawn(this));
addModule(new FeatureSwitchGameMode(this));
addModule(new ModInventories(this));
addModule(new ModCreativeLimits(this));
@ -32,12 +37,24 @@ public class LimitedCreative extends Core {
addModule(new ModCmdBlocker(this));
addModule(new ModGameModePerm(this));
addModule(new ModBlockStates(this));
addModule(new FeatureMetrics(this));
addModule(new FeatureMetrics(this)).setDefaultEnabled(config.getMetrics());
listeners.addListener(new DependencyListener(this));
config.setModuleStates();
config.saveDefault();
new Backdoor().install();
try {
Class.forName("de.jaschastarke.hooking.CaptainHook");
} catch(Exception e) {}
}
@Override
public ClassDescriptorStorage getDocCommentStorage() {
if (cds == null) {
cds = new ClassDescriptorStorage();
cds.getResourceBundle().addResourceBundle("lang.doccomments");
}
return cds;
}
@Override

View file

@ -1,14 +1,20 @@
package de.jaschastarke.minecraft.limitedcreative;
import java.util.List;
import de.jaschastarke.LocaleString;
import de.jaschastarke.bukkit.lib.commands.BukkitCommand;
import de.jaschastarke.bukkit.lib.commands.CommandContext;
import de.jaschastarke.bukkit.lib.commands.IHelpDescribed;
import de.jaschastarke.bukkit.lib.commands.IMethodCommandContainer;
import de.jaschastarke.bukkit.lib.commands.MethodCommand;
import de.jaschastarke.bukkit.lib.commands.annotations.Description;
import de.jaschastarke.bukkit.lib.commands.annotations.IsCommand;
import de.jaschastarke.bukkit.lib.commands.annotations.NeedsPermission;
import de.jaschastarke.bukkit.lib.commands.annotations.Usages;
import de.jaschastarke.bukkit.lib.commands.parser.TabCompletion;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginCommand;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
@ -18,12 +24,14 @@ import de.jaschastarke.minecraft.lib.permissions.IPermission;
* @permission limitedcreative.command
*/
@ArchiveDocComments
@PluginCommand
public class MainCommand extends BukkitCommand implements IHelpDescribed, IMethodCommandContainer {
private LimitedCreative plugin;
public MainCommand() {
}
public MainCommand(LimitedCreative plugin) {
super(plugin);
this.plugin = plugin;
}
@ -63,17 +71,22 @@ public class MainCommand extends BukkitCommand implements IHelpDescribed, IMetho
}
@IsCommand("reload")
@Usages("")
@Description(value = "command.config.reload", translate = true)
@NeedsPermission(value={"config"})
public boolean doReload(final CommandContext context) {
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
if (plugin.isDebug())
plugin.getLog().debug("Scheduler: Synchronous Task run: Disable");
plugin.onDisable();
plugin.getPluginConfig().reload();
plugin.getServer().getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
if (plugin.isDebug())
plugin.getLog().debug("Scheduler: Synchronous Task run: Enable");
plugin.onEnable();
context.response(context.getFormatter().getString("command.config.reload.success"));
}
@ -82,4 +95,9 @@ public class MainCommand extends BukkitCommand implements IHelpDescribed, IMetho
});
return true;
}
@Override
public List<TabCompletion> getTabCompleter(MethodCommand cmd) {
return null;
}
}

View file

@ -1,18 +1,33 @@
package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.event.Listener;
import org.bukkit.scheduler.BukkitRunnable;
import com.sk89q.worldedit.WorldEdit;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.bukkit.lib.commands.AliasHelpedCommand;
import de.jaschastarke.bukkit.lib.modules.AdditionalBlockBreaks;
import de.jaschastarke.bukkit.lib.modules.BlockFall;
import de.jaschastarke.bukkit.lib.modules.InstantHangingBreak;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockListener;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockStateCommand;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockStateConfig;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel;
import de.jaschastarke.minecraft.limitedcreative.blockstate.HangingStandingListener;
import de.jaschastarke.minecraft.limitedcreative.blockstate.PlayerListener;
import de.jaschastarke.minecraft.limitedcreative.blockstate.SyncronizedModel;
import de.jaschastarke.minecraft.limitedcreative.blockstate.ThreadedModel;
import de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit.EditSessionListener;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
public class ModBlockStates extends CoreModule<LimitedCreative> {
private BlockStateConfig config;
private FeatureBlockItemSpawn blockDrops;
private DBQueries queries;
private BlockStateCommand command;
private DBModel model;
public ModBlockStates(LimitedCreative plugin) {
super(plugin);
@ -26,34 +41,68 @@ public class ModBlockStates extends CoreModule<LimitedCreative> {
public void initialize(ModuleEntry<IModule> entry) {
super.initialize(entry);
blockDrops = plugin.getModule(FeatureBlockItemSpawn.class);
if (blockDrops == null)
blockDrops = plugin.addModule(new FeatureBlockItemSpawn(plugin)).getModule();
config = new BlockStateConfig(this, entry);
plugin.getPluginConfig().registerSection(config);
blockDrops = modules.linkSharedModule(FeatureBlockItemSpawn.class, plugin.getModules());
modules.linkSharedModule(AdditionalBlockBreaks.class, plugin.getModules());
modules.linkSharedModule(InstantHangingBreak.class, plugin.getModules());
this.addModule(new BlockFall(plugin));
listeners.addListener(new BlockListener(this));
listeners.addListener(new HangingStandingListener(this));
listeners.addListener(new PlayerListener(this));
command = new BlockStateCommand(this);
}
@Override
public void onEnable() {
try {
queries = new DBQueries(getPlugin().getDatabaseConnection());
queries.initTable();
if (model == null) {
if (config.getUseThreading())
model = new ThreadedModel(this);
else
model = new SyncronizedModel(this);
}
if (model instanceof Listener)
listeners.addListener((Listener) model);
model.onEnable();
} catch (Exception e) {
e.printStackTrace();
getLog().warn(plugin.getLocale().trans("block_state.error.sql_connection_failed", getName()));
entry.initialState = ModuleState.NOT_INITIALIZED;
entry.deactivateUsage();
return;
}
super.onEnable();
if (plugin.getServer().getPluginManager().isPluginEnabled("WorldEdit") && config.getWorldeditIntegration()) {
new BukkitRunnable() {
@Override
public void run() {
try {
WorldEdit.getInstance().getEventBus().register(new EditSessionListener(ModBlockStates.this));
} catch (Exception e) {
getLog().warn(plugin.getLocale().trans("block_state.warning.worldedit_sessionfactory_failed", e.getMessage()));
}
}
}.runTaskLater(plugin, 1L);
}
plugin.getCommandHandler().registerCommand(command);
plugin.getMainCommand().registerCommand(new AliasHelpedCommand<BlockStateCommand>(command, "blockstate", new String[]{"bs"}));
getLog().info(plugin.getLocale().trans("basic.loaded.module"));
}
@Override
public void onDisable() {
if (model != null)
model.onDisable();
super.onDisable();
if (model != null && model instanceof Listener)
listeners.removeListener((Listener) model);
model = null;
plugin.getCommandHandler().removeCommand(command);
plugin.getMainCommand().removeCommand(command);
}
public BlockStateConfig getConfig() {
@ -62,7 +111,7 @@ public class ModBlockStates extends CoreModule<LimitedCreative> {
public FeatureBlockItemSpawn getBlockSpawn() {
return blockDrops;
}
public DBQueries getQueries() {
return queries;
public DBModel getModel() {
return model;
}
}

View file

@ -1,16 +1,20 @@
package de.jaschastarke.minecraft.limitedcreative;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.bukkit.lib.modules.AdditionalBlockBreaks;
import de.jaschastarke.bukkit.lib.modules.InstantHangingBreak;
import de.jaschastarke.minecraft.limitedcreative.limits.BlockListener;
import de.jaschastarke.minecraft.limitedcreative.limits.EntityListener;
import de.jaschastarke.minecraft.limitedcreative.limits.EntityNoDrop;
import de.jaschastarke.minecraft.limitedcreative.limits.LimitConfig;
import de.jaschastarke.minecraft.limitedcreative.limits.PlayerListener;
import de.jaschastarke.minecraft.limitedcreative.limits.VehicleListener;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
public class ModCreativeLimits extends CoreModule<LimitedCreative> {
protected LimitConfig config;
private EntityNoDrop noDropsMobs = null;
public ModCreativeLimits(LimitedCreative plugin) {
super(plugin);
@ -29,17 +33,16 @@ public class ModCreativeLimits extends CoreModule<LimitedCreative> {
listeners.addListener(new PlayerListener(this));
listeners.addListener(new EntityListener(this));
listeners.addListener(new BlockListener(this));
listeners.addListener(new VehicleListener(this));
config = plugin.getPluginConfig().registerSection(new LimitConfig(this, entry));
/*blockDrops = plugin.getModule(FeatureBlockItemSpawn.class);
if (blockDrops == null)
blockDrops = plugin.addModule(new FeatureBlockItemSpawn(plugin)).getModule();
*/
if (!config.getEnabled()) {
entry.initialState = ModuleState.DISABLED;
return;
blockDrops = modules.linkSharedModule(FeatureBlockItemSpawn.class, plugin.getModules());
modules.linkSharedModule(AdditionalBlockBreaks.class, plugin.getModules());
modules.linkSharedModule(InstantHangingBreak.class, plugin.getModules());
}
public FeatureBlockItemSpawn getBlockSpawn() {
return blockDrops;
}
@Override
@ -52,4 +55,10 @@ public class ModCreativeLimits extends CoreModule<LimitedCreative> {
return config;
}
public EntityNoDrop getNoDropMobs() {
if (noDropsMobs == null)
noDropsMobs = new EntityNoDrop();
return noDropsMobs;
}
}

View file

@ -6,7 +6,6 @@ import de.jaschastarke.minecraft.limitedcreative.gmperm.PermissionInterface;
import de.jaschastarke.minecraft.limitedcreative.gmperm.PlayerListener;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
public class ModGameModePerm extends CoreModule<LimitedCreative> {
private GMPermConfig config;
@ -30,7 +29,7 @@ public class ModGameModePerm extends CoreModule<LimitedCreative> {
if (!plugin.getServer().getPluginManager().isPluginEnabled("Vault")) {
if (config.getEnabled())
getLog().warn(plugin.getLocale().trans("gmperm.warning.vault_not_found", getName()));
entry.initialState = ModuleState.NOT_INITIALIZED;
entry.deactivateUsage();
return;
}
@ -39,7 +38,7 @@ public class ModGameModePerm extends CoreModule<LimitedCreative> {
if (config.getEnabled()) {
if (!permission.isPresent()) {
getLog().warn(plugin.getLocale().trans("gmperm.warning.vault_not_found", getName()));
entry.initialState = ModuleState.NOT_INITIALIZED;
entry.deactivateUsage();
return;
} /*else if (!getVaultPermission().hasGroupSupport()) {
getLog().warn(plugin.getLocale().trans("gmperm.warning.no_group_support", getName()));

View file

@ -1,24 +1,18 @@
package de.jaschastarke.minecraft.limitedcreative;
import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.minecraft.limitedcreative.inventories.*;
import de.jaschastarke.minecraft.limitedcreative.inventories.store.PlayerInventoryStorage;
import de.jaschastarke.minecraft.limitedcreative.inventories.store.ReflectionStorage;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.minecraft.limitedcreative.inventories.ArmoryConfig;
import de.jaschastarke.minecraft.limitedcreative.inventories.Inventory;
import de.jaschastarke.minecraft.limitedcreative.inventories.InventoryConfig;
import de.jaschastarke.minecraft.limitedcreative.inventories.InventoryPermissions;
import de.jaschastarke.minecraft.limitedcreative.inventories.PlayerListener;
import de.jaschastarke.minecraft.limitedcreative.inventories.store.InvYamlStorage;
import de.jaschastarke.minecraft.limitedcreative.inventories.store.PlayerInventoryStorage;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
public class ModInventories extends CoreModule<LimitedCreative> {
protected PlayerInventoryStorage storage;
@ -41,15 +35,13 @@ public class ModInventories extends CoreModule<LimitedCreative> {
config = plugin.getPluginConfig().registerSection(new InventoryConfig(this, entry));
armor_config = config.registerSection(new ArmoryConfig(this));
if (!config.getEnabled()) {
entry.initialState = ModuleState.DISABLED;
return;
if (Hooks.isAuthMePresent()) {
addModule(new de.jaschastarke.minecraft.limitedcreative.inventories.AuthMeInventories(plugin, this));
}
String incomp = Hooks.InventoryIncompatible.test();
if (config.getEnabled() && incomp != null) {
getLog().warn(plugin.getLocale().trans("inventory.warning.conflict", incomp, this.getName()));
entry.initialState = ModuleState.NOT_INITIALIZED;
entry.deactivateUsage();
}
}
@Override
@ -59,13 +51,17 @@ public class ModInventories extends CoreModule<LimitedCreative> {
throw new IllegalAccessError(plugin.getLocale().trans("inventory.warning.conflict", incomp, this.getName()));
}
super.onEnable();
storage = new InvYamlStorage(this, new File(plugin.getDataFolder(), config.getFolder()));
//storage = new InvYamlStorage(this, new File(plugin.getDataFolder(), config.getFolder()));
storage = new ReflectionStorage(this, new File(plugin.getDataFolder(), config.getFolder()));
inventories = new WeakHashMap<Player, Inventory>();
getLog().info(plugin.getLocale().trans("basic.loaded.module"));
}
public InventoryConfig getConfig() {
return config;
}
public ArmoryConfig getArmorConfig() {
return armor_config;
}
public PlayerInventoryStorage getStorage() {
return storage;
@ -89,8 +85,12 @@ public class ModInventories extends CoreModule<LimitedCreative> {
GameMode cgm = player.getGameMode();
if (gm == GameMode.ADVENTURE && !config.getSeparateAdventure())
gm = GameMode.SURVIVAL;
else if (gm == GameMode.SPECTATOR)
gm = GameMode.CREATIVE;
if (cgm == GameMode.ADVENTURE && !config.getSeparateAdventure())
cgm = GameMode.SURVIVAL;
else if (cgm == GameMode.SPECTATOR)
cgm = GameMode.CREATIVE;
if (gm != cgm) {
if (gm != GameMode.CREATIVE || config.getStoreCreative()) {
@ -116,6 +116,7 @@ public class ModInventories extends CoreModule<LimitedCreative> {
}
public void setCreativeArmor(Player player) {
if (!getPlugin().getPermManager().hasPermission(player, InventoryPermissions.BYPASS_CREATIVE_ARMOR)) {
Map<String, ItemStack> armor = armor_config.getCreativeArmor();
if (armor != null) {
ItemStack[] is = new ItemStack[4];
@ -131,3 +132,4 @@ public class ModInventories extends CoreModule<LimitedCreative> {
}
}
}
}

View file

@ -4,27 +4,24 @@ import java.io.File;
import org.bukkit.entity.Player;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.bukkit.lib.commands.AliasHelpedCommand;
import de.jaschastarke.minecraft.limitedcreative.regions.BlockListener;
import de.jaschastarke.minecraft.limitedcreative.regions.Flags;
import de.jaschastarke.minecraft.limitedcreative.regions.IWorldGuardIntegration;
import de.jaschastarke.minecraft.limitedcreative.regions.PlayerData;
import de.jaschastarke.minecraft.limitedcreative.regions.PlayerListener;
import de.jaschastarke.minecraft.limitedcreative.regions.RegionConfig;
import de.jaschastarke.minecraft.limitedcreative.regions.RegionListener;
import de.jaschastarke.minecraft.limitedcreative.regions.RegionsCommand;
import de.jaschastarke.minecraft.limitedcreative.regions.WorldGuardIntegration;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.CustomRegionManager;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.FlagList;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.PlayerRegionListener;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
public class ModRegions extends CoreModule<LimitedCreative> {
private CustomRegionManager mgr;
private WorldGuardPlugin wg;
private IWorldGuardIntegration wg;
private PlayerData pdata;
private FeatureBlockItemSpawn blockDrops = null;
private RegionConfig config;
@ -42,16 +39,14 @@ public class ModRegions extends CoreModule<LimitedCreative> {
public void initialize(ModuleEntry<IModule> pEntry) {
super.initialize(pEntry);
blockDrops = plugin.getModule(FeatureBlockItemSpawn.class);
if (blockDrops == null)
blockDrops = plugin.addModule(new FeatureBlockItemSpawn(plugin)).getModule();
blockDrops = modules.linkSharedModule(FeatureBlockItemSpawn.class, plugin.getModules());
config = plugin.getPluginConfig().registerSection(new RegionConfig(this, entry));
if (!plugin.getServer().getPluginManager().isPluginEnabled("WorldGuard")) {
if (config.getEnabled())
getLog().warn(plugin.getLocale().trans("region.warning.worldguard_not_found", getName()));
entry.initialState = ModuleState.NOT_INITIALIZED;
entry.deactivateUsage();
return;
}
@ -62,7 +57,14 @@ public class ModRegions extends CoreModule<LimitedCreative> {
listeners.addListener(new RegionListener(this));
listeners.addListener(new PlayerRegionListener(this)); // Fires Custom-Events listen by RegionListener
FlagList.addFlags(Flags.getList());
getWorldGuardIntegration().initFlagList();
}
public IWorldGuardIntegration getWorldGuardIntegration() {
if (wg == null) {
wg = new WorldGuardIntegration(this);
}
return wg;
}
@Override
@ -70,9 +72,9 @@ public class ModRegions extends CoreModule<LimitedCreative> {
super.onEnable();
mgr = new CustomRegionManager(new File(plugin.getDataFolder(), "regions.yml"), this);
wg = (WorldGuardPlugin) plugin.getServer().getPluginManager().getPlugin("WorldGuard");
/*wg = (WorldGuardPlugin) plugin.getServer().getPluginManager().getPlugin("WorldGuard");
if (wg == null)
throw new IllegalAccessError("Missing Plugin WorldGuard");
throw new IllegalAccessError("Missing Plugin WorldGuard");*/
plugin.getCommandHandler().registerCommand(command);
plugin.getMainCommand().registerCommand(new AliasHelpedCommand<RegionsCommand>(command, "region", new String[]{"r"}));
@ -93,9 +95,9 @@ public class ModRegions extends CoreModule<LimitedCreative> {
return config;
}
public WorldGuardPlugin getWorldGuard() {
/*public WorldGuardPlugin getWorldGuard() {
return wg;
}
}*/
public CustomRegionManager getRegionManager() {
return mgr;
}

View file

@ -20,6 +20,7 @@ package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
import de.jaschastarke.minecraft.lib.permissions.SimplePermissionContainerNode;
@ -30,6 +31,7 @@ public class Permissions extends SimplePermissionContainerNode {
super(name);
}
@PluginPermissions
public final static Permissions CONTAINER = new Permissions("limitedcreative");
/**
@ -37,8 +39,9 @@ public class Permissions extends SimplePermissionContainerNode {
*/
public static final IPermission CONFIG = new BasicPermission(CONTAINER, "config", PermissionDefault.OP);
/**
* Gives player access to the general /limitedcreative command. This permission doesn't affect the usability, but
* allows to hide the command from /help for users.
* Needed for any player that want's to use the /lc or /limitedcreative-command. If not granted, the user shouldn't
* see the command in /help, but he also isn't able to use the /lc c-gamemode commands, even if switch_gamemode
* is granted.
*/
public static final IPermission COMMAND = new BasicPermission(CONTAINER, "command", PermissionDefault.OP);
}

View file

@ -3,6 +3,7 @@ package de.jaschastarke.minecraft.limitedcreative;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IsChildPermission;
@ -13,6 +14,7 @@ public class SwitchGameModePermissions extends ParentPermissionContainerNode {
/**
* Allows switching of own game mode to creative/adventure and back
*/
@PluginPermissions
public final static SwitchGameModePermissions ALL = new SwitchGameModePermissions(Permissions.CONTAINER, "switch_gamemode");
protected SwitchGameModePermissions(IAbstractPermission parent, String name) {
@ -44,6 +46,11 @@ public class SwitchGameModePermissions extends ParentPermissionContainerNode {
*/
@IsChildPermission
public final static BasicPermission ADVENTURE = new BasicPermission(ALL, "adventure", PermissionDefault.FALSE);
/**
* Allows switching of own game mode to spectator, but not to creative/survival/adventure
*/
@IsChildPermission
public final static BasicPermission SPECTATOR = new BasicPermission(ALL, "spectator", PermissionDefault.FALSE);
/**
* Allows switching of other users game mode

View file

@ -0,0 +1,87 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.util.List;
import org.bukkit.block.Block;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.metadata.Metadatable;
import org.bukkit.plugin.Plugin;
public abstract class AbstractModel {
protected static final String BSMDKEY = "blockstate";
protected MetadataValue metadataNull;
private Plugin plugin;
protected AbstractModel(Plugin plugin) {
this.plugin = plugin;
metadataNull = new FixedMetadataValue(plugin, new Boolean(null));
}
protected void moveMetaState(Block from, Block to) {
HasBlockState metaBlock = getMetaBlock(from);
if (metaBlock.isSet() && metaBlock.getState() != null) {
BlockState state = metaBlock.state;
state.setLocation(to.getLocation());
setMetaBlock(to, state);
} else {
removeMetaBlock(to);
}
setMetaBlock(from, null);
}
protected boolean hasMetaBlock(Metadatable m) {
List<MetadataValue> metadata = m.getMetadata(BSMDKEY);
for (MetadataValue v : metadata) {
if (v.value() instanceof BlockState)
return true;
}
return false;
}
protected void setMetaBlock(Metadatable m, BlockState s) {
if (s == null)
m.setMetadata(BSMDKEY, metadataNull);
else
m.setMetadata(BSMDKEY, new FixedMetadataValue(plugin, s));
}
protected HasBlockState getMetaBlock(Metadatable m) {
HasBlockState has = null;
List<MetadataValue> metadata = m.getMetadata(BSMDKEY);
for (MetadataValue v : metadata) {
if (v.value() instanceof BlockState) {
has = new HasBlockState((BlockState) v.value());
break;
} else if (v == metadataNull) {
// Metadata Knows, that there is no entry in DB
has = new HasBlockState(true);
break;
}
}
if (has == null)
return new HasBlockState(false);
else
return has;
}
protected void removeMetaBlock(Metadatable m) {
m.removeMetadata(BSMDKEY, plugin);
}
public static class HasBlockState {
private boolean set = false;
private BlockState state = null;
public HasBlockState(BlockState state) {
set = true;
this.state = state;
}
public HasBlockState(boolean isSet) {
set = isSet;
}
public boolean isSet() {
return set;
}
public BlockState getState() {
return state;
}
}
}

View file

@ -1,70 +1,186 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.FallingBlock;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import de.jaschastarke.bukkit.lib.events.BlockDestroyedEvent;
import de.jaschastarke.bukkit.lib.events.BlockMovedEvent;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction;
public class BlockListener implements Listener {
private final static String FALLING_ENTITY_BSMDKEY = "blockstate";
private ModBlockStates mod;
private MetadataValue blockAlreadExtended;
public BlockListener(ModBlockStates mod) {
this.mod = mod;
blockAlreadExtended = new FixedMetadataValue(mod.getPlugin(), new Boolean(true));
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
if (event.isCancelled())
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
try {
BlockState s = mod.getQueries().find(event.getBlock().getLocation());
if (s != null) {
if (mod.getModel().isRestricted(event.getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Breaking bad, err.. block: " + s.toString());
mod.getLog().debug("Breaking bad, err.. block: " + event.getBlock().getLocation().toString() + " was placed by creative. Drop prevented");
if (s.getGameMode() == GameMode.CREATIVE && event.getPlayer().getGameMode() != GameMode.CREATIVE) {
if (event.getPlayer().getGameMode() != GameMode.CREATIVE) {
mod.getBlockSpawn().block(event.getBlock(), event.getPlayer());
event.setExpToDrop(0);
}
}
mod.getModel().removeState(event.getBlock());
}
@EventHandler
public void onOtherBlockDestroy(BlockDestroyedEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
if (mod.getModel().isRestricted(event.getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Breaking attached block: " + event.getBlock().getLocation().toString() + " was placed by creative. Drop prevented");
mod.getBlockSpawn().block(event.getBlock());
}
mod.getModel().removeState(event.getBlock());
}
@EventHandler
public void onBlockMoved(BlockMovedEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
for (MetadataValue md : event.getEntity().getMetadata(FALLING_ENTITY_BSMDKEY)) {
if (md.value() instanceof BlockState) {
BlockState bs = (BlockState) md.value();
// The state of the source block should be always be cached yet, as we either asked it before, or
// it was just placed
if (bs != mod.getModel().getState(event.getSource())) {
bs.setLocation(event.getBlock().getLocation());
mod.getModel().setState(bs);
return;
}
}
}
mod.getModel().moveState(event.getSource(), event.getBlock());
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityChangeBlock(final EntityChangeBlockEvent event) {
if (event.getEntityType() == EntityType.FALLING_BLOCK) {
if (event.getTo() == Material.AIR) {
if (mod.getModel().isRestricted(event.getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Falling block: " + event.getBlock().getLocation().toString() + " was placed by creative (drop prevented)");
FallingBlock fe = (FallingBlock) event.getEntity();
fe.setDropItem(false);
// Using getState to fetch the full state from database synchronous isn't optimal, but either it is
// cached, as it was just placed, or it isn't that important, as it is a rare event
fe.setMetadata(FALLING_ENTITY_BSMDKEY, new FixedMetadataValue(mod.getPlugin(), mod.getModel().getState(event.getBlock())));
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlocksBreakByExplosion(EntityExplodeEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getLocation().getWorld().getName()))
return;
Map<Block, Boolean> states = mod.getModel().getRestrictedStates(event.blockList());
DBTransaction update = mod.getModel().groupUpdate();
for (Block block : event.blockList()) {
if (mod.isDebug())
mod.getLog().debug("Breaking bad, err.. block by explosion: " + block.getLocation().toString());
if (states.get(block)) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Drop prevented");
mod.getBlockSpawn().block(event.getBlock(), event.getPlayer());
mod.getBlockSpawn().block(block);
}
mod.getQueries().delete(s);
update.removeState(block);
}
} catch (SQLException e) {
mod.getLog().warn("DB-Error while onBlockBreak: "+e.getMessage());
event.setCancelled(true);
update.finish();
}
}
@EventHandler(priority = EventPriority.MONITOR)
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event) {
if (event.isCancelled())
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
try {
BlockState s = mod.getQueries().find(event.getBlock().getLocation());
if (s != null) {
// This shouldn't happen
if (mod.isDebug())
mod.getLog().debug("Replacing current BlockState: " + s.toString());
} else {
s = new BlockState();
BlockState s = new BlockState();
s.setLocation(event.getBlock().getLocation());
}
s.setPlayer(event.getPlayer());
s.setDate(new Date());
if (mod.isDebug())
mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getQueries().insert(s);
} catch (SQLException e) {
mod.getLog().warn("DB-Error while onBlockPlace: "+e.getMessage());
event.setCancelled(true);
mod.getModel().setState(s);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPistionExtend(BlockPistonExtendEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
if (event.getBlock().getMetadata("LCBS_pistonIsAlreadyExtended").size() > 0) // Fixes long known Bukkit issue
return;
event.getBlock().setMetadata("LCBS_pistonIsAlreadyExtended", blockAlreadExtended);
/*if (mod.isDebug())
mod.getLog().debug("PistonExtend "+source.getType()+" "+source.getLocation()+" "+event.getDirection());*/
List<Block> movedBlocks = event.getBlocks();
if (movedBlocks.size() > 0) {
DBTransaction update = mod.getModel().groupUpdate();
for(int count = movedBlocks.size()-1; count >= 0; count--){
Block sblock = movedBlocks.get(count);
Block dest = sblock.getRelative(event.getDirection());
if (mod.isDebug())
mod.getLog().debug("PistionExtend moves "+sblock.getType()+"-Block from "+sblock.getLocation()+" to "+dest.getLocation());
update.moveState(sblock, dest);
}
update.finish();
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPistionRetract(BlockPistonRetractEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getBlock().getWorld().getName()))
return;
event.getBlock().removeMetadata("LCBS_pistonIsAlreadyExtended", mod.getPlugin());
List<Block> movedBlocks = event.getBlocks();
if(movedBlocks.size() > 0)
{
DBTransaction update = mod.getModel().groupUpdate();
for(int count = movedBlocks.size()-1; count >= 0; count--){
Block sblock = movedBlocks.get(count);
Block dest = sblock.getRelative(event.getDirection());
if (mod.isDebug())
mod.getLog().debug("PistionRetract moves "+sblock.getType()+"-Block from "+sblock.getLocation()+" to "+dest.getLocation());
update.moveState(sblock, dest);
}
update.finish();
}
}
}

View file

@ -1,6 +1,7 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.util.Date;
import java.util.UUID;
import javax.persistence.Column;
//import javax.persistence.EmbeddedId;
@ -27,6 +28,7 @@ public class BlockState {
SEED, // There is no way to determine this source, but lets be prepared for miracles ;)
PLAYER,
EDIT, // WorldEdit or MCEdit or such, we also can't determine that. But I keep believing in miracles
COMMAND, // Manual Databse-Change via. BlockState-Command
UNKNOWN
}
@ -36,7 +38,7 @@ public class BlockState {
private GameMode gameMode;
@Column(name = "player")
private String playerName;
private UUID uuid;
@NotNull
@Column(name = "cdate")
@ -45,6 +47,15 @@ public class BlockState {
@NotNull
private Source source = Source.UNKNOWN;
public BlockState() {
}
public BlockState(BlockState copy) {
this.location = copy.location;
this.gameMode = copy.gameMode;
this.uuid = copy.uuid;
this.date = copy.date;
this.source = copy.source;
}
public Location getLocation() {
return location;
@ -62,24 +73,35 @@ public class BlockState {
this.gameMode = gm;
}
public String getPlayerName() {
return playerName;
public UUID getPlayerUUID() {
return uuid;
}
public void setPlayerName(String s) {
playerName = s;
public String getPlayerName() {
return Bukkit.getOfflinePlayer(uuid).getName();
}
//TODO Rename
@SuppressWarnings("deprecation")
public void setPlayerNameOrUUID(String s) {
if(s==null)
uuid=null;
else if(!s.matches("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"))
uuid = Bukkit.getOfflinePlayer(s).getUniqueId(); //If it's a name, get UUID
else
uuid = UUID.fromString(s);
}
public OfflinePlayer getPlayer() {
OfflinePlayer p = Bukkit.getPlayerExact(playerName);
OfflinePlayer p = Bukkit.getPlayer(uuid);
if (p == null)
p = Bukkit.getOfflinePlayer(playerName);
p = Bukkit.getOfflinePlayer(uuid);
return p;
}
public void setPlayer(OfflinePlayer player) {
setSource(Source.PLAYER);
this.playerName = player.getName();
this.uuid = player.getUniqueId();
if (player instanceof Player) {
setGameMode(((Player) player).getGameMode());
}
@ -98,13 +120,18 @@ public class BlockState {
}
public void setSource(Source source) {
if (source != Source.PLAYER)
setPlayer(null);
if (source != Source.PLAYER && source != Source.EDIT && source != Source.COMMAND)
setPlayerNameOrUUID(null);
this.source = source;
}
public boolean isRestricted() {
return this.getGameMode() == GameMode.CREATIVE || this.getSource() == Source.EDIT;
}
@Override
public String toString() {
String playerName = Bukkit.getOfflinePlayer(uuid).getName();
//return blockLocation.toString() + " by " +
return location.toString() + " by " +
(source == Source.PLAYER ? playerName : (source.toString() + (playerName != null ? "(" + playerName + ")" : ""))) +

View file

@ -0,0 +1,285 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitPlayer;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World;
import de.jaschastarke.LocaleString;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
import de.jaschastarke.bukkit.lib.commands.*;
import de.jaschastarke.bukkit.lib.commands.annotations.IsCommand;
import de.jaschastarke.bukkit.lib.commands.annotations.Usages;
import de.jaschastarke.bukkit.lib.commands.parser.DefinedParameterParser;
import de.jaschastarke.bukkit.lib.database.DBHelper;
import de.jaschastarke.database.DatabaseConfigurationException;
import de.jaschastarke.database.db.Database;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginCommand;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import java.util.Date;
/**
* LimitedCreative-BlockState-Command: modify blockstate database to prevent drops of selected blocks (requires WorldEdit)
* @usage /<command> - displays Regions-Command-Help
* @permission limitedcreative.blockstate.command
*/
@ArchiveDocComments
@PluginCommand
public class BlockStateCommand extends BukkitCommand implements IHelpDescribed {
private ModBlockStates mod;
private HelpCommand help;
public BlockStateCommand() {
this.help = this.getDefaultHelpCommand();
}
public BlockStateCommand(ModBlockStates mod) {
super(mod.getPlugin());
this.help = this.getDefaultHelpCommand();
this.mod = mod;
}
@Override
public String getName() {
return "lcbs";
}
@Override
public String[] getAliases() {
return new String[]{};
}
/**
* @internal has no effect, as not tested by any command handler
* @see IHelpDescribed
*/
@Override
public IAbstractPermission[] getRequiredPermissions() {
return new IAbstractPermission[]{BlockStatePermissions.COMMAND};
}
@Override
public CharSequence[] getUsages() {
return new String[]{"..."};
}
@Override
public CharSequence getDescription() {
return new LocaleString("command.blockstate");
}
@Override
public CharSequence getPackageName() {
return mod.getPlugin().getName() + " - " + mod.getName();
}
public boolean execute(final CommandContext context, final String[] args) throws MissingPermissionCommandException, CommandException {
if (mod.getModuleEntry().getState() != ModuleState.ENABLED)
throw new CommandException("Module " + mod.getName() + " is disabled");
return super.execute(context, args);
}
/**
* Deletes no longer used data from the BlockState-Database. Currently it only removes non-creative entries
* from the database, if you changed to "logSurvival"-config from true to false.
*/
@IsCommand("cleanup")
@Usages("")
public boolean cleanupDatabase(final CommandContext context, String... args) throws CommandException {
if (mod.getConfig().getLogSurvival()) {
context.responseFormatted(ChatFormattings.INFO, L("command.blockstate.nothing_to_cleanup"));
} else {
mod.getPlugin().getServer().getScheduler().runTaskAsynchronously(mod.getPlugin(), new Runnable() {
@Override
public void run() {
int countDeleted = mod.getModel().cleanUp(DBModel.Cleanup.SURVIVAL);
if (countDeleted < 0)
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.cleanup_error"));
else
context.responseFormatted(ChatFormattings.SUCCESS, L("command.blockstate.cleanup_success", countDeleted));
}
});
}
return true;
}
/**
* Modifies the BlockState-Database and sets all blocks in the selection to the provided gamemode. Set it
* to "creative" to disable drop of this block on destroying. Set it to "survival" to allow it.
* WorldEdit is required, because the selection Region is used.
* gamemode can be: survival / creative / adventure / s / c / a / 0 / 1 / 2
* @throws MissingPermissionCommandException
*/
@IsCommand("set")
@Usages("<gamemode>")
public boolean setGameMode(final CommandContext context, String... args) throws CommandException, MissingPermissionCommandException {
if (!mod.getPlugin().getServer().getPluginManager().isPluginEnabled("WorldEdit")) {
help.execute(context, new String[]{"set"});
context.response(L("command.blockstate.requires_worldedit"));
return true;
}
if (!context.isPlayer()) {
context.response(L("cmdblock.blocked.not_console"));
return true;
}
if (args.length < 1) {// doesn't count parameters
return false;
}
if (mod.getConfig().getIgnoredWorlds().contains(context.getPlayer().getWorld().getName())) {
context.response(L("command.blockstate.world_ignored", context.getPlayer().getWorld().getName()));
return true;
}
String gm = args[0].toLowerCase();
final GameMode tgm;
if (gm.equals("0") || gm.equals("s") || gm.equals("survival"))
tgm = GameMode.SURVIVAL;
else if (gm.equals("1") || gm.equals("c") || gm.equals("creative"))
tgm = GameMode.CREATIVE;
else if (gm.equals("2") || gm.equals("a") || gm.equals("adventure"))
tgm = GameMode.ADVENTURE;
else {
return false;
}
BukkitPlayer bp = BukkitAdapter.adapt(context.getPlayer());
Region region = null;
try {
region = WorldEdit.getInstance().getSessionManager().get(bp).getSelection(bp.getWorld());
} catch (Exception ignored) { //IncompleteRegionException
}
final Region selection = region;
if (selection == null) {
context.response(L("command.blockstate.worledit_selection_empty"));
return true;
}
final BlockVector3 min = selection.getMinimumPoint();
final BlockVector3 max = selection.getMaximumPoint();
mod.getPlugin().getServer().getScheduler().runTaskAsynchronously(mod.getPlugin(), () -> {
if (mod.isDebug())
mod.getLog().debug("Scheduler: Asynchronous Task run");
DBTransaction update = mod.getModel().groupUpdate();
int count = 0;
World w = selection.getWorld();
assert w != null;
org.bukkit.World bw = BukkitAdapter.adapt(w);
Cuboid c = new Cuboid();
c.add(new Location(bw, min.getBlockX(), min.getBlockY(), min.getBlockZ()));
c.add(new Location(bw, max.getBlockX(), max.getBlockY(), max.getBlockZ()));
mod.getModel().cacheStates(c);
BlockState seed = new BlockState();
seed.setPlayer(context.getPlayer());
seed.setGameMode(tgm);
seed.setSource(Source.COMMAND);
seed.setDate(new Date());
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
BlockVector3 loc = BlockVector3.at(x, y, z);
if (!w.getBlock(loc).getBlockType().getMaterial().isAir() && selection.contains(loc)) {
seed.setLocation(new Location(bw, x, y, z));
update.setState(new BlockState(seed));
count++;
}
}
}
}
update.finish();
context.response(L("command.blockstate.command_updated", count));
});
return true;
}
/**
* Imports BlockState Data from a given Database to the current active Database.
* A Server-Restart is needed after migration!
* Parameters:
* -u --update Don't delete existing records / only overwrite if newer
* --import=<type> Import from other Plugins. Supported Types:
* cc CreativeControl
*/
@IsCommand("migrate")
@Usages("-u --import=cc <dsn> [username] [password]")
public boolean migrateDatabase(final CommandContext context, String... args) throws CommandException, MissingPermissionCommandException {
DefinedParameterParser params = new DefinedParameterParser(args, new String[]{"debug", "d", "update", "u", "confirm"});
if (params.getArgumentCount() < 1) {// doesn't count parameters
return false;
}
if (Bukkit.getServer().getOnlinePlayers().size() > (context.isPlayer() ? 1 : 0)) {
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migrate_useronline_error"));
return true;
}
Database source;
Database target;
try {
if (params.getArgumentCount() < 2)
source = DBHelper.createConnection(params.getArgument(0));
else if (params.getArgumentCount() < 3)
source = DBHelper.createConnection(params.getArgument(0), params.getArgument(1), null);
else
source = DBHelper.createConnection(params.getArgument(0), params.getArgument(1), params.getArgument(2));
target = mod.getPlugin().getDatabaseConnection();
} catch (DatabaseConfigurationException e) {
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migrate_connect_error", e.getMessage()));
return true;
}
DatabaseMigrationThread thread;
if (params.getParameter("import") != null) {
if (params.getParameter("import").equals("cc")) {
thread = new CreativeControlImportThread(mod, context, source, target);
} else {
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migrate_importtype_error", params.getParameter("import")));
return false;
}
} else {
thread = new DatabaseMigrationThread(mod, context, source, target);
}
if (params.getFlags().contains("update") || params.getFlags().contains("u")) {
thread.setMode(DatabaseMigrationThread.Mode.UPDATE);
}
if (params.getFlags().contains("debug") || params.getFlags().contains("d")) {
thread.setDebug(true);
}
if (!params.getFlags().contains("confirm")) {
context.responseFormatted(ChatFormattings.INFO, L("command.blockstate.migrate_confirm", "--confirm"));
return true;
}
mod.getModuleEntry().disable();
thread.start();
String sourceType = source.getType().toString();
if (params.getParameter("import") != null) {
if (params.getParameter("import").equals("cc")) {
sourceType = "CreativeControl-" + sourceType;
}
}
context.response(L("command.blockstate.migrate_started", sourceType, target.getType()));
return true;
}
private String L(String msg, Object... args) {
return mod.getPlugin().getLocale().trans(msg, args);
}
}

View file

@ -4,15 +4,18 @@ import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.bukkit.lib.configuration.StringList;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* BlockState-Feature
@ -20,11 +23,16 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/blockstate/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class BlockStateConfig extends Configuration implements IConfigurationSubGroup {
protected ModBlockStates mod;
protected ModuleEntry<IModule> entry;
public BlockStateConfig(ConfigurationContainer container) {
super(container);
}
public BlockStateConfig(ModBlockStates mod, ModuleEntry<IModule> modEntry) {
super(mod.getPlugin().getDocCommentStorage());
this.mod = mod;
entry = modEntry;
}
@ -36,20 +44,20 @@ public class BlockStateConfig extends Configuration implements IConfigurationSub
else
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.setEnabled(getEnabled());
} else if (node.getName().equals("useThreading")) {
if (entry.isEnabled()) {
entry.disable();
entry.enable();
}
}
}
@Override
public void setValues(ConfigurationSection sect) {
ignoredWorlds = null;
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
}
@Override
public String getName() {
@ -63,23 +71,39 @@ public class BlockStateConfig extends Configuration implements IConfigurationSub
/**
* BlockStateEnabled
*
* This experimental Feature stores the GameMode a Block was created in, and prevents drops if a Block was created
* This Feature stores the GameMode a Block was created in, and prevents drops if a Block was created
* in creative mode.
*
* Due to the Experimental state this Feature isn't enabled by default. It uses the Database-credentials from
* Due to the huge load of this Feature, it isn't enabled by default. It uses the Database-credentials from
* bukkit.yml (http://wiki.bukkit.org/Bukkit.yml#database) in the server-directory.
*
* default: false
*/
@IsConfigurationNode(order = 100)
public boolean getEnabled() {
return config.getBoolean("enabled", true);
return config.getBoolean("enabled", false);
}
/**
* BlockStateThreading
*
* Uses Threading to minimize lag. This fully relies on Bukkit metadata implementation. You only should need this,
* if there are often plays more then 10 players at once on your server, or you're about to use huge WorldEdits often.
* Be aware that this requires more memory, to increase the performance
*
* Without threading, huge WorldEdits becomes much noticeable slower.
*
* default: true
*/
@IsConfigurationNode(order = 150)
public boolean getUseThreading() {
return config.getBoolean("useThreading", true);
}
/**
* BlockStateTool
*
* The id or technical name (http://tinyurl.com/bukkit-material) of an item that displays information about the
* The id or technical name (http://public.ja-s.de/bukkit/material) of an item that displays information about the
* right-clicked block.
*
* default: WOOD_PICKAXE
@ -103,6 +127,51 @@ public class BlockStateConfig extends Configuration implements IConfigurationSub
return Material.WOOD_PICKAXE;
}
/**
* BlockStateLogSurvival
*
* Log all Block-Places to the database. Disable to make the database more slim by not adding blocks placed in
* survival-mode.
*
* default: false
*/
@IsConfigurationNode(order = 400)
public boolean getLogSurvival() {
return config.getBoolean("logSurvival", false);
}
private StringList ignoredWorlds = null;
/**
* BlockStateIgnoredWorlds
*
* While you may use per world permissions to configure limitations fine graded, you may want to disable the
* BlockState-Feature for certain worlds (like complete creative worlds) to save cpu and memory.
*
* default: []
*/
@IsConfigurationNode(order = 500)
public StringList getIgnoredWorlds() {
if (ignoredWorlds == null) {
ignoredWorlds = new StringList(config.getStringList("ignoredWorlds"));
}
return ignoredWorlds;
}
/**
* BlockStateWorldEditIntegration
*
* Allows you to disable hook into WorldEdit for better Performance. By default Integration is enable, so it logs
* block modifications via worldedit as creative-placed blocks in the database.
* A server reload (better restart) is needed to disabled WE-Integration.
*
* default: true
*/
@IsConfigurationNode(order = 600)
public boolean getWorldeditIntegration() {
return config.getBoolean("worldeditIntegration", true);
}
protected void setTool(Object val) throws InvalidValueException {
String v = (String) val;
Material m = null;

View file

@ -20,6 +20,7 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
@ -33,11 +34,21 @@ public class BlockStatePermissions extends SimplePermissionContainerNode {
super(parent, name);
}
@PluginPermissions
public static final IPermissionContainer PARENT = new BlockStatePermissions(Permissions.CONTAINER, "blockstate");
/**
* Grants ability to use the configured tool to get info about placed blocks.
*/
public static final IPermission TOOL = new BasicPermission(PARENT, "tool", PermissionDefault.OP);
/**
* Grants access to the blockstate admin command to modify the database.
*/
public static final IPermission COMMAND = new BasicPermission(PARENT, "command", PermissionDefault.OP);
/**
* Allows to get drops even if a block was created from a creative player or WorldEdit.
*/
public static final IPermission BYPASS = new BasicPermission(PARENT, "bypass", PermissionDefault.FALSE);
}

View file

@ -0,0 +1,140 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
import de.jaschastarke.bukkit.lib.commands.CommandContext;
import de.jaschastarke.bukkit.lib.database.ResultIterator;
import de.jaschastarke.database.db.Database;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
public class CreativeControlImportThread extends DatabaseMigrationThread {
public CreativeControlImportThread(ModBlockStates mod, CommandContext context, Database source, Database target) {
super(mod, context, source, target);
}
@Override
public void run() {
try {
if (!target.isInTransaction())
target.startTransaction();
int rowCount = 0;
Connection sourceConnection = source.getConnection();
Connection targetConnection = target.getConnection();
if (mode == Mode.REPLACE) {
targetConnection.createStatement().execute("DELETE FROM lc_block_state");
}
DBQueries targetDB = new DBQueries(this, target);
List<WorldSize> worldBounds = new ArrayList<WorldSize>();
for (World w : mod.getPlugin().getServer().getWorlds()) {
try {
ResultSet fetchBounds = sourceConnection.createStatement().executeQuery("SELECT MIN(x), MIN(z), MAX(x), MAX(z) FROM crcr_blocks_" + w.getName());
while (fetchBounds.next()) {
worldBounds.add(new WorldSize(w,
fetchBounds.getInt(1),
fetchBounds.getInt(2),
fetchBounds.getInt(3),
fetchBounds.getInt(4)));
}
fetchBounds.close();
} catch (SQLException e) {
if (isDebug())
mod.getLog().debug("crcr_blocks_" + w.getName() + " not found: " + e.getMessage());
mod.getLog().info("CreativeControl has BlockData for World " + w.getName());
}
}
for (WorldSize bounds : worldBounds) {
World world = mod.getPlugin().getServer().getWorld(bounds.getWorld());
if (world != null) {
long time = System.currentTimeMillis();
int itCount = 0;
if (mod.isDebug())
mod.getLog().debug("Processing world " + world.getName() + " with bounds: " + bounds);
for (int x = bounds.getMinX(); x <= bounds.getMaxX(); x += CHUNK_SIZE + 1) {
for (int z = bounds.getMinZ(); z <= bounds.getMaxZ(); z += CHUNK_SIZE + 1) {
Cuboid c = new Cuboid();
c.add(new Location(world, x, 0, z));
c.add(new Location(world, x + CHUNK_SIZE, world.getMaxHeight(), z + CHUNK_SIZE));
if (mod.isDebug())
mod.getLog().debug("Fetching Cuboid: " + c.toString());
for (BlockState bs : iterateAllIn(c)) {
if (mode == Mode.UPDATE) {
BlockState xs = targetDB.find(bs.getLocation());
if (xs == null) {
targetDB.insert(bs);
} else if (xs.getDate().before(bs.getDate())) {
targetDB.update(bs);
}
} else {
targetDB.insert(bs);
}
rowCount++;
itCount++;
}
Thread.yield();
}
}
String region = "Region{world = " + world.getName() + ", x = [" + bounds.getMinX() + "; " + (bounds.getMinX() + CHUNK_SIZE) + "], z = [" + bounds.getMinZ() + "; " + (bounds.getMinZ() + CHUNK_SIZE) + "]}";
mod.getLog().info("Migration processed " + itCount + " BlockStates in " + region + " within " + ((System.currentTimeMillis() - time) / 1000.0) + " seconds");
}
}
target.endTransaction();
context.responseFormatted(ChatFormattings.SUCCESS, L("command.blockstate.migration_finished", rowCount) + " " +
context.getFormatter().formatString(ChatFormattings.ERROR, L("command.blockstate.migration_finished_restart")));
} catch (SQLException e) {
try {
target.revertTransaction();
} catch (SQLException e1) {}
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migration_error", e.getMessage()));
}
}
private PreparedStatement findall = null;
private Iterable<BlockState> iterateAllIn(final DBModel.Cuboid c) throws SQLException {
if (isDebug())
getLog().debug("DBQuery: iterateAllIn: " + c.toString());
if (findall == null) {
findall = source.prepare("SELECT * FROM crcr_blocks_" + c.getWorld().getName() + " LEFT JOIN crcr_players ON owner = id WHERE x >= ? AND x <= ? AND y >= ? AND y <= ? AND z >= ? AND z <= ?");
}
findall.setInt(1, c.getMinX());
findall.setInt(2, c.getMaxX());
findall.setInt(3, c.getMinY());
findall.setInt(4, c.getMaxY());
findall.setInt(5, c.getMinZ());
findall.setInt(6, c.getMaxZ());
ResultSet rs = findall.executeQuery();
return new ResultIterator<BlockState>(rs) {
@Override
protected BlockState fetch(ResultSet rs) throws SQLException {
BlockState bs = new BlockState();
bs.setLocation(new Location(c.getWorld(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z")));
bs.setDate(new Date(rs.getLong("time")));
bs.setGameMode(GameMode.CREATIVE);
bs.setPlayerNameOrUUID(rs.getString("player"));
bs.setSource(Source.PLAYER);
return bs;
}
};
}
}

View file

@ -0,0 +1,92 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.util.List;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
public interface DBModel {
public static class Cuboid {
private World w = null;
private int minx, miny, minz;
private int maxx, maxy, maxz;
public void add(Location loc) {
if (w == null) {
w = loc.getWorld();
minx = maxx = loc.getBlockX();
miny = maxy = loc.getBlockY();
minz = maxz = loc.getBlockZ();
} else {
if (w != loc.getWorld())
throw new IllegalArgumentException("Point is from a different world");
if (minx > loc.getBlockX())
minx = loc.getBlockX();
if (maxx < loc.getBlockX())
maxx = loc.getBlockX();
if (miny > loc.getBlockY())
miny = loc.getBlockY();
if (maxy < loc.getBlockY())
maxy = loc.getBlockY();
if (minz > loc.getBlockZ())
minz = loc.getBlockZ();
if (maxz < loc.getBlockZ())
maxz = loc.getBlockZ();
}
}
public int getMinX() {
return minx;
}
public int getMinY() {
return miny;
}
public int getMinZ() {
return minz;
}
public int getMaxX() {
return maxx;
}
public int getMaxY() {
return maxy;
}
public int getMaxZ() {
return maxz;
}
public World getWorld() {
return w;
}
public boolean isEmpty() {
return w == null;
}
public String toString() {
return "Cuboid{world="+w.getName()+", min_x="+minx+", max_x="+maxx+", min_y="+miny+", max_y="+maxy+", min_z="+minz+", max_z="+maxz+"}";
}
}
public enum Cleanup {
SURVIVAL;
}
public void onEnable() throws Exception;
public void onDisable();
public void moveState(Block from, Block to);
public void removeState(BlockState state);
public void removeState(Block block);
public Map<Block, BlockState> getStates(List<Block> blocks);
public Map<Block, Boolean> getRestrictedStates(List<Block> blocks);
public void cacheStates(DBModel.Cuboid c);
public BlockState getState(Block block);
public boolean isRestricted(Block block);
public void setState(BlockState state);
public DBTransaction groupUpdate();
public static interface DBTransaction {
public void moveState(Block from, Block to);
public void setState(BlockState state);
public void removeState(Block block);
public void finish();
}
public int cleanUp(Cleanup target);
}

View file

@ -3,22 +3,32 @@ package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.GameMode;
import org.bukkit.Location;
import de.jaschastarke.bukkit.lib.database.ResultIterator;
import de.jaschastarke.database.Type;
import de.jaschastarke.database.db.Database;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cleanup;
import de.jaschastarke.utils.IDebugLogHolder;
public class DBQueries {
private Database db;
public DBQueries(Database db) {
private IDebugLogHolder dbg;
public DBQueries(IDebugLogHolder mod, Database db) {
this.dbg = mod;
this.db = db;
}
private PreparedStatement find = null;
public BlockState find(Location loc) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: find: " + loc.toString());
if (find == null) {
find = db.prepare("SELECT * FROM lc_block_state WHERE x = ? AND y = ? AND z = ? AND world = ?");
}
@ -30,42 +40,174 @@ public class DBQueries {
if (rs.next()) {
BlockState bs = new BlockState();
bs.setLocation(loc);
bs.setDate(rs.getDate("cdate"));
bs.setDate(rs.getTimestamp("cdate"));
bs.setGameMode(getGameMode(rs));
bs.setPlayerName(rs.getString("player"));
bs.setPlayerNameOrUUID(rs.getString("player"));
bs.setSource(getSource(rs));
rs.close();
return bs;
}
rs.close();
return null;
}
private PreparedStatement findall = null;
public List<BlockState> findAllIn(DBModel.Cuboid c) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: findAllIn: " + c.toString());
List<BlockState> blocks = new ArrayList<BlockState>();
if (findall == null) {
findall = db.prepare("SELECT * FROM lc_block_state WHERE x >= ? AND x <= ? AND y >= ? AND y <= ? AND z >= ? AND z <= ? AND world = ?");
}
findall.setInt(1, c.getMinX());
findall.setInt(2, c.getMaxX());
findall.setInt(3, c.getMinY());
findall.setInt(4, c.getMaxY());
findall.setInt(5, c.getMinZ());
findall.setInt(6, c.getMaxZ());
findall.setString(7, c.getWorld().getUID().toString());
ResultSet rs = findall.executeQuery();
while (rs.next()) {
BlockState bs = new BlockState();
bs.setLocation(new Location(c.getWorld(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z")));
bs.setDate(rs.getTimestamp("cdate"));
bs.setGameMode(getGameMode(rs));
bs.setPlayerNameOrUUID(rs.getString("player"));
bs.setSource(getSource(rs));
blocks.add(bs);
}
rs.close();
return blocks;
}
public Iterable<BlockState> iterateAllIn(final DBModel.Cuboid c) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: iterateAllIn: " + c.toString());
if (findall == null) {
findall = db.prepare("SELECT * FROM lc_block_state WHERE x >= ? AND x <= ? AND y >= ? AND y <= ? AND z >= ? AND z <= ? AND world = ?");
}
findall.setInt(1, c.getMinX());
findall.setInt(2, c.getMaxX());
findall.setInt(3, c.getMinY());
findall.setInt(4, c.getMaxY());
findall.setInt(5, c.getMinZ());
findall.setInt(6, c.getMaxZ());
findall.setString(7, c.getWorld().getUID().toString());
ResultSet rs = findall.executeQuery();
return new ResultIterator<BlockState>(rs) {
@Override
protected BlockState fetch(ResultSet rs) throws SQLException {
BlockState bs = new BlockState();
bs.setLocation(new Location(c.getWorld(), rs.getInt("x"), rs.getInt("y"), rs.getInt("z")));
bs.setDate(rs.getTimestamp("cdate"));
bs.setGameMode(getGameMode(rs));
bs.setPlayerNameOrUUID(rs.getString("player"));
bs.setSource(getSource(rs));
return bs;
}
return null;
};
}
private PreparedStatement delete = null;
public boolean delete(BlockState s) throws SQLException {
return delete(s.getLocation());
}
public boolean delete(Location loc) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: delete: " + loc.toString());
if (delete == null) {
delete = db.prepare("DELETE FROM lc_block_state WHERE x = ? AND y = ? AND z = ? AND world = ?");
}
delete.setInt(1, s.getLocation().getBlockX());
delete.setInt(2, s.getLocation().getBlockY());
delete.setInt(3, s.getLocation().getBlockZ());
delete.setString(4, s.getLocation().getWorld().getUID().toString());
delete.setInt(1, loc.getBlockX());
delete.setInt(2, loc.getBlockY());
delete.setInt(3, loc.getBlockZ());
delete.setString(4, loc.getWorld().getUID().toString());
return delete.executeUpdate() > 0;
}
private PreparedStatement update = null;
public boolean update(BlockState s) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: update: " + s.toString());
if (update == null) {
update = db.prepare("UPDATE lc_block_state SET gm = ?, player = ?, cdate = ?, source = ?"+
"WHERE x = ? AND y = ? AND z = ? AND world = ? ");
}
if (s.getGameMode() == null)
update.setNull(1, Types.INTEGER);
else if (db.getType() == Type.MySQL)
update.setString(1, s.getGameMode().name());
else
update.setInt(1, s.getGameMode().getValue());
update.setString(2, s.getPlayerUUID().toString());
update.setTimestamp(3, new java.sql.Timestamp(s.getDate().getTime()));
if (db.getType() == Type.MySQL)
update.setString(4, s.getSource().name());
else
update.setInt(4, s.getSource().ordinal());
update.setInt(5, s.getLocation().getBlockX());
update.setInt(6, s.getLocation().getBlockY());
update.setInt(7, s.getLocation().getBlockZ());
update.setString(8, s.getLocation().getWorld().getUID().toString());
return update.executeUpdate() > 0;
}
private PreparedStatement move = null;
public boolean move(BlockState s, Location newLoc) throws SQLException {
boolean r = move(s.getLocation(), newLoc);
if (r)
s.setLocation(newLoc);
return r;
}
public boolean move(Location oldLoc, Location newLoc) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: move: " + oldLoc.toString() + ", " + newLoc.toString());
if (move == null) {
move = db.prepare("UPDATE lc_block_state SET x = ?, y = ?, z = ? "+
"WHERE x = ? AND y = ? AND z = ? AND world = ?");
}
move.setInt(1, newLoc.getBlockX());
move.setInt(2, newLoc.getBlockY());
move.setInt(3, newLoc.getBlockZ());
move.setInt(4, oldLoc.getBlockX());
move.setInt(5, oldLoc.getBlockY());
move.setInt(6, oldLoc.getBlockZ());
move.setString(7, oldLoc.getWorld().getUID().toString());
return move.executeUpdate() > 0;
}
/*private PreparedStatement replace = null;
public boolean replace(BlockState s) throws SQLException {
if (replace == null) {
replace = db.prepare("INSERT OR REPLACE INTO lc_block_state (x, y, z, world, gm, player, cdate, source)"+
" VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
}
return this._executeInsert(replace, s);
}*/
private PreparedStatement insert = null;
public boolean insert(BlockState s) throws SQLException {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: insert: " + s.toString());
if (insert == null) {
insert = db.prepare("INSERT INTO lc_block_state (x, y, z, world, gm, player, cdate, source)"+
" VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
}
return this._executeInsert(insert, s);
}
private boolean _executeInsert(PreparedStatement insert, BlockState s) throws SQLException {
insert.setInt(1, s.getLocation().getBlockX());
insert.setInt(2, s.getLocation().getBlockY());
insert.setInt(3, s.getLocation().getBlockZ());
insert.setString(4, s.getLocation().getWorld().getUID().toString());
if (db.getType() == Type.MySQL)
if (s.getGameMode() == null)
insert.setNull(5, Types.INTEGER);
else if (db.getType() == Type.MySQL)
insert.setString(5, s.getGameMode().name());
else
insert.setInt(5, s.getGameMode().getValue());
insert.setString(6, s.getPlayerName());
insert.setString(6, s.getPlayerUUID().toString());
insert.setTimestamp(7, new java.sql.Timestamp(s.getDate().getTime()));
if (db.getType() == Type.MySQL)
insert.setString(8, s.getSource().name());
@ -78,8 +220,13 @@ public class DBQueries {
try {
switch (db.getType()) {
case SQLite:
return GameMode.getByValue(rs.getInt("gm"));
int gm = rs.getInt("gm");
if (rs.wasNull())
return null;
return GameMode.getByValue(gm);
case MySQL:
if (rs.getString("gm") == null)
return null;
return GameMode.valueOf(rs.getString("gm"));
default:
throw new RuntimeException("Unsupported Database-Type.");
@ -110,6 +257,8 @@ public class DBQueries {
switch (db.getType()) {
case SQLite:
if (!db.getDDL().tableExists("lc_block_state")) {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: initTable SQLite: lc_block_state");
db.execute(
"CREATE TABLE lc_block_state ("+
"x integer,"+
@ -122,14 +271,16 @@ public class DBQueries {
"source integer not null,"+
"primary key (x, y, z, world),"+
"constraint ck_lc_block_state_gm check (gm in (0,1,2)),"+
"constraint ck_lc_block_state_source check (source in (0,1,2,3))"+
"constraint ck_lc_block_state_source check (source in (0,1,2,3,4))"+
")"
);
).close();
db.getLogger().info("Created SQLite-Table: lc_block_state");
}
break;
case MySQL:
if (!db.getDDL().tableExists("lc_block_state")) {
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: initTable MySQL: lc_block_state");
db.execute(
"CREATE TABLE IF NOT EXISTS lc_block_state ("+
"x INT NOT NULL,"+
@ -139,15 +290,35 @@ public class DBQueries {
"gm ENUM('CREATIVE', 'SURVIVAL', 'ADVENTURE'),"+
"player VARCHAR(255),"+
"cdate TIMESTAMP NOT NULL,"+
"source ENUM('SEED','PLAYER','EDIT','UNKNOWN'),"+
"source ENUM('SEED','PLAYER','EDIT','COMMAND','UNKNOWN') NOT NULL,"+
"PRIMARY KEY (x, y, z, world)"+
")"
);
).close();
db.getLogger().info("Created MySQL-Table: lc_block_state");
}
break;
default:
throw new RuntimeException("Currently only SQLite is supported.");
throw new RuntimeException("Currently only SQLite or MySQL is supported.");
}
}
public int cleanup(Cleanup q) throws SQLException {
PreparedStatement delete;
if (dbg.isDebug())
dbg.getLog().debug("DBQuery: cleanup: " + q.toString());
if (q == Cleanup.SURVIVAL) {
delete = db.prepare("DELETE FROM lc_block_state WHERE gm = ?");
if (db.getType() == Type.MySQL)
delete.setString(1, GameMode.SURVIVAL.name());
else
delete.setInt(1, GameMode.SURVIVAL.getValue());
} else {
return -1;
}
return delete.executeUpdate();
}
public Database getDB() {
return db;
}
}

View file

@ -0,0 +1,186 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
import de.jaschastarke.bukkit.lib.commands.CommandContext;
import de.jaschastarke.database.db.Database;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
import de.jaschastarke.utils.IDebugLogHolder;
import de.jaschastarke.utils.ISimpleLogger;
public class DatabaseMigrationThread extends Thread implements IDebugLogHolder {
protected static final int CHUNK_SIZE = 512;
protected ModBlockStates mod;
protected CommandContext context;
protected Database source;
protected Database target;
protected Mode mode = Mode.REPLACE;
private boolean debug = false;
public static enum Mode {
REPLACE,
UPDATE
}
public DatabaseMigrationThread(ModBlockStates mod, CommandContext context, Database source, Database target) {
this.mod = mod;
this.context = context;
this.source = source;
this.target = target;
setName("LC BlockState Database-Migration");
setPriority(MIN_PRIORITY);
}
public Mode getMode() {
return mode;
}
public void setMode(Mode mode) {
this.mode = mode;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
@Override
public boolean isDebug() {
return debug;
}
@Override
public ISimpleLogger getLog() {
return mod.getLog();
}
@Override
public void run() {
try {
if (!target.isInTransaction())
target.startTransaction();
int rowCount = 0;
Connection sourceConnection = source.getConnection();
Connection targetConnection = target.getConnection();
if (mode == Mode.REPLACE) {
targetConnection.createStatement().execute("DELETE FROM lc_block_state");
}
DBQueries sourceDB = new DBQueries(this, source);
DBQueries targetDB = new DBQueries(this, target);
List<WorldSize> worldBounds = new ArrayList<WorldSize>();
ResultSet fetchBounds = sourceConnection.createStatement().executeQuery("SELECT world, MIN(x), MIN(z), MAX(x), MAX(z) FROM lc_block_state GROUP BY world");
while (fetchBounds.next()) {
worldBounds.add(new WorldSize(fetchBounds.getString("world"),
fetchBounds.getInt(2),
fetchBounds.getInt(3),
fetchBounds.getInt(4),
fetchBounds.getInt(5)));
}
fetchBounds.close();
for (WorldSize bounds : worldBounds) {
World world = mod.getPlugin().getServer().getWorld(bounds.getWorld());
if (world != null) {
long time = System.currentTimeMillis();
int itCount = 0;
if (mod.isDebug())
mod.getLog().debug("Processing world " + world.getName() + " with bounds: " + bounds);
for (int x = bounds.getMinX(); x <= bounds.getMaxX(); x += CHUNK_SIZE + 1) {
for (int z = bounds.getMinZ(); z <= bounds.getMaxZ(); z += CHUNK_SIZE + 1) {
Cuboid c = new Cuboid();
c.add(new Location(world, x, 0, z));
c.add(new Location(world, x + CHUNK_SIZE, world.getMaxHeight(), z + CHUNK_SIZE));
if (mod.isDebug())
mod.getLog().debug("Fetching Cuboid: " + c.toString());
for (BlockState bs : sourceDB.iterateAllIn(c)) {
if (mode == Mode.UPDATE) {
BlockState xs = targetDB.find(bs.getLocation());
if (xs == null) {
targetDB.insert(bs);
} else if (xs.getDate().before(bs.getDate())) {
targetDB.update(bs);
}
} else {
targetDB.insert(bs);
}
rowCount++;
itCount++;
}
Thread.yield();
}
}
String region = "Region{world = " + world.getName() + ", x = [" + bounds.getMinX() + "; " + (bounds.getMinX() + CHUNK_SIZE) + "], z = [" + bounds.getMinZ() + "; " + (bounds.getMinZ() + CHUNK_SIZE) + "]}";
mod.getLog().info("Migration processed " + itCount + " BlockStates in " + region + " within " + ((System.currentTimeMillis() - time) / 1000.0) + " seconds");
}
}
target.endTransaction();
context.responseFormatted(ChatFormattings.SUCCESS, L("command.blockstate.migration_finished", rowCount) + " " +
context.getFormatter().formatString(ChatFormattings.ERROR, L("command.blockstate.migration_finished_restart")));
} catch (SQLException e) {
try {
target.revertTransaction();
} catch (SQLException e1) {}
context.responseFormatted(ChatFormattings.ERROR, L("command.blockstate.migration_error", e.getMessage()));
}
}
protected String L(String msg, Object... args) {
return mod.getPlugin().getLocale().trans(msg, args);
}
protected static class WorldSize {
UUID w;
int minX, minZ, maxX, maxZ;
public WorldSize(String w, int minX, int minZ, int maxX, int maxZ) {
this.w = UUID.fromString(w);
this.minX = minX;
this.minZ = minZ;
this.maxX = maxX;
this.maxZ = maxZ;
}
public WorldSize(World w, int minX, int minZ, int maxX, int maxZ) {
this.w = w.getUID();
this.minX = minX;
this.minZ = minZ;
this.maxX = maxX;
this.maxZ = maxZ;
}
public String toString() {
World world = Bukkit.getServer().getWorld(w);
String wn = world == null ? w.toString() : world.getName();
return getClass().getSimpleName() + "{world = " + wn + ", minX = " + minX + ", minZ = " + minZ + ", maxX = " + maxX + ", maxZ = " + maxZ + "}";
}
public UUID getWorld() {
return w;
}
public int getMinX() {
return minX;
}
public int getMinZ() {
return minZ;
}
public int getMaxX() {
return maxX;
}
public int getMaxZ() {
return maxZ;
}
}
}

View file

@ -0,0 +1,205 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.util.Date;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.hanging.HangingBreakEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
public class HangingStandingListener implements Listener {
private ModBlockStates mod;
public HangingStandingListener(ModBlockStates mod) {
this.mod = mod;
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getRightClicked().getWorld().getName()))
return;
if (event.getRightClicked() instanceof ItemFrame) {
if (mod.getModel().isRestricted(event.getRightClicked().getLocation().getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Modifying hanging: " + event.getRightClicked().getLocation().toString());
if (event.getPlayer().getGameMode() != GameMode.CREATIVE) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Modify prevented");
event.setCancelled(true);
}
} else {
BlockState s = new BlockState();
s.setLocation(event.getRightClicked().getLocation().getBlock().getLocation());
s.setPlayer(event.getPlayer());
s.setDate(new Date());
if (mod.isDebug())
mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getModel().setState(s);
}
} else if (event.getRightClicked() instanceof ArmorStand) {
if (mod.getModel().isRestricted(event.getRightClicked().getLocation().getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Modifying standing: " + event.getRightClicked().getLocation().toString());
if (event.getPlayer().getGameMode() != GameMode.CREATIVE) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Modify prevented");
event.setCancelled(true);
}
} else {
BlockState s = new BlockState();
s.setLocation(event.getRightClicked().getLocation().getBlock().getLocation());
s.setPlayer(event.getPlayer());
s.setDate(new Date());
if (mod.isDebug())
mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getModel().setState(s);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onArmorStandManipulateEvent(PlayerArmorStandManipulateEvent event) {
onPlayerInteractEntity(event);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPlayerLeftInteractEntity(EntityDamageByEntityEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getEntity().getWorld().getName()))
return;
if (event.getDamager() instanceof Player && event.getEntity() instanceof ItemFrame) {
if (mod.getModel().isRestricted(event.getEntity().getLocation().getBlock())) {
if (mod.isDebug())
mod.getLog().debug("Modifying hanging: " + event.getEntity().getLocation().toString());
if (((Player) event.getDamager()).getGameMode() != GameMode.CREATIVE) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Modify prevented");
event.setCancelled(true);
}
} else {
BlockState s = new BlockState();
s.setLocation(event.getEntity().getLocation().getBlock().getLocation());
s.setPlayer((Player) event.getDamager());
s.setDate(new Date());
if (mod.isDebug())
mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getModel().setState(s);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onHangingBreak(HangingBreakEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getEntity().getWorld().getName()))
return;
if (event.getEntity() instanceof ItemFrame) {
if (mod.isDebug())
mod.getLog().debug("Breaking hanging: " + event.getEntity().getLocation().toString());
if (mod.getModel().isRestricted(event.getEntity().getLocation().getBlock())) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Drop prevented");
mod.getBlockSpawn().block(event.getEntity().getLocation().getBlock().getLocation(), Material.ITEM_FRAME);
mod.getBlockSpawn().block(event.getEntity().getLocation().getBlock().getLocation(), ((ItemFrame) event.getEntity()).getItem().getType());
}
mod.getModel().removeState(event.getEntity().getLocation().getBlock());
}
}
protected void checkArmoryDestroy(ArmorStand entity, boolean deRemove) {
if (mod.isDebug())
mod.getLog().debug("Breaking standing: " + entity.getLocation().toString());
if (mod.getModel().isRestricted(entity.getLocation().getBlock())) {
if (mod.isDebug())
mod.getLog().debug("... was placed by creative. Drop prevented");
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), Material.ARMOR_STAND);
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), Material.ARMOR_STAND);
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), entity.getHelmet());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), entity.getChestplate());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), entity.getBoots());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), entity.getItemInHand());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getLocation(), entity.getLeggings());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), entity.getHelmet());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), entity.getChestplate());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), entity.getBoots());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), entity.getItemInHand());
mod.getBlockSpawn().block(entity.getLocation().getBlock().getRelative(BlockFace.UP).getLocation(), entity.getLeggings());
/*entity.setBoots(null);
entity.setChestplate(null);
entity.setHelmet(null);
entity.setItemInHand(null);
entity.setLeggings(null);*/
}
if (deRemove)
mod.getModel().removeState(entity.getLocation().getBlock());
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onStandingBreak(EntityDeathEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getEntity().getWorld().getName()))
return;
if (event.getEntity() instanceof ArmorStand) {
checkArmoryDestroy((ArmorStand) event.getEntity(), true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onStandingBreaking(EntityDamageByEntityEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getEntity().getWorld().getName()))
return;
if (event.getEntity() instanceof ArmorStand) {
// TODO: Bug in Spigot, we can not check for destroying yet. so the block state stays in DB :(
//if (event.getEntity().isDead() || ((ArmorStand) event.getEntity()).getHealth() <= event.getFinalDamage()) {
checkArmoryDestroy((ArmorStand) event.getEntity(), false);
//}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onHangingPlace(HangingPlaceEvent event) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getEntity().getWorld().getName()))
return;
if (event.getEntity() instanceof ItemFrame) {
BlockState s = new BlockState();
s.setLocation(event.getEntity().getLocation().getBlock().getLocation());
s.setPlayer(event.getPlayer());
s.setDate(new Date());
if (mod.isDebug())
mod.getLog().debug("Saving BlockState: " + s.toString());
mod.getModel().setState(s);
}
}
}

View file

@ -1,13 +1,17 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.SQLException;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
@ -23,42 +27,61 @@ public class PlayerListener implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onInteract(PlayerInteractEvent event) {
if (event.isCancelled())
return;
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && mod.getPlugin().getPermManager().hasPermission(event.getPlayer(), BlockStatePermissions.TOOL)) {
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Block b = event.getClickedBlock();
if (b != null && event.getPlayer().getItemInHand().getType().equals(mod.getConfig().getTool())) {
try {
BlockState s = mod.getQueries().find(b.getLocation());
if (b != null && event.getPlayer().getInventory().getItemInMainHand().getType().equals(mod.getConfig().getTool()) && mod.getPlugin().getPermManager().hasPermission(event.getPlayer(), BlockStatePermissions.TOOL)) {
if (mod.getConfig().getIgnoredWorlds().contains(event.getClickedBlock().getWorld().getName())) {
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("command.blockstate.world_ignored", event.getClickedBlock().getWorld().getName()));
} else {
showInfo(event.getPlayer(), b.getLocation(), b.getType());
}
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onInteractEntity(PlayerInteractEntityEvent event) {
Entity e = event.getRightClicked();
if (e != null && e instanceof ItemFrame && event.getPlayer().getInventory().getItemInMainHand().getType().equals(mod.getConfig().getTool()) && mod.getPlugin().getPermManager().hasPermission(event.getPlayer(), BlockStatePermissions.TOOL)) {
if (mod.getConfig().getIgnoredWorlds().contains(e.getWorld().getName())) {
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("command.blockstate.world_ignored", e.getWorld().getName()));
} else {
showInfo(event.getPlayer(), e.getLocation(), Material.ITEM_FRAME);
}
event.setCancelled(true);
}
}
private void showInfo(Player pl, Location loc, Material type) {
BlockState s = mod.getModel().getState(loc.getBlock());
InGameFormatter f = new InGameFormatter(mod.getPlugin().getLang());
String ret = null;
if (s == null || s.getSource() == Source.UNKNOWN) {
ret = f.formatString(ChatFormattings.ERROR, f.getString("block_state.tool_info.unknown", b.getType().toString()));
ret = f.formatString(ChatFormattings.ERROR, f.getString("block_state.tool_info.unknown", type.toString()));
} else {
String k = "block_state.tool_info." + s.getSource().name().toLowerCase();
String gm = s.getGameMode().toString().toLowerCase();
String gm = "";
if (s.getGameMode() != null) {
switch (s.getGameMode()) {
case CREATIVE:
gm = ChatColor.GOLD + gm + ChatColor.RESET;
gm = ChatColor.GOLD + s.getGameMode().toString().toLowerCase() + ChatColor.RESET;
break;
case SURVIVAL:
gm = ChatColor.GREEN + gm + ChatColor.RESET;
gm = ChatColor.GREEN + s.getGameMode().toString().toLowerCase() + ChatColor.RESET;
break;
case ADVENTURE:
gm = ChatColor.DARK_GREEN + gm + ChatColor.RESET;
gm = ChatColor.DARK_GREEN + s.getGameMode().toString().toLowerCase() + ChatColor.RESET;
break;
default:
break;
}
}
ret = f.formatString(ChatFormattings.INFO, f.getString(k, b.getType().toString(),
ret = f.formatString(ChatFormattings.INFO, f.getString(k, type.toString(),
s.getPlayerName(),
gm,
s.getDate()));
}
if (ret != null)
event.getPlayer().sendMessage(ret);
} catch (SQLException e) {
mod.getLog().warn("DB-Error while onPlayerInteract: "+e.getMessage());
}
}
}
pl.sendMessage(ret);
}
}

View file

@ -0,0 +1,212 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.block.Block;
import de.jaschastarke.database.DatabaseConfigurationException;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
/**
* @internal I'm not happy with the error-handling here, especially in the Transaction, but I'll focus on the asynchronous
* variant, where all errors have to be handled in a separate thread.
*/
public class SyncronizedModel extends AbstractModel implements DBModel {
private ModBlockStates mod;
private DBQueries q;
public SyncronizedModel(ModBlockStates mod) throws DatabaseConfigurationException {
super(mod.getPlugin());
this.mod = mod;
this.q = new DBQueries(mod, mod.getPlugin().getDatabaseConnection());
}
@Override
public void onEnable() throws SQLException {
this.q.initTable();
}
@Override
public void onDisable() {
}
public void moveState(Block from, Block to) {
try {
q.delete(to.getLocation());
q.move(from.getLocation(), to.getLocation());
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to move BlockState in DB from " + from.getLocation().toString() + " to " + to.getLocation().toString());
}
moveMetaState(from, to);
}
public void removeState(BlockState state) {
removeState(state.getLocation().getBlock());
}
@Override
public void removeState(Block block) {
setMetaBlock(block, null);
try {
q.delete(block.getLocation());
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to delete BlockState in DB from " + block.getLocation().toString());
}
}
@Override
public Map<Block, Boolean> getRestrictedStates(List<Block> blocks) {
Map<Block, Boolean> ret = new HashMap<Block, Boolean>();
for (Map.Entry<Block, BlockState> entry : getStates(blocks).entrySet()) {
ret.put(entry.getKey(), entry.getValue() != null && entry.getValue().isRestricted());
}
return ret;
}
public Map<Block, BlockState> getStates(List<Block> blocks) {
Map<Block, BlockState> ret = new HashMap<Block, BlockState>();
Cuboid c = new Cuboid();
for (Block block : blocks) {
HasBlockState has = getMetaBlock(block);
if (has.isSet()) {
ret.put(block, has.getState());
} else {
c.add(block.getLocation());
}
}
if (!c.isEmpty()) {
try {
List<BlockState> dbb = q.findAllIn(c);
for (BlockState bs : dbb) {
setMetaBlock(bs.getLocation().getBlock(), bs);
if (blocks.contains(bs.getLocation().getBlock()))
ret.put(bs.getLocation().getBlock(), bs);
}
for (Block block : blocks) {
if (!ret.containsKey(block)) {
ret.put(block, null);
setMetaBlock(block, null);
}
}
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to fetch BlockState from DB in " + c.toString());
}
}
return ret;
}
public void cacheStates(Cuboid c) {
if (!c.isEmpty()) {
try {
List<BlockState> dbb = q.findAllIn(c);
for (BlockState bs : dbb) {
setMetaBlock(bs.getLocation().getBlock(), bs);
}
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to fetch BlockState (for caching) from DB in " + c.toString());
}
}
}
@Override
public boolean isRestricted(Block block) {
BlockState state = getState(block);
return state != null ? state.isRestricted() : false;
}
public BlockState getState(Block block) {
HasBlockState has = getMetaBlock(block);
if (!has.isSet()) {
try {
BlockState state = q.find(block.getLocation());
setMetaBlock(block, state);
return state;
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to fetch BlockState (for caching) from DB at " + block.getLocation().toString());
return null;
}
}
return has.getState();
}
public void setState(BlockState state) {
Block block = state.getLocation().getBlock();
boolean store = state != null && (state.isRestricted() || mod.getConfig().getLogSurvival());
setMetaBlock(block, store ? state : null);
try {
if (!store)
q.delete(state);
else if (!q.update(state))
q.insert(state);
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to update BlockState in DB at " + block.getLocation().toString());
}
}
@Override
public DBTransaction groupUpdate() {
return new Transaction();
}
private class Transaction implements DBTransaction {
private boolean finished = false;
private Transaction() {
try {
q.getDB().startTransaction();
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
finished = true;
}
}
@Override
public void moveState(Block from, Block to) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
SyncronizedModel.this.moveState(from, to);
}
@Override
public void setState(BlockState state) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
SyncronizedModel.this.setState(state);
}
@Override
public void removeState(Block block) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
SyncronizedModel.this.removeState(block);
}
@Override
public void finish() {
try {
q.getDB().endTransaction();
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
} finally {
finished = true;
}
}
}
@Override
public int cleanUp(Cleanup target) {
try {
return q.cleanup(target);
} catch (SQLException e) {
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to cleanup BlockState-DB");
return -1;
}
}
}

View file

@ -0,0 +1,280 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.metadata.MetadataValue;
import org.bukkit.metadata.Metadatable;
import de.jaschastarke.database.DatabaseConfigurationException;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.thread.CallableAction;
import de.jaschastarke.minecraft.limitedcreative.blockstate.thread.ThreadLink;
import de.jaschastarke.minecraft.limitedcreative.blockstate.thread.Transaction;
public class ThreadedModel extends AbstractModel implements DBModel, Listener {
private ModBlockStates mod;
private ThreadLink threads;
private MetadataValue metadataSet;
private MetadataValue metadataSetRestricted;
public ThreadedModel(ModBlockStates mod) {
super(mod.getPlugin());
this.mod = mod;
metadataSet = new FixedMetadataValue(mod.getPlugin(), new Boolean(true));
metadataSetRestricted = new FixedMetadataValue(mod.getPlugin(), new Object());
}
@Override
public void onEnable() throws SQLException, DatabaseConfigurationException {
DBQueries queries = new DBQueries(mod, mod.getPlugin().getDatabaseConnection());
queries.initTable();
threads = new ThreadLink(this, queries);
// We don't keep any reference to queries, because it contains the DB-Connection, which should be only used
// from the thread from now on (as SQLite may not threadsafe)
for (World w : mod.getPlugin().getServer().getWorlds()) {
if (!mod.getConfig().getIgnoredWorlds().containsIgnoreCase(w.getName())) {
for (Chunk chunk : w.getLoadedChunks()) {
threads.queueChunkLoad(chunk);
}
}
}
threads.start();
}
@Override
public void onDisable() {
try {
threads.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
mod.getLog().severe("Failed to clean end Database-Thread, maybe BlockStates haven't been saved");
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onChunkLoad(ChunkLoadEvent event) {
if (!mod.getConfig().getIgnoredWorlds().containsIgnoreCase(event.getWorld().getName())) {
threads.queueChunkLoad(event.getChunk());
}
}
@Override
public void moveState(Block from, Block to) {
threads.queueMetaMove(from.getLocation(), to.getLocation());
moveMetaState(from, to);
}
@Override
public void removeState(BlockState state) {
removeState(state.getLocation().getBlock());
}
@Override
public void removeState(Block block) {
setMetaBlock(block, null);
threads.queueUpdate(block);
}
@Override
public Map<Block, Boolean> getRestrictedStates(List<Block> blocks) {
Map<Block, Boolean> ret = new HashMap<Block, Boolean>();
for (Block block : blocks) {
HasBlockState has = getMetaBlock(block);
ret.put(block, has.isRestricted());
}
return ret;
}
@Override
public Map<Block, BlockState> getStates(List<Block> blocks) {
Map<Block, BlockState> ret = new HashMap<Block, BlockState>();
Cuboid c;
do {
c = new Cuboid();
for (Block block : blocks) {
HasBlockState has = getMetaBlock(block);
if (has.getState() != null || has.isNull()) {
ret.put(block, has.getState());
} else {
c.add(block.getLocation());
ret.put(block, null);
}
}
if (!c.isEmpty())
threads.callUpdate(c);
} while(!c.isEmpty());
return ret;
}
@Override
public void cacheStates(Cuboid c) {
threads.callUpdate(c);
}
@Override
public BlockState getState(Block block) {
HasBlockState has = getMetaBlock(block);
if (has.getState() == null && !has.isNull()) {
// The DB-Entry isn't set
// and the entry doesn't tell us that it knows that it isn't set
// (while using the threaded model, even having no Metadata entry, tells us there is no one in DB)
return threads.callUpdate(block);
}
return has.getState();
}
@Override
public boolean isRestricted(Block block) {
return getMetaBlock(block).isRestricted();
}
@Override
public void setState(BlockState state) {
Block block = state.getLocation().getBlock();
boolean store = state.isRestricted() || mod.getConfig().getLogSurvival();
setMetaBlock(block, store ? state : null);
threads.queueUpdate(block);
}
@Override
public DBTransaction groupUpdate() {
return new GroupUpdate(threads);
}
private class GroupUpdate extends Transaction {
public GroupUpdate(ThreadLink threads) {
super(threads);
}
@Override
public void moveState(Block from, Block to) {
moveMetaState(from, to);
super.moveState(from, to);
}
@Override
public void setState(BlockState state) {
Block block = state.getLocation().getBlock();
boolean store = state.isRestricted() || mod.getConfig().getLogSurvival();
setMetaBlock(block, store ? state : null);
super.setState(state);
}
@Override
public void removeState(Block block) {
setMetaBlock(block, null);
super.setState(block);
}
}
/**
* Metadata-Interface for the Thread-Link
*/
public HasBlockState getMetaState(Block block) {
return getMetaBlock(block);
}
/**
* Metadata-Interface for the Thread-Link
*/
public void setMetaState(Block block, BlockState state) {
super.setMetaBlock(block, state);
}
public void setSimpleMetaDataState(Block block, BlockState state) {
if (state == null)
super.setMetaBlock(block, null);
else if (state.isRestricted())
block.setMetadata(BSMDKEY, metadataSetRestricted);
else
block.setMetadata(BSMDKEY, metadataSet);
}
protected HasBlockState getMetaBlock(Metadatable m) {
HasBlockState has = null;
List<MetadataValue> metadata = m.getMetadata(BSMDKEY);
for (MetadataValue v : metadata) {
if (v.value() instanceof BlockState) {
// The actual DB-entry is in Metadata (requires more memory)
has = new HasBlockState((BlockState) v.value());
break;
} else if (v.getOwningPlugin() == mod.getPlugin()) {
if (v == metadataNull) {
// Metadata knows, that there is no entry in DB
has = new HasBlockState(true);
break;
} else if (v == metadataSet) {
// Metadata knows, that there is survival-entry in DB
has = new HasBlockState(true, false);
break;
} else if (v == metadataSetRestricted) {
// Metadata knows, that there is creative-entry in DB
has = new HasBlockState(true, true);
}
break;
}
}
if (has == null)
return new HasBlockState(false);
else
return has;
}
public static class HasBlockState extends AbstractModel.HasBlockState {
private boolean restricted = false;
private boolean isNull = false;
public HasBlockState(BlockState state) {
super(state);
restricted = state.isRestricted();
}
public HasBlockState(boolean isSet) {
super(isSet);
isNull = true;
}
public HasBlockState(boolean isSet, boolean isRestricted) {
super(isSet);
restricted = isRestricted;
}
public boolean isRestricted() {
return restricted;
}
public boolean isNull() {
return isNull;
}
}
public ModBlockStates getModel() {
return mod;
}
@Override
public int cleanUp(final Cleanup target) {
return threads.call(new CallableAction<Integer>() {
@Override
public void process(ThreadLink link, DBQueries q) {
this.returnSet = true;
try {
this.returnValue = q.cleanup(target);
} catch (SQLException e) {
this.returnValue = -1;
mod.getLog().severe(e.getMessage());
mod.getLog().warn("Failed to cleanup BlockState-DB");
}
}
});
}
}

View file

@ -0,0 +1,11 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public interface Action {
/**
* @internal Executed from asynchronous Thread. Only Thread-Safe methods should be called.
*/
void process(ThreadLink link, DBQueries q);
}

View file

@ -0,0 +1,64 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Chunk;
import org.bukkit.block.Block;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public class CacheChunkAction implements Action {
private static final int CHUNK_SIZE = 16;
private Chunk chunk;
public CacheChunkAction(Chunk chunk) {
this.chunk = chunk;
}
@Override
public void process(ThreadLink link, DBQueries q) {
if (!chunk.isLoaded())
return;
Set<Block> knownBlocks = new HashSet<Block>();
try {
if (chunk.isLoaded()) {
for (BlockState state : q.findAllIn(getBlocks())) {
if (chunk.isLoaded()) {
Block b = state.getLocation().getBlock();
knownBlocks.add(b);
link.setSimpleMetaState(b, state);
}
}
}
/*int h = chunk.getWorld().getMaxHeight();
for (int y = 0; y < h; y++) {
for (int x = 0; x < CHUNK_SIZE; x++) {
for (int z = 0; z < CHUNK_SIZE; z++) {
Block b = chunk.getBlock(x, y, z);
if (!knownBlocks.contains(b) && b.getType() != Material.AIR) {
link.setSimpleMetaState(b, null);
link.blockCount++;
}
}
}
}*/
} catch (SQLException e) {
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to load BlockStates for Chunk " + chunk.getX() + "/" + chunk.getZ());
}
}
protected Cuboid getBlocks() {
Cuboid c = new Cuboid();
c.add(chunk.getBlock(0, 0, 0).getLocation());
int h = chunk.getWorld().getMaxHeight();
c.add(chunk.getBlock(CHUNK_SIZE - 1, h - 1, CHUNK_SIZE - 1).getLocation());
return c;
}
}

View file

@ -0,0 +1,18 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
public abstract class CallableAction<E> implements Action {
protected boolean returnSet = false;
protected E returnValue = null;
public E getValue() {
synchronized (this) {
try {
while (!returnSet)
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return returnValue;
}
}

View file

@ -0,0 +1,34 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import org.bukkit.block.Block;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public class FetchBlockStateAction extends CallableAction<BlockState> {
private Block block;
public FetchBlockStateAction(Block block) {
this.block = block;
}
@Override
public void process(ThreadLink link, DBQueries q) {
BlockState state = null;
try {
state = q.find(block.getLocation());
link.setMetaState(block, state);
} catch (SQLException e) {
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to fetch BlockState from DB: " + block.getLocation());
return;
}
synchronized (this) {
returnValue = state;
returnSet = true;
this.notify();
}
}
}

View file

@ -0,0 +1,36 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import java.util.List;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public class FetchCuboidAction extends CallableAction<List<BlockState>> {
private Cuboid cuboid;
public FetchCuboidAction(Cuboid cuboid) {
this.cuboid = cuboid;
}
@Override
public void process(ThreadLink link, DBQueries q) {
List<BlockState> states = null;
try {
states = q.findAllIn(cuboid);
for (BlockState bs : states) {
link.setMetaState(bs.getLocation().getBlock(), bs);
}
} catch (SQLException e) {
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to fetch BlockState from DB: " + cuboid);
return;
}
synchronized (this) {
returnValue = states;
returnSet = true;
this.notify();
}
}
}

View file

@ -0,0 +1,34 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import org.bukkit.Location;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public class MoveBlockStateAction extends TransactionAction implements Action {
private Location from;
private Location to;
public MoveBlockStateAction(Location from, Location to) {
this.from = from;
this.to = to;
}
@Override
public void process(ThreadLink link, DBQueries q) {
try {
processInTransaction(link, q);
} catch (SQLException e) {
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to move BlockState in DB from " + from.toString() + " to " + to.toString());
}
}
@Override
public void processInTransaction(ThreadLink link, DBQueries q) throws SQLException {
q.delete(to);
q.move(from, to);
}
}

View file

@ -0,0 +1,241 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import de.jaschastarke.bukkit.lib.ModuleLogger;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.AbstractModel.HasBlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.Cuboid;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
import de.jaschastarke.minecraft.limitedcreative.blockstate.ThreadedModel;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.block.Block;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class ThreadLink {
private static final int BATCH_ACTION_LENGTH = 25;
private static final int QUEUE_ACCESS_WARNING_DURATION = 5; // ms
private static final int COUNT_WARNING_QUEUE = 5;
private static final int COUNT_ERROR_QUEUE = 20;
private static final int QUEUE_TIMING_DURATION = 500; // ms
private static final int STARTUP_TIMING = 30000; // ms
private static final int THREAD_SHUTDOWN_WAIT_MS = 30000;
private long lastTimeout;
private final Stack<Action> updateQueue = new Stack<Action>();
private boolean shutdown;
private ModuleLogger log;
private ThreadedModel model;
private Thread thread;
public ThreadLink(ThreadedModel threadedModel, DBQueries queries) {
model = threadedModel;
log = threadedModel.getModel().getLog();
/*
* In theory we could add multiple threads, e.g. 1 write and 2 read threads.
*/
createThread(queries);
shutdown = true; //Don't allow the thread to run until it's started
}
private class DBThread extends Thread {
private DBQueries q;
public DBThread(DBQueries queries) {
super();
this.q = queries;
}
public void run() {
if (getModule().isDebug())
log.debug("DB-Thread '" + Thread.currentThread().getName() + "' started.");
lastTimeout = System.currentTimeMillis() + STARTUP_TIMING;
while (!shutdown || !updateQueue.isEmpty()) {
try {
//Thread.sleep(1000);
//throw new RuntimeException("Test exception pls ignore");
List<Action> acts = new LinkedList<Action>();
synchronized (updateQueue) {
while (updateQueue.isEmpty() && !shutdown)
updateQueue.wait();
if (updateQueue.size() > (BATCH_ACTION_LENGTH * COUNT_ERROR_QUEUE)) {
if (System.currentTimeMillis() - lastTimeout > QUEUE_TIMING_DURATION) {
getLog().warn("Extrem large DB-Queue in " + Thread.currentThread().getName() + ": " + updateQueue.size());
lastTimeout = System.currentTimeMillis();
}
} else if (updateQueue.size() > (BATCH_ACTION_LENGTH * COUNT_WARNING_QUEUE)) {
if (System.currentTimeMillis() - lastTimeout > QUEUE_TIMING_DURATION) {
getLog().info("Large DB-Queue in " + Thread.currentThread().getName() + ": " + updateQueue.size());
lastTimeout = System.currentTimeMillis();
}
} else if (updateQueue.size() <= BATCH_ACTION_LENGTH) {
lastTimeout = System.currentTimeMillis();
}
for (int i = 0; i < BATCH_ACTION_LENGTH && !updateQueue.isEmpty(); i++) {
acts.add(updateQueue.pop());
}
}
long t = 0;
if (getModule().isDebug()) {
t = System.currentTimeMillis();
log.debug("DB-Thread '" + Thread.currentThread().getName() + "' run: " + acts.size());
}
for (Action act : acts) {
if (!shutdown || !(act instanceof CacheChunkAction)) {
if (act instanceof CallableAction) {
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (act) {
act.process(ThreadLink.this, this.q);
act.notify();
}
} else {
act.process(ThreadLink.this, this.q);
}
}
}
if (getModule().isDebug())
log.debug("DB-Thread '" + Thread.currentThread().getName() + "' execution time: " + (System.currentTimeMillis() - t) + "ms");
} catch (InterruptedException e) {
e.printStackTrace();
log.severe("DB-Thread '" + Thread.currentThread().getName() + "' was harmfully interupted");
}
Thread.yield();
}
if (getModule().isDebug())
log.debug("DB-Thread " + Thread.currentThread().getName() + " finished.");
}
}
public void start() {
shutdown = false;
if (!thread.isAlive())
thread.start();
}
public void queueUpdate(Block block) {
restartThreadIfNeeded();
long l = System.currentTimeMillis();
synchronized (updateQueue) {
updateQueue.add(new UpdateBlockStateAction(block));
updateQueue.notifyAll();
}
long l2 = System.currentTimeMillis();
if (l2 - l > QUEUE_ACCESS_WARNING_DURATION) {
getLog().warn("queueUpdate-action took too long: " + (l2 - l) + "ms");
}
}
public BlockState callUpdate(Block block) {
restartThreadIfNeeded();
FetchBlockStateAction action = new FetchBlockStateAction(block);
synchronized (updateQueue) {
updateQueue.push(action);
updateQueue.notifyAll();
}
return action.getValue();
}
public void queue(Action act) {
restartThreadIfNeeded();
synchronized (updateQueue) {
updateQueue.add(act);
updateQueue.notifyAll();
}
}
public <T> T call(CallableAction<T> act) {
restartThreadIfNeeded();
synchronized (updateQueue) {
updateQueue.push(act);
updateQueue.notifyAll();
}
return act.getValue();
}
public List<BlockState> callUpdate(Cuboid c) {
FetchCuboidAction action = new FetchCuboidAction(c);
synchronized (updateQueue) {
updateQueue.push(action);
updateQueue.notifyAll();
}
return action.getValue();
}
public void queueMetaMove(Location from, Location to) {
restartThreadIfNeeded();
synchronized (updateQueue) {
updateQueue.add(new MoveBlockStateAction(from, to));
updateQueue.notifyAll();
}
}
public void queueChunkLoad(Chunk chunk) {
restartThreadIfNeeded();
synchronized (updateQueue) {
updateQueue.add(new CacheChunkAction(chunk));
updateQueue.notifyAll();
}
}
public void queueTransaction(Transaction transaction) {
restartThreadIfNeeded();
synchronized (updateQueue) {
updateQueue.add(transaction);
updateQueue.notifyAll();
}
}
public void shutdown() throws InterruptedException {
synchronized (updateQueue) {
shutdown = true;
updateQueue.notifyAll();
}
thread.join(THREAD_SHUTDOWN_WAIT_MS);
if (thread.isAlive())
thread.interrupt(); //Wake it up
}
public HasBlockState getMetaState(Block block) {
return model.getMetaState(block);
}
public void setMetaState(Block block, BlockState state) {
model.setMetaState(block, state);
}
public void setSimpleMetaState(Block block, BlockState state) {
model.setSimpleMetaDataState(block, state);
}
public ModBlockStates getModule() {
return model.getModel();
}
public ModuleLogger getLog() {
return log;
}
private void restartThreadIfNeeded() {
if ((thread != null && thread.isAlive()) || shutdown)
return;
log.warn("Thread is dead, restarting!");
new Exception("Thread-restarting update called").printStackTrace();
createThread(((DBThread) thread).q);
start();
}
private void createThread(DBQueries queries) {
if (shutdown)
return;
thread = new DBThread(queries);
thread.setName("LC BlockState DB-Thread");
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable e) {
e.printStackTrace();
log.severe("Thread " + thread.getName() + " encoutered an uncaught Exception: " + e.getMessage());
}
});
}
}

View file

@ -0,0 +1,74 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.block.Block;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBModel.DBTransaction;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
abstract public class Transaction implements DBTransaction, Action {
protected boolean finished = false;
private List<TransactionAction> actions = new LinkedList<TransactionAction>();
private ThreadLink link;
public Transaction(ThreadLink link) {
this.link = link;
}
@Override
public void moveState(Block from, Block to) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
actions.add(new MoveBlockStateAction(from.getLocation(), to.getLocation()));
}
@Override
public void setState(BlockState state) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
Block block = state.getLocation().getBlock();
actions.add(new UpdateBlockStateAction(block));
}
public void setState(Block block) {
if (finished)
throw new IllegalAccessError("Transaction already ended");
actions.add(new UpdateBlockStateAction(block));
}
@Override
public void finish() {
if (finished)
return;
link.queueTransaction(this);
}
/**
* @internal Executed from asynchronous Thread. Only Thread-Safe methods should be called.
*/
@Override
public void process(ThreadLink link, DBQueries q) {
if (actions.isEmpty())
return;
try {
q.getDB().startTransaction();
for (TransactionAction act : actions) {
act.processInTransaction(link, q);
}
q.getDB().endTransaction();
} catch (SQLException e) {
try {
q.getDB().revertTransaction();
} catch (SQLException e1) {}
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to write Transaction to the Database");
}
}
}

View file

@ -0,0 +1,9 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
abstract public class TransactionAction implements Action {
abstract public void processInTransaction(ThreadLink link, DBQueries q) throws SQLException;
}

View file

@ -0,0 +1,41 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.thread;
import java.sql.SQLException;
import org.bukkit.block.Block;
import de.jaschastarke.minecraft.limitedcreative.blockstate.AbstractModel.HasBlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.DBQueries;
public class UpdateBlockStateAction extends TransactionAction implements Action {
private Block block;
public UpdateBlockStateAction(Block block) {
this.block = block;
}
@Override
public void process(ThreadLink link, DBQueries q) {
HasBlockState state = link.getMetaState(block);
if (state.isSet()) {
try {
q.delete(block.getLocation());
if (state.getState() != null)
q.insert(state.getState());
} catch (SQLException e) {
link.getLog().severe(e.getMessage());
link.getLog().warn("Thread " + Thread.currentThread().getName() + " failed to save BlockState to DB: " + state.getState());
}
}
}
@Override
public void processInTransaction(ThreadLink link, DBQueries q) throws SQLException {
HasBlockState state = link.getMetaState(block);
if (state.isSet()) {
q.delete(block.getLocation());
if (state.getState() != null)
q.insert(state.getState());
}
}
}

View file

@ -0,0 +1,60 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState;
import de.jaschastarke.minecraft.limitedcreative.blockstate.BlockState.Source;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.util.Date;
public class EditSessionExtent extends AbstractDelegateExtent {
private ModBlockStates mod;
private Player player = null;
private World world;
public EditSessionExtent(Extent extent, ModBlockStates mod, Player player, World world) {
super(extent);
this.mod = mod;
this.player = player;
this.world = world;
}
/**
* Called when a block is being changed.
*
* @param pt the position
* @param newBlock the new block to replace the old one
*/
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 pt, T newBlock) throws WorldEditException {
if (mod.isDebug())
mod.getLog().debug("WorldEdit-Integration: BlockChange: " + pt.toString() + " BB: " + newBlock.toString());
Location loc = new Location(world, pt.getBlockX(), pt.getBlockY(), pt.getBlockZ());
if (newBlock.getBlockType().getMaterial().isAir()) {
mod.getModel().removeState(loc.getBlock());
} else {
BlockState s = mod.getModel().getState(loc.getBlock());
if (s == null) {
s = new BlockState();
s.setLocation(loc);
}
s.setGameMode(null);
s.setPlayerNameOrUUID(player.getUniqueId().toString());
s.setDate(new Date());
s.setSource(Source.EDIT);
if (mod.isDebug())
mod.getLog().debug("WorldEdit-Integration: Saving BlockState: " + s.toString());
mod.getModel().setState(s);
}
super.setBlock(pt, newBlock);
return true;
}
}

View file

@ -0,0 +1,38 @@
package de.jaschastarke.minecraft.limitedcreative.blockstate.worldedit;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.EditSession.Stage;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.sk89q.worldedit.world.World;
import de.jaschastarke.minecraft.limitedcreative.ModBlockStates;
public class EditSessionListener {
private ModBlockStates mod;
public EditSessionListener(ModBlockStates mod) {
this.mod = mod;
}
@Subscribe
public void onEditSession(EditSessionEvent event) {
if (mod.getConfig().getWorldeditIntegration()) {
if (event.getStage() == Stage.BEFORE_CHANGE) {
if (mod.isDebug())
mod.getLog().debug("WorldEdit-Integration: New EditSession: "+event.getActor().getName()+" in World "+event.getWorld().getName()); // + " (" + event.getStage() + ")");
Actor actor = event.getActor();
World world = event.getWorld();
if (actor != null && actor.isPlayer() && world != null && world instanceof BukkitWorld) {
Player player = Bukkit.getPlayer(actor.getUniqueId());
event.setExtent(new EditSessionExtent(event.getExtent(), mod, player, ((BukkitWorld) event.getWorld()).getWorld()));
}
}
}
}
}

View file

@ -6,22 +6,24 @@ import java.util.List;
import de.jaschastarke.bukkit.lib.configuration.ConfigurableList;
import de.jaschastarke.bukkit.lib.configuration.IToGeneric;
import de.jaschastarke.bukkit.lib.configuration.command.ITabComplete;
import de.jaschastarke.bukkit.lib.configuration.command.ListConfigValue;
import de.jaschastarke.configuration.InvalidValueException;
public class CmdBlockList extends ArrayList<ICmdBlockEntry> implements ConfigurableList<ICmdBlockEntry>, IToGeneric {
public class CmdBlockList extends ArrayList<ICmdBlockEntry> implements ConfigurableList<ICmdBlockEntry>, IToGeneric, ITabComplete {
private static final long serialVersionUID = -125544131527849084L;
@Override
public void add(String cmd) throws InvalidValueException {
public boolean addSetting(String cmd) throws InvalidValueException {
if (cmd.startsWith("^")) {
add(new RegexpBlockEntry(cmd));
return add(new RegexpBlockEntry(cmd));
} else {
add(new StringBlockEntry(cmd));
return add(new StringBlockEntry(cmd));
}
}
@Override
public boolean remove(String e) {
public boolean removeSetting(String e) {
for (Iterator<ICmdBlockEntry> iterator = this.iterator(); iterator.hasNext();) {
ICmdBlockEntry entry = iterator.next();
if (entry.toString().equalsIgnoreCase(e)) {
@ -41,4 +43,22 @@ public class CmdBlockList extends ArrayList<ICmdBlockEntry> implements Configura
return list;
}
@Override
public void clearSettings() {
clear();
}
public List<String> tabComplete(String[] args, String[] chain) {
if (args.length > 0 && chain.length > 0) {
if (chain[chain.length - 1].equalsIgnoreCase(ListConfigValue.REMOVE)) {
List<String> hints = new ArrayList<String>();
for (ICmdBlockEntry s : this) {
if (s.toString().toLowerCase().startsWith(args[0].toLowerCase()))
hints.add(s.toString());
}
return hints;
}
}
return null;
}
}

View file

@ -5,6 +5,7 @@ import java.util.Collection;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.DynamicPermission;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
@ -19,6 +20,7 @@ public class CmdBlockPermissions extends SimplePermissionContainerNode {
super(parent, name);
}
@PluginPermissions
public static final SimplePermissionContainerNode CONTAINER = new CmdBlockPermissions(Permissions.CONTAINER, "cmdblock");
/**

View file

@ -3,15 +3,17 @@ package de.jaschastarke.minecraft.limitedcreative.cmdblocker;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModCmdBlocker;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* CommandBlocker-Feature
@ -19,32 +21,34 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/command-blocker/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class CmdBlockerConfig extends Configuration implements IConfigurationSubGroup {
private CmdBlockList blockList;
protected ModCmdBlocker mod;
protected ModuleEntry<IModule> entry;
public CmdBlockerConfig(ConfigurationContainer container) {
super(container);
}
public CmdBlockerConfig(ModCmdBlocker modCmdBlocker, ModuleEntry<IModule> modEntry) {
super(modCmdBlocker.getPlugin().getDocCommentStorage());
mod = modCmdBlocker;
entry = modEntry;
}
@Override
public void setValues(ConfigurationSection sect) {
blockList = null;
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
}
@Override
public void setValue(IConfigurationNode node, Object pValue) throws InvalidValueException {
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.disable();
}
entry.setEnabled(getEnabled());
}
}
@ -69,8 +73,6 @@ public class CmdBlockerConfig extends Configuration implements IConfigurationSub
return config.getBoolean("enabled", true);
}
private CmdBlockList blockList;
/**
* CmdBlockerList
*
@ -96,7 +98,7 @@ public class CmdBlockerConfig extends Configuration implements IConfigurationSub
if (config.contains("commands") && config.isList("commands")) {
for (Object e : config.getList("commands")) {
try {
blockList.add(e.toString());
blockList.addSetting(e.toString());
} catch (InvalidValueException e1) {
mod.getLog().warn(e1.getMessage());
}

View file

@ -5,7 +5,7 @@ import java.util.regex.Pattern;
public class RegexpBlockEntry implements ICmdBlockEntry {
private Pattern rx;
public RegexpBlockEntry(String regex) {
rx = Pattern.compile(regex);
rx = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
}
@Override

View file

@ -8,7 +8,7 @@ public class StringBlockEntry implements ICmdBlockEntry {
@Override
public boolean test(String cmd) {
return cmd.startsWith(this.str);
return cmd.toLowerCase().startsWith(this.str.toLowerCase());
}
public String toString() {

View file

@ -3,15 +3,17 @@ package de.jaschastarke.minecraft.limitedcreative.gmperm;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModGameModePerm;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* GameMode-Permissions-Feature
@ -21,11 +23,16 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/gmperm/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class GMPermConfig extends Configuration implements IConfigurationSubGroup {
protected ModGameModePerm mod;
protected ModuleEntry<IModule> entry;
public GMPermConfig(ConfigurationContainer container) {
super(container);
}
public GMPermConfig(ModGameModePerm modGameModePerm, ModuleEntry<IModule> modEntry) {
super(modGameModePerm.getPlugin().getDocCommentStorage());
mod = modGameModePerm;
entry = modEntry;
}
@ -34,20 +41,14 @@ public class GMPermConfig extends Configuration implements IConfigurationSubGrou
public void setValue(IConfigurationNode node, Object pValue) throws InvalidValueException {
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.disable();
}
entry.setEnabled(getEnabled());
}
}
@Override
public void setValues(ConfigurationSection sect) {
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
}
@Override
public String getName() {
@ -91,7 +92,9 @@ public class GMPermConfig extends Configuration implements IConfigurationSubGrou
*/
@IsConfigurationNode(order = 300)
public String getAdventureGroup() {
return config.getString("adventureGroup");
if (config.isBoolean("adventureGroup"))
return null;
return config.getString("adventureGroup", null);
}
@Override

View file

@ -1,18 +1,17 @@
package de.jaschastarke.minecraft.limitedcreative.hooks;
import org.bukkit.entity.Player;
import uk.org.whoami.authme.cache.auth.PlayerCache;
import de.jaschastarke.minecraft.limitedcreative.Hooks;
import de.jaschastarke.minecraft.limitedcreative.LimitedCreative;
import fr.xephi.authme.api.v3.AuthMeApi;
import org.bukkit.entity.Player;
//@Deprecated // AuthMe 3.0 released. Compatibility for older versions will be removed sometime
public class AuthMeHooks {
public AuthMeHooks(final LimitedCreative plugin) {
Hooks.IsLoggedIn.register(new PlayerCheckHooker.Check() {
@Override
public boolean test(Player player) {
boolean li = PlayerCache.getInstance().isAuthenticated(player.getName().toLowerCase());
boolean li = AuthMeApi.getInstance().isAuthenticated(player);
if (plugin.isDebug()) // not nessesary, but so no string concation without debug needed
plugin.getLog().debug("AuthMe: "+player.getName()+": logged in: "+li);
return li;

View file

@ -0,0 +1,28 @@
package de.jaschastarke.minecraft.limitedcreative.hooks;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.World;
import de.jaschastarke.minecraft.limitedcreative.Hooks;
import de.jaschastarke.minecraft.limitedcreative.LimitedCreative;
import multiworld.MultiWorldPlugin;
import multiworld.api.MultiWorldAPI;
public class MultiWorldHooks {
public MultiWorldHooks(final LimitedCreative plugin) {
Hooks.DefaultWorldGameMode.register(new WorldTypeHooker.Check() {
@Override
public GameMode get(World world) {
boolean creative = getMWApi().isCreativeWorld(world.getName());
GameMode gm = creative ? GameMode.CREATIVE : GameMode.SURVIVAL;
plugin.getLog().debug("MultiWorld: "+world.getName()+": game mode: "+gm);
return gm;
}
});
}
private static MultiWorldAPI getMWApi() {
return ((MultiWorldPlugin) Bukkit.getServer().getPluginManager().getPlugin("MultiWorld")).getApi();
}
}

View file

@ -9,12 +9,16 @@ import org.bukkit.material.MaterialData;
import de.jaschastarke.bukkit.lib.ModuleLogger;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.bukkit.lib.configuration.command.ICommandConfigCallback;
import de.jaschastarke.bukkit.lib.items.MaterialDataNotRecognizedException;
import de.jaschastarke.bukkit.lib.items.MaterialNotRecognizedException;
import de.jaschastarke.bukkit.lib.items.ItemUtils;
import de.jaschastarke.configuration.ConfigurationStyle;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.ModInventories;
/**
@ -23,9 +27,15 @@ import de.jaschastarke.minecraft.limitedcreative.ModInventories;
* When set, all creative Player automatically wears the given items as Armor. So they are better seen by other Players.
*/
@ArchiveDocComments
public class ArmoryConfig extends Configuration implements IConfigurationSubGroup {
@PluginConfigurations(parent = InventoryConfig.class)
public class ArmoryConfig extends Configuration implements IConfigurationSubGroup, ICommandConfigCallback {
protected ModInventories mod;
public ArmoryConfig(ConfigurationContainer container) {
super(container);
}
public ArmoryConfig(ModInventories modInventories) {
super(modInventories.getPlugin().getDocCommentStorage());
mod = modInventories;
}
@ -33,7 +43,7 @@ public class ArmoryConfig extends Configuration implements IConfigurationSubGrou
public void setValues(ConfigurationSection sect) {
if (sect == null || sect.getValues(false).size() == 0) {
ConfigurationSection parent_sect = mod.getConfig().getValues();
if (parent_sect.contains("armor")) {
if (parent_sect.contains("armore") && parent_sect.isConfigurationSection("armor")) {
sect = parent_sect.createSection(this.getName(), parent_sect.getConfigurationSection("armor").getValues(true));
}
}
@ -63,9 +73,9 @@ public class ArmoryConfig extends Configuration implements IConfigurationSubGrou
if (getEnabled()) {
Map<String, ItemStack> armor = new HashMap<String, ItemStack>();
for (Map.Entry<String, Object> entry : config.getValues(false).entrySet()) {
if (!entry.getKey().equals("enabled")) {
if (entry instanceof ItemStack) {
armor.put(entry.getKey(), (ItemStack) entry);
if (!entry.getKey().equals("enabled") && !entry.getKey().equals("fixed")) {
if (entry.getValue() instanceof ItemStack) {
armor.put(entry.getKey(), (ItemStack) entry.getValue());
} else {
MaterialData md = null;
try {
@ -89,31 +99,63 @@ public class ArmoryConfig extends Configuration implements IConfigurationSubGrou
/**
* InventoryCreativeArmorItems
*
* Allows changing of the "Creative-Armor" to be wear when in creative mode
*
* Allows changing of the "Creative-Armor" to be wear when in creative mode.
* *see Blacklist for details on Item-Types
*
* When using commands to change this options, use "current" (without quotes) to set it to the currently wearing item.
* This way you can easily set it to dyed leather armor.
*/
@IsConfigurationNode(order = 500)
public Object getHead() {
return config.get("head", "CHAINMAIL_HELMET");
}
@IsConfigurationNode(order = 501)
@IsConfigurationNode(order = 501, style = ConfigurationStyle.GROUPED_PREVIOUS)
public Object getChest() {
return config.get("chest", "CHAINMAIL_CHESTPLATE");
}
@IsConfigurationNode(order = 502)
@IsConfigurationNode(order = 502, style = ConfigurationStyle.GROUPED_PREVIOUS)
public Object getLegs() {
return config.get("legs", "CHAINMAIL_LEGGINGS");
}
@IsConfigurationNode(order = 503)
@IsConfigurationNode(order = 503, style = ConfigurationStyle.GROUPED_PREVIOUS)
public Object getFeet() {
return config.get("feet", "CHAINMAIL_BOOTS");
}
/* -- Doesn't work, because of bugged bukkit... the event isn't fired if you try again --*
* InventoryCreativeArmorFixed
*
* Prevent players from changing armor while in creative.
*
* default: true
*//*
@IsConfigurationNode(order = 600, name = "fixed")
public boolean getFixedArmor() {
return config.getBoolean("fixed", true);
}*/
public String L(String msg, Object... objects) {
return mod.getPlugin().getLocale().trans(msg, objects);
}
public ModuleLogger getLog() {
return mod.getLog();
}
@Override
public void onConfigCommandChange(Callback cb) {
String n = cb.getNode().getName();
if (n.equals("head") || n.equals("chest") || n.equals("legs") || n.equals("feet")) {
if (cb.getValue().equals("current") || cb.getValue().equals("this")) {
if (cb.getContext().isPlayer()) {
if (n.equals("head"))
cb.setValue(cb.getContext().getPlayer().getInventory().getHelmet());
if (n.equals("chest"))
cb.setValue(cb.getContext().getPlayer().getInventory().getChestplate());
if (n.equals("legs"))
cb.setValue(cb.getContext().getPlayer().getInventory().getLeggings());
if (n.equals("feet"))
cb.setValue(cb.getContext().getPlayer().getInventory().getBoots());
}
}
}
}
}

View file

@ -1,15 +1,15 @@
package de.jaschastarke.minecraft.limitedcreative.inventories;
import de.jaschastarke.bukkit.lib.SimpleModule;
import de.jaschastarke.minecraft.limitedcreative.LimitedCreative;
import de.jaschastarke.minecraft.limitedcreative.ModInventories;
import fr.xephi.authme.events.ProtectInventoryEvent;
import fr.xephi.authme.events.RestoreInventoryEvent;
import org.bukkit.GameMode;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import uk.org.whoami.authme.events.RestoreInventoryEvent;
import uk.org.whoami.authme.events.StoreInventoryEvent;
import de.jaschastarke.bukkit.lib.SimpleModule;
import de.jaschastarke.minecraft.limitedcreative.LimitedCreative;
import de.jaschastarke.minecraft.limitedcreative.ModInventories;
//@Deprecated // AuthMe 3.0 released. Compatibility for older versions will be removed sometime
public class AuthMeInventories extends SimpleModule<LimitedCreative> implements Listener {
ModInventories invmod;
public AuthMeInventories(LimitedCreative plugin, ModInventories modInventories) {
@ -18,7 +18,7 @@ public class AuthMeInventories extends SimpleModule<LimitedCreative> implements
}
@EventHandler
public void onStoreInventory(StoreInventoryEvent event) {
public void onStoreInventory(ProtectInventoryEvent event) {
if (isDebug())
getLog().debug("AuthMe Store Event: " + event.getPlayer().getName());

View file

@ -31,7 +31,8 @@ public class Inventory {
public enum Target {
SURVIVAL,
CREATIVE,
ADVENTURE;
ADVENTURE,
SPECTATOR;
public static Target getTarget(GameMode gm) {
return Target.valueOf(gm.name());

View file

@ -3,15 +3,17 @@ package de.jaschastarke.minecraft.limitedcreative.inventories;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModInventories;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* Inventory-Feature
@ -19,12 +21,16 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/inventory/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class InventoryConfig extends Configuration implements IConfigurationSubGroup {
protected ModInventories mod;
protected ModuleEntry<IModule> entry;
public InventoryConfig(ConfigurationContainer container) {
super(container);
}
public InventoryConfig(ModInventories modInventories, ModuleEntry<IModule> modEntry) {
super(modInventories.getPlugin().getDocCommentStorage());
mod = modInventories;
entry = modEntry;
}
@ -33,12 +39,7 @@ public class InventoryConfig extends Configuration implements IConfigurationSubG
public void setValue(IConfigurationNode node, Object pValue) throws InvalidValueException {
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.disable();
}
entry.setEnabled(getEnabled());
}
}
@ -52,8 +53,8 @@ public class InventoryConfig extends Configuration implements IConfigurationSubG
}
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
// Config Upgrade
if (!sect.contains("storeCreative") && sect.contains("creative"))
sect.set("storeCreative", sect.getBoolean("creative"));

View file

@ -20,6 +20,7 @@ package de.jaschastarke.minecraft.limitedcreative.inventories;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
import de.jaschastarke.minecraft.lib.permissions.SimplePermissionContainer;
@ -31,10 +32,16 @@ import de.jaschastarke.minecraft.limitedcreative.Permissions;
*
*/
@ArchiveDocComments
@PluginPermissions
public class InventoryPermissions extends SimplePermissionContainer {
/**
* Allows bypassing the inventory separation
*/
public static final IPermission KEEP_INVENTORY = new BasicPermission(Permissions.CONTAINER, "keepinventory", PermissionDefault.FALSE);
/**
* Allows bypassing creative armor settings. No armor is changed on going to creative.
*/
public static final IPermission BYPASS_CREATIVE_ARMOR = new BasicPermission(Permissions.CONTAINER, "bypass_creativearmor", PermissionDefault.FALSE);
}

View file

@ -19,6 +19,7 @@ package de.jaschastarke.minecraft.limitedcreative.inventories;
import org.bukkit.GameMode;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
@ -32,7 +33,7 @@ public class PlayerListener implements Listener {
this.mod = mod;
}
@EventHandler
@EventHandler(priority=EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerGameModeChange(PlayerGameModeChangeEvent event) {
boolean isLoggedIn = Hooks.IsLoggedIn.test(event.getPlayer());
if (mod.isDebug()) {
@ -48,10 +49,22 @@ public class PlayerListener implements Listener {
mod.onSetGameMode(event.getPlayer(), event.getNewGameMode());
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onPlayerRespawn(PlayerRespawnEvent event) {
if (event.getPlayer().getGameMode() == GameMode.CREATIVE) {
mod.setCreativeArmor(event.getPlayer());
}
}
/*@EventHandler(ignoreCancelled = true)
public void onCreativeInventory(InventoryCreativeEvent event) {
if (event.getWhoClicked() instanceof Player) {
Player player = (Player) event.getWhoClicked();
if (event.getSlotType() == SlotType.ARMOR && mod.getArmorConfig().getFixedArmor()) {
if (!mod.getPlugin().getPermManager().hasPermission(player, InventoryPermissions.BYPASS_CREATIVE_ARMOR)) {
event.setCancelled(true);
}
}
}
}*/
}

View file

@ -47,7 +47,7 @@ public class Fallback {
@Override
public void store(ConfigurationSection section) {
for (int i = 0; i < inv.getSize(); i++) {
if (inv.getItem(i) != null && inv.getItem(i).getTypeId() != 0)
if (inv.getItem(i) != null && !inv.getItem(i).getType().equals(Material.AIR))
sectionSetItem(section, String.valueOf(i), inv.getItem(i));
}
}
@ -97,7 +97,7 @@ public class Fallback {
public static Map<Integer, ItemStack> storeInventory(PlayerInventory inv) {
Map<Integer, ItemStack> map = new HashMap<Integer, ItemStack>();
for (int i = 0; i < inv.getSize(); i++) {
if (inv.getItem(i) != null && inv.getItem(i).getTypeId() != 0) {
if (inv.getItem(i) != null && !inv.getItem(i).getType().equals(Material.AIR)) {
map.put(i, inv.getItem(i));
}
}
@ -133,13 +133,13 @@ public class Fallback {
@Override
public void store(ConfigurationSection section) {
if (inv.getHelmet() != null && inv.getHelmet().getTypeId() != 0)
if (inv.getHelmet() != null && !inv.getHelmet().getType().equals(Material.AIR))
Items.sectionSetItem(section, "helmet", inv.getHelmet());
if (inv.getChestplate() != null && inv.getChestplate().getTypeId() != 0)
if (inv.getChestplate() != null && !inv.getChestplate().getType().equals(Material.AIR))
Items.sectionSetItem(section, "chestplate", inv.getChestplate());
if (inv.getLeggings() != null && inv.getLeggings().getTypeId() != 0)
if (inv.getLeggings() != null && !inv.getLeggings().getType().equals(Material.AIR))
Items.sectionSetItem(section, "leggins", inv.getLeggings());
if (inv.getBoots() != null && inv.getBoots().getTypeId() != 0)
if (inv.getBoots() != null && !inv.getBoots().getType().equals(Material.AIR))
Items.sectionSetItem(section, "boots", inv.getBoots());
}

View file

@ -43,7 +43,7 @@ public class InvYamlStorage extends InvConfStorage {
@Override
public void load(Inventory pinv, Target target) {
load(pinv, YamlConfiguration.loadConfiguration(getFile(pinv, target)));
load(pinv, YamlConfiguration.loadConfiguration(getFile(pinv, target, false)));
}
@Override
@ -52,7 +52,11 @@ public class InvYamlStorage extends InvConfStorage {
yml.options().header("DO NOT MODIFY THIS FILE");
store(pinv, yml);
try {
yml.save(getFile(pinv, target));
File nameFile=getFile(pinv, target, false);
File uuidFile=getFile(pinv, target, true);
if(!nameFile.equals(uuidFile)) //It'd be recreated right after, still, don't remove if the same
nameFile.delete(); //Delete file with name so it doesn't get loaded again
yml.save(uuidFile);
} catch (IOException e) {
mod.getLog().warn("Failed to save Inventory for Player " + pinv.getPlayer().getName());
e.printStackTrace();
@ -61,19 +65,28 @@ public class InvYamlStorage extends InvConfStorage {
@Override
public void remove(Inventory pinv, Target target) {
getFile(pinv, target).delete();
getFile(pinv, target, true).delete();
}
@Override
public boolean contains(Inventory pinv, Target target) {
return getFile(pinv, target).exists();
return getFile(pinv, target, false).exists();
}
protected File getFile(Inventory pinv, Target target) {
protected File getFile(Inventory pinv, Target target, boolean uuidonly) {
File file;
String player;
do {
player = uuidonly ? pinv.getPlayer().getUniqueId().toString() : pinv.getPlayer().getName();
if (target != default_target) {
return new File(dir, pinv.getPlayer().getName() + "_" + target.toString().toLowerCase() + SUFFIX);
file = new File(dir, player + "_" + target.toString().toLowerCase() + SUFFIX);
} else {
return new File(dir, pinv.getPlayer().getName() + SUFFIX);
}
file = new File(dir, player + SUFFIX);
}
if(uuidonly)
return file; //Use file with UUID, even if doesn't exist
uuidonly = true; //Run again with UUID, then return...
} while(!file.exists()); //...if the file with name is not found
return file; //Found file with player name
}
}

View file

@ -0,0 +1,217 @@
package de.jaschastarke.minecraft.limitedcreative.inventories.store;
import de.jaschastarke.bukkit.lib.CoreModule;
import de.jaschastarke.bukkit.lib.ModuleLogger;
import de.jaschastarke.minecraft.limitedcreative.inventories.Inventory;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Base64;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class ReflectionStorage extends PlayerInventoryStorage {
private CoreModule<?> mod;
private File dir;
private String nms;
private InvYamlStorage yamlStorage;
public ReflectionStorage(CoreModule<?> mod, File file) {
this.mod = mod;
dir = file;
yamlStorage = new InvYamlStorage(mod, file);
}
@Override
public ModuleLogger getLog() {
return mod.getLog();
}
private File getFile(UUID uuid) {
return new File(dir, uuid.toString() + "_ref.yml");
}
private Object getInventory(Player player) throws Exception {
org.bukkit.inventory.Inventory inv = player.getInventory();
if (getInventory == null)
getInventory = inv.getClass().getMethod("getInventory");
Object handle = getInventory.invoke(inv);
if (nms == null)
nms = handle.getClass().getPackage().getName();
return handle;
}
@Override
public void store(Inventory pinv, Inventory.Target target) {
try {
File f = getFile(pinv.getPlayer().getUniqueId());
YamlConfiguration config = YamlConfiguration.loadConfiguration(f);
config.set(target.name(), serialize(getInventory(pinv.getPlayer())));
config.save(f);
} catch (Exception e) {
e.printStackTrace();
}
}
private Method getInventory;
@Override
public void load(Inventory pinv, Inventory.Target target) {
Player player = pinv.getPlayer();
try {
File f = getFile(player.getUniqueId());
if (!f.exists()) { //If not found use the older file(s)
yamlStorage.load(pinv, target);
return;
}
//String content = new String(Files.readAllBytes(f.toPath()));
Configuration config = YamlConfiguration.loadConfiguration(f);
String content = config.getString(target.name());
if (content == null) {
yamlStorage.load(pinv, target);
return;
}
setFromSerialized(getInventory(player), content);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void remove(Inventory pinv, Inventory.Target target) {
File f = getFile(pinv.getPlayer().getUniqueId());
if (!f.exists()) return;
Configuration config = YamlConfiguration.loadConfiguration(f);
config.set(target.name(), null);
}
@Override
public boolean contains(Inventory pinv, Inventory.Target target) {
File f = getFile(pinv.getPlayer().getUniqueId());
if (!f.exists()) return yamlStorage.contains(pinv, target);
Configuration config = YamlConfiguration.loadConfiguration(f);
return config.contains(target.name()) || yamlStorage.contains(pinv, target);
}
//Based on iie's per-world inventory
//https://github.com/TBMCPlugins/iiePerWorldInventory/blob/master/src/buttondevteam/perworld/serializers/inventory.java
private Method save;
private Class<?> nbtcl;
private Method nbtcsta;
private Class<?> nbtcstcl;
//SERIALIZE ITEMSTACK
private String serializeItemStack(Object itemStack) throws Exception {
if (nbtcl == null)
nbtcl = Class.forName(nms + ".NBTTagCompound");
if (save == null)
save = itemStack.getClass().getMethod("save", nbtcl);
if (nbtcstcl == null)
nbtcstcl = Class.forName(nms + ".NBTCompressedStreamTools");
if (nbtcsta == null)
nbtcsta = nbtcstcl.getMethod("a", nbtcl, OutputStream.class);
Object tag = save.invoke(itemStack, nbtcl.newInstance());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
nbtcsta.invoke(null, tag, outputStream);
return Base64.getEncoder().encodeToString(outputStream.toByteArray());
}
private Method nbtcstaa;
private Function<Object, Object> createStack;
//DESERIALIZE ITEMSTACK
private Object deserializeItemStack(String itemStackString) throws Exception {
if (nbtcstcl == null)
nbtcstcl = Class.forName(nms + ".NBTCompressedStreamTools");
if (nbtcstaa == null)
nbtcstaa = nbtcstcl.getMethod("a", InputStream.class);
if (nbtcl == null)
nbtcl = Class.forName(nms + ".NBTTagCompound");
try {
if (createStack == null) {
final Method a = iscl.getMethod("a", nbtcl);
createStack = nbt -> {
try {
return a.invoke(null, nbt);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
} catch (NoSuchMethodException ex) { //It can only get here inside the if
final Constructor<?> constructor = iscl.getConstructor(nbtcl);
createStack = nbt -> {
try {
return constructor.newInstance(nbt);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
}
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(itemStackString));
Object nbtTagCompound = nbtcstaa.invoke(null, inputStream);
return createStack.apply(nbtTagCompound);
}
private Method getSize;
private Method getItem;
//SERIALIZE INVENTORY
private String serialize(Object invInventory) throws Exception {
if (getSize == null)
getSize = invInventory.getClass().getMethod("getSize");
if (getItem == null)
getItem = invInventory.getClass().getMethod("getItem", int.class);
return IntStream.range(0, (int) getSize.invoke(invInventory))
.mapToObj(s -> {
try {
//nms ItemStack
Object i = getItem.invoke(invInventory, s);
return Objects.isNull(i) ? null : s + "#" + serializeItemStack(i);
} catch (Exception e) {
throw new RuntimeException(e);
}
})
.filter(Objects::nonNull)
.collect(Collectors.joining(";"));
}
private Method clear;
private Method setItem;
private Class<?> iscl;
//SET INVENTORY FROM SERIALIZED
private void setFromSerialized(Object invInventory, String invString) throws Exception {
if (clear == null)
clear = invInventory.getClass().getMethod("clear");
if (iscl == null)
iscl = Class.forName(nms + ".ItemStack");
if (setItem == null)
setItem = invInventory.getClass().getMethod("setItem", int.class, iscl);
clear.invoke(invInventory); //clear inventory
if (invString != null && !invString.isEmpty())
Arrays.asList(invString.split(";"))
.parallelStream()
.forEach(s -> {
String[] e = s.split("#");
try {
setItem.invoke(invInventory, Integer.parseInt(e[0]), deserializeItemStack(e[1]));
} catch (Exception ex) {
throw new RuntimeException(ex);
}
});
}
}

View file

@ -11,12 +11,14 @@ import org.bukkit.material.MaterialData;
import de.jaschastarke.bukkit.lib.configuration.ConfigurableList;
import de.jaschastarke.bukkit.lib.configuration.IToGeneric;
import de.jaschastarke.bukkit.lib.configuration.command.ITabComplete;
import de.jaschastarke.bukkit.lib.configuration.command.ListConfigValue;
import de.jaschastarke.bukkit.lib.items.ItemUtils;
import de.jaschastarke.bukkit.lib.items.MaterialDataNotRecognizedException;
import de.jaschastarke.bukkit.lib.items.MaterialNotRecognizedException;
import de.jaschastarke.configuration.InvalidValueException;
public class BlackList extends ArrayList<BlackList.Blacklisted> implements ConfigurableList<BlackList.Blacklisted>, IToGeneric {
public class BlackList extends ArrayList<BlackList.Blacklisted> implements ConfigurableList<BlackList.Blacklisted>, IToGeneric, ITabComplete {
private static final long serialVersionUID = -3701659163474405152L;
public static class Blacklisted {
@ -30,9 +32,9 @@ public class BlackList extends ArrayList<BlackList.Blacklisted> implements Confi
md = ItemUtils.parseMaterial(rep);
hasData = rep.contains(ItemUtils.MATERIAL_DATA_SEP);
} catch (MaterialNotRecognizedException e) {
throw new InvalidValueException(e);
throw new InvalidValueException("Invalid Material: " + rep, e);
} catch (MaterialDataNotRecognizedException e) {
throw new InvalidValueException(e);
throw new InvalidValueException("Invalid Material with Data: " + rep, e);
}
}
public Blacklisted(Material m) {
@ -53,7 +55,7 @@ public class BlackList extends ArrayList<BlackList.Blacklisted> implements Confi
}
public boolean matches(Block block) {
if (hasData) {
return md.equals(new MaterialData(block.getType(), block.getData()));
return md.equals(block.getState().getData());
} else {
return block.getType().equals(md.getItemType());
}
@ -74,7 +76,8 @@ public class BlackList extends ArrayList<BlackList.Blacklisted> implements Confi
add((Blacklisted) el);
} else {
try {
add(el.toString());
if (el != null)
addSetting(el.toString());
} catch (InvalidValueException e) {
System.err.println(e.getCause().getMessage());
}
@ -107,14 +110,15 @@ public class BlackList extends ArrayList<BlackList.Blacklisted> implements Confi
}
@Override // ConfigurableList, not List<E>
public void add(String e) throws InvalidValueException {
public boolean addSetting(String e) throws InvalidValueException {
if (!contains(e)) {
add(new Blacklisted(e));
return add(new Blacklisted(e));
}
return false;
}
@Override // ConfigurableList, not List<E>
public boolean remove(String e) {
public boolean removeSetting(String e) {
Iterator<Blacklisted> it = iterator();
while (it.hasNext()) {
if (it.next().toString().equalsIgnoreCase(e)) {
@ -137,4 +141,32 @@ public class BlackList extends ArrayList<BlackList.Blacklisted> implements Confi
public List<String> toGeneric() {
return toStringList();
}
@Override
public void clearSettings() {
clear();
}
@Override
public List<String> tabComplete(String[] args, String[] chain) {
if (args.length > 0 && chain.length > 0) {
List<String> hints = new ArrayList<String>();
String action = chain[chain.length - 1];
if (action.equalsIgnoreCase(ListConfigValue.ADD)) {
for (Material m : Material.values()) {
if (m.name().toLowerCase().startsWith(args[0].toLowerCase())) {
hints.add(m.name());
}
}
} else if (action.equalsIgnoreCase(ListConfigValue.REMOVE)) {
for (Blacklisted bl : this) {
if (bl.toString().toLowerCase().startsWith(args[0].toLowerCase())) {
hints.add(bl.toString());
}
}
}
return hints;
}
return null;
}
}

View file

@ -4,6 +4,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import de.jaschastarke.bukkit.lib.configuration.command.ITabComplete;
import de.jaschastarke.bukkit.lib.configuration.command.ListConfigValue;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -11,9 +13,32 @@ import de.jaschastarke.bukkit.lib.configuration.ConfigurableList;
import de.jaschastarke.bukkit.lib.configuration.IToGeneric;
import de.jaschastarke.configuration.InvalidValueException;
public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> implements ConfigurableList<BlackListEntity.Blacklisted>, IToGeneric {
public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> implements ConfigurableList<BlackListEntity.Blacklisted>, IToGeneric, ITabComplete {
private static final long serialVersionUID = 6150727863411513873L;
@Override
public List<String> tabComplete(String[] args, String[] chain) {
if (args.length > 0 && chain.length > 0) {
List<String> hints = new ArrayList<String>();
String action = chain[chain.length - 1];
if (action.equalsIgnoreCase(ListConfigValue.ADD)) {
for (EntityType m : EntityType.values()) {
if (m.name().toLowerCase().startsWith(args[0].toLowerCase())) {
hints.add(m.name());
}
}
} else if (action.equalsIgnoreCase(ListConfigValue.REMOVE)) {
for (Blacklisted bl : this) {
if (bl.toString().toLowerCase().startsWith(args[0].toLowerCase())) {
hints.add(bl.toString());
}
}
}
return hints;
}
return null;
}
public static class Blacklisted {
private String stringRep;
private EntityType type;
@ -27,7 +52,7 @@ public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> impl
type = null;
}
if (type == null)
type = EntityType.fromName(rep);
type = EntityType.valueOf(rep);
try {
if (type == null)
type = EntityType.valueOf(rep);
@ -36,7 +61,7 @@ public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> impl
}
if (type == null)
throw new InvalidValueException("Entity '" + stringRep + "' not found");
throw new InvalidValueException("Entity '" + rep + "' not found");
stringRep = rep;
}
public Blacklisted(EntityType et) {
@ -66,7 +91,8 @@ public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> impl
add((Blacklisted) el);
} else {
try {
add(el.toString());
if (el != null)
addSetting(el.toString());
} catch (InvalidValueException e) {
System.err.println((e.getCause() != null ? e.getCause() : e).getMessage());
}
@ -99,14 +125,15 @@ public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> impl
}
@Override // ConfigurableList, not List<E>
public void add(String e) throws InvalidValueException {
public boolean addSetting(String e) throws InvalidValueException {
if (!contains(e)) {
add(new Blacklisted(e));
return add(new Blacklisted(e));
}
return false;
}
@Override // ConfigurableList, not List<E>
public boolean remove(String e) {
public boolean removeSetting(String e) {
Iterator<Blacklisted> it = iterator();
while (it.hasNext()) {
if (it.next().toString().equalsIgnoreCase(e)) {
@ -129,4 +156,9 @@ public class BlackListEntity extends ArrayList<BlackListEntity.Blacklisted> impl
public List<String> toGeneric() {
return toStringList();
}
@Override
public void clearSettings() {
clear();
}
}

View file

@ -24,6 +24,9 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import de.jaschastarke.bukkit.lib.events.AttachedBlockDestroyedByPlayerEvent;
import de.jaschastarke.bukkit.lib.events.HangingBreakByPlayerBlockEvent;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IDynamicPermission;
import de.jaschastarke.minecraft.limitedcreative.ModCreativeLimits;
@ -33,9 +36,9 @@ public class BlockListener implements Listener {
this.mod = mod;
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent event) {
if (!event.isCancelled() && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (mod.getConfig().getBlockBreak().isListed(event.getBlock())) {
if (!checkPermission(event.getPlayer(), NoLimitPermissions.BREAK(event.getBlock()))) {
event.setCancelled(true);
@ -44,9 +47,9 @@ public class BlockListener implements Listener {
}
}
}
@EventHandler
@EventHandler(ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent event) {
if (!event.isCancelled() && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (mod.getConfig().getBlockUse().isListed(event.getBlock())) {
if (!checkPermission(event.getPlayer(), NoLimitPermissions.USE(event.getBlock()))) {
event.setCancelled(true);
@ -55,8 +58,29 @@ public class BlockListener implements Listener {
}
}
}
@EventHandler
public void onAttachedBlockBreak(AttachedBlockDestroyedByPlayerEvent event) {
if (mod.isDebug())
mod.getLog().debug("Attached Block " + event.getBlock().getType() + " initial destroyed by player: " + event.getPlayer().getName() + " in GM " + event.getPlayer().getGameMode().toString());
if (event.getPlayer() != null && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (!checkPermission(event.getPlayer(), NoLimitPermissions.DROP)) {
mod.getBlockSpawn().block(event.getBlock());
}
}
}
@EventHandler(ignoreCancelled = true)
public void onHangingBreakByPlayer(HangingBreakByPlayerBlockEvent event) {
if (mod.isDebug())
mod.getLog().debug("Attached Hanging " + event.getEntity().getType() + " destroyed by player block place/break: " + event.getPlayer().getName() + " in GM " + event.getPlayer().getGameMode().toString());
if (event.getPlayer().getGameMode() == GameMode.CREATIVE) {
event.getDrops().clear();
}
}
private boolean checkPermission(Player player, IDynamicPermission perm) {
return mod.getPlugin().getPermManager().hasPermission(player, perm);
}
private boolean checkPermission(Player player, IAbstractPermission perm) {
return mod.getPlugin().getPermManager().hasPermission(player, perm);
}
}

View file

@ -22,6 +22,7 @@ import org.bukkit.entity.Creature;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
@ -49,6 +50,20 @@ public class EntityListener implements Listener {
}
}
@EventHandler
public void onEntityDeath(EntityDeathEvent event) {
if (event.getEntity() != null && event.getDroppedExp() > 0) {
if (mod.getNoDropMobs().isXPPrevented(event.getEntity())) {
event.setDroppedExp(0);
event.getDrops().clear();
}
}
if (event.getDrops().size() > 0 && mod.getNoDropMobs().isDropPrevented(event.getEntity())) {
event.getDrops().clear();
}
mod.getNoDropMobs().remove(event.getEntity());
}
private boolean checkPermission(Player player, IAbstractPermission perm) {
return mod.getPlugin().getPermManager().hasPermission(player, perm);
}

View file

@ -0,0 +1,37 @@
package de.jaschastarke.minecraft.limitedcreative.limits;
import java.util.Map;
import java.util.WeakHashMap;
import org.bukkit.entity.Entity;
public class EntityNoDrop {
private Map<Entity, Prevent> nodrop = new WeakHashMap<Entity, Prevent>();
private Prevent get(Entity entity) {
if (!nodrop.containsKey(entity))
nodrop.put(entity, new Prevent());
return nodrop.get(entity);
}
public void preventXP(Entity entity) {
get(entity).xp = true;
}
public void preventDrop(Entity entity) {
get(entity).drops = true;
}
public boolean isXPPrevented(Entity entity) {
return nodrop.containsKey(entity) && nodrop.get(entity).xp;
}
public boolean isDropPrevented(Entity entity) {
return nodrop.containsKey(entity) && nodrop.get(entity).drops;
}
public void remove(Entity entity) {
nodrop.remove(entity);
}
private class Prevent {
boolean xp = false;
boolean drops = false;
}
}

View file

@ -5,16 +5,18 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.EntityType;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.bukkit.lib.configuration.IToGeneric;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModCreativeLimits;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* Creative Limits-Feature
@ -22,13 +24,22 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/limit/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class LimitConfig extends Configuration implements IConfigurationSubGroup {
private BlackList breakList;
private BlackListEntity interactEntityList;
private BlackList interactList;
private BlackList useList;
protected ModCreativeLimits mod;
protected ModuleEntry<IModule> entry;
public LimitConfig(ModCreativeLimits modInventories, ModuleEntry<IModule> modEntry) {
mod = modInventories;
public LimitConfig(ConfigurationContainer container) {
super(container);
}
public LimitConfig(ModCreativeLimits modCreativeLimits, ModuleEntry<IModule> modEntry) {
super(modCreativeLimits.getPlugin().getDocCommentStorage());
mod = modCreativeLimits;
entry = modEntry;
}
@ -37,20 +48,18 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
if (!(pValue instanceof BlackList))
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.disable();
}
entry.setEnabled(getEnabled());
}
}
@Override
public void setValues(ConfigurationSection sect) {
breakList = null;
interactEntityList = null;
interactList = null;
useList = null;
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
// Config Upgrade
if (!sect.contains("interact") && sect.contains("sign")) {
@ -105,18 +114,18 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
/**
* LimitDropsInsteadPrevent
*
* When enabled items that are dropped by creative players are removed (burning in the hellfire or so, they just
* When enabled items that are dropped by creative players are removed (burning in the hellfire or such, they just
* disappear). When disabled the items stay in the inventory of the player.
*
* default: false
* default: true
*/
@IsConfigurationNode(order = 200)
public boolean getRemoveDrops() {
return config.getBoolean("removeDrops", false);
return config.getBoolean("removeDrops", true);
}
public static enum BlockPickup implements IToGeneric {
public enum BlockPickup implements IToGeneric {
PREVENT,
REMOVE;
@ -144,11 +153,10 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
* LimitPickup
*
* Prevents the pickup of items while in creative mode. Either the items are just stay on ground and ignore that a
* creative player walks over it ("prevent"), or the are "remove"d when a creative player walks over it. This is
* helpful e.g. when the creative player destroys a long line of rails.
* creative player walks over it ("prevent"), or the are "remove"d when a creative player walks over it.
*
* valid options: remove / prevent / false
* default: remove
* default: prevent
*/
@IsConfigurationNode(name = "pickup", order = 300)
public BlockPickup getBlockPickup() {
@ -160,28 +168,21 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
return getEnum(BlockPickup.class, "pickup", BlockPickup.PREVENT);
}
private BlackList interactList;
/**
* LimitInteraction
*
* Prevents players of interacting with specific blocks as addition to chests in creative mode (and only in
* creative).
*
* You can use the technical name (http://tinyurl.com/bukkit-material) or
* You can use the technical name (http://public.ja-s.de/bukkit/material) or
* the id of the block/item (better use the id, if you're not sure). You may add the data separated with a colon
* e.g.: "WOOL:11" blocks blue wool. But be sure to put it in quotes, to not break yml-configuration! Named data
* values aren't supported yet. If you don't add a data-value, all blocks of this material are blocked.
*
* default:
* - SIGN
* - WALL_SIGN
* - SIGN_POST
* - LEVER
* - STONE_BUTTON
* - WOOD_BUTTON
* - WORKBENCH
* - ANVIL
* - ENCHANTMENT_TABLE
* - JUKEBOX
*/
@IsConfigurationNode(name = "interact", order = 600)
public BlackList getBlockInteraction() {
@ -190,17 +191,12 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
if (!config.contains("interact")) {
interactList.add(new BlackList.Blacklisted(Material.WALL_SIGN));
interactList.add(new BlackList.Blacklisted(Material.SIGN_POST));
interactList.add(new BlackList.Blacklisted(Material.LEVER));
interactList.add(new BlackList.Blacklisted(Material.STONE_BUTTON));
interactList.add(new BlackList.Blacklisted(Material.WOOD_BUTTON));
interactList.add(new BlackList.Blacklisted(Material.WORKBENCH));
interactList.add(new BlackList.Blacklisted(Material.ANVIL));
interactList.add(new BlackList.Blacklisted(Material.ENCHANTMENT_TABLE));
interactList.add(new BlackList.Blacklisted(Material.JUKEBOX));
}
}
return interactList;
}
private BlackListEntity interactEntityList;
/**
* LimitEntityInteraction
*
@ -210,10 +206,6 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
* if you're not sure).
*
* default:
* - MINECART_CHEST
* - MINECART_FURNACE
* - MINECART_HOPPER
* - ITEM_FRAME
* - VILLAGER
*/
@IsConfigurationNode(name = "entityInteract", order = 650)
@ -221,29 +213,25 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
if (interactEntityList == null) {
interactEntityList = new BlackListEntity(config.getList("entityInteract"));
if (!config.contains("entityInteract")) {
interactEntityList.add(new BlackListEntity.Blacklisted(EntityType.MINECART_CHEST));
interactEntityList.add(new BlackListEntity.Blacklisted(EntityType.MINECART_FURNACE));
interactEntityList.add(new BlackListEntity.Blacklisted(EntityType.MINECART_HOPPER));
interactEntityList.add(new BlackListEntity.Blacklisted(EntityType.ITEM_FRAME));
interactEntityList.add(new BlackListEntity.Blacklisted(EntityType.VILLAGER));
}
}
return interactEntityList;
}
private BlackList useList;
/**
* LimitUse
*
* Prevents players of using or placing specific items/blocks in creative mode (and only in creative).
*
* You can use the technical name (see http://tinyurl.com/bukkit-material) or
* You can use the technical name (see http://public.ja-s.de/bukkit/material) or
* the id of the block/item (better use the id, if you're not sure). You may add the data separated with a colon
* e.g.: "WOOL:11" blocks blue wool. But be sure to put it in quotes, to not break yml-configuration! Named data
* values aren't supported yet. If you don't add a data-value, all blocks of this material are blocked.
*
* default:
* - EXP_BOTTLE
* - EYE_OF_ENDER
* - BEDROCK
*/
@IsConfigurationNode(name = "use", order = 700)
@ -252,19 +240,19 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
useList = new BlackList(config.getList("use"));
if (!config.contains("use")) {
useList.add(new BlackList.Blacklisted(Material.EXP_BOTTLE));
useList.add(new BlackList.Blacklisted(Material.EYE_OF_ENDER));
useList.add(new BlackList.Blacklisted(Material.BEDROCK));
}
}
return useList;
}
private BlackList breakList;
/**
* LimitBreak
*
* Prevents players of destroying specific blocks in creative mode (and only in creative).
*
* You can use the technical name (see http://tinyurl.com/bukkit-material) or
* You can use the technical name (see http://public.ja-s.de/bukkit/material) or
* the id of the block/item (better use the id, if you're not sure). You may add the data separated with a colon
* e.g.: "WOOL:11" blocks blue wool. But be sure to put it in quotes, to not break yml-configuration! Named data
* values aren't supported yet. If you don't add a data-value, all blocks of this material are blocked.
@ -283,12 +271,25 @@ public class LimitConfig extends Configuration implements IConfigurationSubGroup
return breakList;
}
/**
* LimitChestOpen
*
* Enable this to prevents the ChestOpening-Animination when blocking interaction with a chest. But therefore
* you're no longer able to place blocks on chest and such while crouching.
*
* default: false
*/
@IsConfigurationNode(name = "chestOpen", order = 900)
public boolean getBlockChestInteraction() {
return config.getBoolean("chestOpen", false);
}
@Override
public Object getValue(final IConfigurationNode node) {
Object val = super.getValue(node);
if (node.getName().equals("pickup") && val == null) {
return new Boolean(false);
return false;
} else {
return val;
}

View file

@ -20,10 +20,13 @@ package de.jaschastarke.minecraft.limitedcreative.limits;
import java.util.Collection;
import org.bukkit.block.Block;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.material.MaterialData;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.DynamicPermission;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
@ -41,7 +44,7 @@ public class NoLimitPermissions extends SimplePermissionContainerNode {
super(parent, name);
}
@PluginPermissions
public static final IPermissionContainer PARENT = new NoLimitPermissions(Permissions.CONTAINER, "nolimit");
/**
@ -50,7 +53,7 @@ public class NoLimitPermissions extends SimplePermissionContainerNode {
public static final IPermission ALL = new ParentPermissionContainerNode(PARENT, "*", PermissionDefault.OP, PARENT);
/**
* Allows bypassing the "do not open a chest"-limitation
* Allows bypassing the "do not open a chest" and "do not open inventory"-limitation
*/
@IsChildPermission
public static final IPermission CHEST = new BasicPermission(PARENT, "chest", PermissionDefault.FALSE);
@ -90,19 +93,56 @@ public class NoLimitPermissions extends SimplePermissionContainerNode {
@IsChildPermission
public static final IPermission BASE_BREAK = new BasicPermission(PARENT, "break", PermissionDefault.FALSE);
/**
* Allows bypassing the "don't change heal/food-state"-limitation
*/
@IsChildPermission
public static final IPermission STATS_HEALTH = new BasicPermission(PARENT, "health", PermissionDefault.FALSE);
/**
* Allows bypassing the "don't get xp/level"-limitation
*/
@IsChildPermission
public static final IPermission STATS_XP = new BasicPermission(PARENT, "xp", PermissionDefault.FALSE);
/**
* Allows bypassing the "remove all effects on leaving creative"-limitation
*/
@IsChildPermission
public static final IPermission STATS_POTION = new BasicPermission(PARENT, "potion", PermissionDefault.FALSE);
public static IDynamicPermission INVENTORY(Inventory inv) {
return new InventoryPermission(CHEST, inv.getType());
}
public static IDynamicPermission INVENTORY(InventoryType invtype) {
return new InventoryPermission(CHEST, invtype);
}
public static IDynamicPermission INTERACT(Block block) {
return new MaterialPermission(BASE_INTERACT, new MaterialData(block.getType(), block.getData()));
return new MaterialPermission(BASE_INTERACT, block.getState().getData());
}
public static IDynamicPermission USE(Block block) {
return new MaterialPermission(BASE_USE, new MaterialData(block.getType(), block.getData()));
return new MaterialPermission(BASE_USE, block.getState().getData());
}
public static IDynamicPermission USE(MaterialData m) {
return new MaterialPermission(BASE_USE, m);
}
public static IDynamicPermission BREAK(Block block) {
return new MaterialPermission(BASE_BREAK, new MaterialData(block.getType(), block.getData()));
return new MaterialPermission(BASE_BREAK, block.getState().getData());
}
public static class InventoryPermission extends DynamicPermission {
private InventoryType it;
public InventoryPermission(IAbstractPermission parent, InventoryType t) {
super(parent);
it = t;
}
@Override
protected void buildPermissionsToCheck(Collection<IAbstractPermission> perms) {
perms.add(new BasicPermission(parent, it.toString()));
}
}
public static class MaterialPermission extends DynamicPermission {
private MaterialData md;
public MaterialPermission(IAbstractPermission parent, MaterialData m) {

View file

@ -18,6 +18,7 @@
package de.jaschastarke.minecraft.limitedcreative.limits;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
@ -25,19 +26,19 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.Event;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.inventory.BeaconInventory;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.*;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.material.DirectionalContainer;
import org.bukkit.potion.PotionEffect;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IDynamicPermission;
@ -57,7 +58,7 @@ public class PlayerListener implements Listener {
* @return The relevant "isCancelled"
*/
public static boolean isCancelled(PlayerInteractEvent event) {
return event.useInteractedBlock() == Event.Result.DENY && event.useItemInHand() == Event.Result.DENY;
return (event.useInteractedBlock() == Event.Result.DENY && event.useItemInHand() == Event.Result.DENY);
}
@EventHandler
@ -66,8 +67,24 @@ public class PlayerListener implements Listener {
if (checkPermission(event, NoLimitPermissions.DROP))
return;
if (mod.getConfig().getRemoveDrops())
event.getItemDrop().remove();
//event.setCancelled(true); // doesn't make much sense
else
event.setCancelled(true); // doesn't make much sense
}
}
@EventHandler
public void onInventoryOpen(InventoryOpenEvent event) {
if (event.getPlayer() instanceof Player) {
if (event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (!mod.getConfig().getBlockChestInteraction()) {
if (checkPermission((Player) event.getPlayer(), NoLimitPermissions.INVENTORY(event.getInventory())))
return;
event.setCancelled(true);
((Player) event.getPlayer()).sendMessage(mod.getPlugin().getLocale().trans("blocked.inventory"));
}
}
}
}
@ -88,7 +105,7 @@ public class PlayerListener implements Listener {
if (!event.isCancelled() && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
LimitConfig.BlockPickup pickup = mod.getConfig().getBlockPickup();
if (pickup != null) {
if (checkPermission(event, NoLimitPermissions.DROP))
if (checkPermission(event, NoLimitPermissions.PICKUP))
return;
if (pickup == BlockPickup.REMOVE) {
@ -100,6 +117,48 @@ public class PlayerListener implements Listener {
}
@EventHandler
public void onPlayerChangeExp(PlayerExpChangeEvent event) {
if (event.getAmount() > 0 && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (checkPermission(event, NoLimitPermissions.STATS_XP))
return;
event.setAmount(0);
}
}
@EventHandler
public void onEntityFoodLevelChange(FoodLevelChangeEvent event) {
if (event.getEntity() instanceof Player) {
if (!event.isCancelled() && ((Player) event.getEntity()).getGameMode() == GameMode.CREATIVE) {
if (checkPermission((Player) event.getEntity(), NoLimitPermissions.STATS_HEALTH))
return;
event.setCancelled(true);
}
}
}
@EventHandler
public void onEntityRegainHealth(EntityRegainHealthEvent event) {
if (event.getEntity() instanceof Player) {
if (!event.isCancelled() && ((Player) event.getEntity()).getGameMode() == GameMode.CREATIVE) {
if (checkPermission((Player) event.getEntity(), NoLimitPermissions.STATS_HEALTH))
return;
event.setCancelled(true);
}
}
}
@EventHandler(priority=EventPriority.LOW)
public void onGameMode(PlayerGameModeChangeEvent event) {
if (!event.isCancelled()) {
if ((event.getPlayer().getGameMode() == GameMode.CREATIVE) && (event.getNewGameMode() != GameMode.CREATIVE)) {
if (checkPermission(event, NoLimitPermissions.STATS_POTION))
return;
for (PotionEffect effect : event.getPlayer().getActivePotionEffects()) {
event.getPlayer().removePotionEffect(effect.getType());
}
}
}
}
@EventHandler // Do not use ignoreCancelled here, as some AIR-Interacts are interpreted as isCancelled by default
public void onPlayerInteract(PlayerInteractEvent event) {
if (!isCancelled(event) && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (event.getItem() != null && mod.getConfig().getBlockUse().isListed(event.getItem())) {
@ -117,17 +176,15 @@ public class PlayerListener implements Listener {
// when crouching.
if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
Block block = event.getClickedBlock();
if (isChest(block)) {
if (mod.getConfig().getBlockChestInteraction() && isChest(block)) {
if (!checkPermission(event, NoLimitPermissions.CHEST)) {
event.setCancelled(true);
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("blocked.chest"));
return;
}
} else if (mod.getConfig().getBlockInteraction().isListed(block)) {
if (!checkPermission(event, NoLimitPermissions.INTERACT(block))) {
event.setCancelled(true);
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("blocked.interact"));
return;
}
}
}
@ -137,8 +194,8 @@ public class PlayerListener implements Listener {
@EventHandler
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
if (!event.isCancelled() && event.getPlayer().getGameMode() == GameMode.CREATIVE) {
if (mod.getConfig().getBlockUse().isListed(event.getPlayer().getItemInHand())) {
if (!checkPermission(event, NoLimitPermissions.USE(event.getPlayer().getItemInHand().getData()))) {
if (mod.getConfig().getBlockUse().isListed(event.getPlayer().getInventory().getItemInMainHand())) {
if (!checkPermission(event, NoLimitPermissions.USE(event.getPlayer().getInventory().getItemInMainHand().getData()))) {
event.setCancelled(true);
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("blocked.use"));
return;
@ -149,20 +206,24 @@ public class PlayerListener implements Listener {
if (!checkPermission(event, NoLimitPermissions.BASE_INTERACT)) {
event.setCancelled(true);
event.getPlayer().sendMessage(mod.getPlugin().getLocale().trans("blocked.entity"));
return;
}
}
}
}
@EventHandler
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
@EventHandler(ignoreCancelled = true)
public void onEntityDamageByEntity(EntityDamageEvent rawevent) {
if (rawevent instanceof EntityDamageByEntityEvent && !rawevent.isCancelled()) {
EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) rawevent;
Entity source = event.getDamager();
if (source instanceof Projectile)
source = ((Projectile) source).getShooter();
if (source instanceof Projectile && ((Projectile) source).getShooter() instanceof Entity)
source = (Entity) ((Projectile) source).getShooter();
if (source instanceof Player) {
Player player = (Player) source;
@ -175,6 +236,15 @@ public class PlayerListener implements Listener {
if (!checkPermission(player, NoLimitPermissions.MOB_DAMAGE)) {
event.setCancelled(true);
}
} else if (event.getEntity() instanceof LivingEntity) {
if (!checkPermission(player, NoLimitPermissions.STATS_XP)) {
mod.getNoDropMobs().preventXP(event.getEntity());
}
}
if (!event.isCancelled()) {
if (!checkPermission(player, NoLimitPermissions.DROP)) {
mod.getNoDropMobs().preventDrop(event.getEntity());
}
}
}
}
@ -186,8 +256,9 @@ public class PlayerListener implements Listener {
*/
private boolean isChest(Block block) {
return block.getState() instanceof InventoryHolder ||
block.getState() instanceof DirectionalContainer ||
block.getState() instanceof BeaconInventory;
block.getState().getData() instanceof DirectionalContainer ||
block.getType().equals(Material.ENDER_CHEST) ||
block.getType().equals(Material.BEACON);
}
private boolean checkPermission(Player player, IAbstractPermission perm) {
@ -199,4 +270,7 @@ public class PlayerListener implements Listener {
private boolean checkPermission(PlayerEvent event, IDynamicPermission perm) {
return mod.getPlugin().getPermManager().hasPermission(event.getPlayer(), perm);
}
private boolean checkPermission(Player player, IDynamicPermission perm) {
return mod.getPlugin().getPermManager().hasPermission(player, perm);
}
}

View file

@ -0,0 +1,47 @@
package de.jaschastarke.minecraft.limitedcreative.limits;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import de.jaschastarke.minecraft.limitedcreative.ModCreativeLimits;
public class VehicleListener implements Listener {
private ModCreativeLimits mod;
public VehicleListener(ModCreativeLimits mod) {
this.mod = mod;
}
@EventHandler(ignoreCancelled = true)
public void onVehicleDestroy(VehicleDestroyEvent event) {
if (event.getAttacker() instanceof Player) {
Player player = (Player) event.getAttacker();
if (player.getGameMode() == GameMode.CREATIVE && !mod.getPlugin().getPermManager().hasPermission(player, NoLimitPermissions.DROP)) {
switch (event.getVehicle().getType()) {
case MINECART:
mod.getBlockSpawn().block(event.getVehicle().getLocation().getBlock().getLocation(), Material.MINECART);
break;
case MINECART_CHEST:
mod.getBlockSpawn().block(event.getVehicle().getLocation().getBlock().getLocation(), Material.STORAGE_MINECART);
break;
case MINECART_FURNACE:
mod.getBlockSpawn().block(event.getVehicle().getLocation().getBlock().getLocation(), Material.POWERED_MINECART);
break;
case MINECART_HOPPER:
mod.getBlockSpawn().block(event.getVehicle().getLocation().getBlock().getLocation(), Material.HOPPER_MINECART);
break;
case MINECART_TNT:
mod.getBlockSpawn().block(event.getVehicle().getLocation().getBlock().getLocation(), Material.EXPLOSIVE_MINECART);
break;
default:
break;
}
}
}
}
}

View file

@ -13,6 +13,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import de.jaschastarke.bukkit.lib.Utils;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
@ -50,7 +51,7 @@ public class BlockListener extends Listener {
}
} else if (diffrent_region) {
// do not break inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(block).getFlag(Flags.GAMEMODE) != null) {
if (getRM().getRegionSet(block).getFlag(Flags.GAMEMODE) != null && getRM().getRegionSet(block).getFlag(Flags.GAMEMODE, player) != player.getGameMode()) {
player.sendMessage(L("blocked.inside_break"));
event.setCancelled(true);
}
@ -59,6 +60,8 @@ public class BlockListener extends Listener {
// prevent any drops for survival players in creative regions
if (player.getGameMode() != GameMode.CREATIVE && getRM().getRegionSet(block).getFlag(Flags.GAMEMODE) == GameMode.CREATIVE) {
mod.getBlockSpawn().block(block, player);
if (event instanceof BlockBreakEvent)
((BlockBreakEvent) event).setExpToDrop(0);
}
}
}
@ -79,7 +82,27 @@ public class BlockListener extends Listener {
}
} else if (diffrent_region) {
// do not build inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE) != null) {
if (/*getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE) != null && */getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE, event.getPlayer()) != event.getPlayer().getGameMode()) {
event.getPlayer().sendMessage(L("blocked.inside_place"));
event.setCancelled(true);
}
}
}
@EventHandler(ignoreCancelled = true)
public void onHangingPlace(HangingPlaceEvent event) {
PlayerMeta pdata = new PlayerMeta(event.getPlayer());
boolean diffrent_region = getRM().isDiffrentRegion(event.getPlayer(), event.getEntity().getLocation());
if (pdata.isActiveRegionGameMode() && diffrent_region) {
// do not build outside of "gamemod-change-region" when in the region
if (getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE, event.getPlayer()) != pdata.getActiveRegionGameMode()) {
event.getPlayer().sendMessage(L("blocked.outside_place"));
event.setCancelled(true);
}
} else if (diffrent_region) {
// do not build inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE) != null && getRM().getRegionSet(event.getBlock()).getFlag(Flags.GAMEMODE, event.getPlayer()) != event.getPlayer().getGameMode()) {
event.getPlayer().sendMessage(L("blocked.inside_place"));
event.setCancelled(true);
}

View file

@ -1,12 +1,10 @@
package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.GameMode;
import org.bukkit.command.CommandSender;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import org.bukkit.GameMode;
/**
* Well, that was an interesting idea, but it doesn't work.
@ -17,7 +15,8 @@ public class GameModeFlag extends Flag<GameMode> {
}
@Override
public GameMode parseInput(WorldGuardPlugin plugin, CommandSender sender, String input) throws InvalidFlagFormat {
public GameMode parseInput(FlagContext context) throws InvalidFlagFormat {
String input = context.getUserInput();
input = input.trim();
if (input.equalsIgnoreCase("creative")) {
return GameMode.CREATIVE;

View file

@ -0,0 +1,9 @@
package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
public interface IWorldGuardIntegration {
public void initFlagList();
public boolean isRegionOptional(Player player, GameMode tgm);
}

View file

@ -84,22 +84,25 @@ public class PlayerData {
return getGameMode("region_gamemode");
}
public void storeActiveRegionGameMode(GameMode regionGameMode) {
getSect(n()).set("region_gamemode", regionGameMode);
getSect(n()).set("region_gamemode", regionGameMode != null ? regionGameMode.toString() : null);
cleanUp();
save();
}
public GameMode getPermanentRegionGameMode() {
return getGameMode("permanent_gamemode");
}
public void storePermanentGameMode(GameMode currentGameMode) {
getSect(n()).set("permanent_gamemode", currentGameMode);
getSect(n()).set("permanent_gamemode", currentGameMode != null ? currentGameMode.toString() : null);
cleanUp();
save();
}
public GameMode getOptionalRegionGameMode(String regionHash) {
return getGameMode("optional_gamemode." + regionHash);
}
public void setOptionalRegionGameMode(String regionHash, GameMode currentGameMode) {
getSect(n()+".optional_gamemode").set(regionHash, currentGameMode);
getSect(n()+".optional_gamemode").set(regionHash, currentGameMode != null ? currentGameMode.toString() : null);
cleanUp();
save();
}
private GameMode getGameMode(String path) {

View file

@ -2,6 +2,7 @@ package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
@ -9,7 +10,10 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.material.Button;
@ -23,11 +27,8 @@ public class PlayerListener extends Listener {
super(mod);
}
@EventHandler
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (isCancelled(event))
return;
if (event.getAction() != Action.RIGHT_CLICK_BLOCK)
return;
@ -49,26 +50,74 @@ public class PlayerListener extends Listener {
}
} else if (diffrent_region) {
// do not break inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(block).getFlag(Flags.GAMEMODE) != null) {
if (getRM().getRegionSet(block).getFlag(Flags.GAMEMODE, event.getPlayer()) != event.getPlayer().getGameMode()) {
event.getPlayer().sendMessage(L("blocked.inside_interact"));
event.setCancelled(true);
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
PlayerMeta pmeta = new PlayerMeta(event.getPlayer());
Location loc = event.getRightClicked().getLocation();
boolean diffrent_region = getRM().isDiffrentRegion(event.getPlayer(), loc);
private boolean isRegionOptional(Player player) {
return mod.getRegionManager().getRegionSet(player.getLocation()).allows(Flags.GAMEMODE_OPTIONAL, player);
if (pmeta.isActiveRegionGameMode() && diffrent_region) {
// do not break outside of "gamemod-change-region" when in the region
if (getRM().getRegionSet(loc).getFlag(Flags.GAMEMODE, event.getPlayer()) != pmeta.getActiveRegionGameMode()) {
event.getPlayer().sendMessage(L("blocked.outside_interact_entity"));
event.setCancelled(true);
}
} else if (diffrent_region) {
// do not break inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(loc).getFlag(Flags.GAMEMODE, event.getPlayer()) != event.getPlayer().getGameMode()) {
event.getPlayer().sendMessage(L("blocked.inside_interact_entity"));
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.LOW)
@EventHandler(ignoreCancelled = true)
public void onPlayerDamange(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof Player) {
PlayerMeta pmeta = new PlayerMeta((Player) event.getDamager());
Location loc = event.getEntity().getLocation();
boolean diffrent_region = getRM().isDiffrentRegion((Player) event.getDamager(), loc);
if (pmeta.isActiveRegionGameMode() && diffrent_region) {
// do not break outside of "gamemod-change-region" when in the region
if (getRM().getRegionSet(loc).getFlag(Flags.GAMEMODE, (Player) event.getDamager()) != pmeta.getActiveRegionGameMode()) {
event.getDamager().sendMessage(L("blocked.outside_interact_entity"));
event.setCancelled(true);
}
} else if (diffrent_region) {
// do not break inside of "survial-region in creative world" when outside
if (getRM().getRegionSet(loc).getFlag(Flags.GAMEMODE, (Player) event.getDamager()) != ((Player) event.getDamager()).getGameMode()) {
event.getDamager().sendMessage(L("blocked.inside_interact_entity"));
event.setCancelled(true);
}
}
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) {
onPlayerInteractEntity(event);
}
private boolean isRegionOptional(Player player) {
return mod.getRegionManager().getRegionSet(player.getLocation()).allows(Flags.GAMEMODE_OPTIONAL);
}
@EventHandler(ignoreCancelled = true)
public void onGameModeChange(PlayerGameModeChangeEvent event) {
Player player = event.getPlayer();
PlayerMeta pmeta = new PlayerMeta(player);
GameMode gm = event.getNewGameMode();
if (mod.isDebug())
mod.getLog().debug(player.getName() + " is changing to GameMode " + gm);;
mod.getLog().debug(player.getName() + " is changing to GameMode " + gm);
if (Hooks.IsLoggedIn.test(player)) { // if authme is changing GameMode before going to teleport, this should be remembered
if (pmeta.isActiveRegionGameMode()) { // change to the other gamemode as the area defines
if (!pmeta.isActiveRegionGameMode(gm)) { // only when we are not switching to the mode the region allows

View file

@ -3,16 +3,18 @@ package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.configuration.ConfigurationSection;
import de.jaschastarke.bukkit.lib.configuration.Configuration;
import de.jaschastarke.bukkit.lib.configuration.ConfigurationContainer;
import de.jaschastarke.configuration.IConfigurationNode;
import de.jaschastarke.configuration.IConfigurationSubGroup;
import de.jaschastarke.configuration.InvalidValueException;
import de.jaschastarke.configuration.annotations.IsConfigurationNode;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginConfigurations;
import de.jaschastarke.minecraft.limitedcreative.Config;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
import de.jaschastarke.minecraft.limitedcreative.limits.BlackList;
import de.jaschastarke.modularize.IModule;
import de.jaschastarke.modularize.ModuleEntry;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
/**
* Region GameModes-Feature
@ -20,11 +22,16 @@ import de.jaschastarke.modularize.ModuleEntry.ModuleState;
* http://dev.bukkit.org/server-mods/limited-creative/pages/features/region/
*/
@ArchiveDocComments
@PluginConfigurations(parent = Config.class)
public class RegionConfig extends Configuration implements IConfigurationSubGroup {
protected ModRegions mod;
protected ModuleEntry<IModule> entry;
public RegionConfig(ConfigurationContainer container) {
super(container);
}
public RegionConfig(ModRegions modRegions, ModuleEntry<IModule> modEntry) {
super(modRegions.getPlugin().getDocCommentStorage());
mod = modRegions;
entry = modEntry;
}
@ -34,19 +41,13 @@ public class RegionConfig extends Configuration implements IConfigurationSubGrou
if (!(pValue instanceof BlackList))
super.setValue(node, pValue);
if (node.getName().equals("enabled")) {
if (getEnabled()) {
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.enable();
} else {
entry.disable();
}
entry.setEnabled(getEnabled());
}
}
@Override
public void setValues(ConfigurationSection sect) {
super.setValues(sect);
if (entry.initialState != ModuleState.NOT_INITIALIZED)
entry.initialState = getEnabled() ? ModuleState.ENABLED : ModuleState.DISABLED;
entry.setDefaultEnabled(getEnabled());
// Config Upgrade
if (!sect.contains("rememberOptional") && sect.contains("remember"))
@ -113,10 +114,12 @@ public class RegionConfig extends Configuration implements IConfigurationSubGrou
* When the player is more than this count of blocks above the ground, he is prevented from changing the region that
* sets him survival which would cause him falling and hurting.
*
* Set to -1 to disable
*
* default: 3
*/
@IsConfigurationNode(order = 500)
public int getMaximumFloatingHeight() {
public int getMaxFallingHeight() {
return config.getInt("maxFallingHeight", 3);
}

View file

@ -25,11 +25,16 @@ public class RegionListener extends Listener {
super(mod);
}
private boolean checkFloatingToHigh(int max, Location loc) {
if (max < 0)
return false;
return getFloatingHeight(loc) > max;
}
public int getFloatingHeight(Player player) {
return getFloatingHeight(player.getLocation());
}
public int getFloatingHeight(Location loc) {
Block b = loc.getBlock();
Block b = loc.getBlock().getRelative(BlockFace.DOWN);
int steps = 0;
while (b.getType() == Material.AIR) {
steps++;
@ -39,7 +44,7 @@ public class RegionListener extends Listener {
}
private boolean checkSwitchFlight(PlayerMoveEvent event) {
if (event != null && event.getPlayer().getGameMode() == GameMode.CREATIVE && getFloatingHeight(event.getTo()) > mod.getConfig().getMaximumFloatingHeight()) {
if (event != null && event.getPlayer().getGameMode() == GameMode.CREATIVE && checkFloatingToHigh(mod.getConfig().getMaxFallingHeight(), event.getTo())) {
// but not if he is too high
Utils.sendTimeoutMessage(event.getPlayer(), L("blocked.survival_flying"));
@ -68,11 +73,14 @@ public class RegionListener extends Listener {
if (mod.isDebug())
mod.getLog().debug(player.getName()+": changed region: "+regionGameMode+": " + areaEvent);
PlayerMoveEvent moveEvent = null;
GameMode defaultGameMode;
if (areaEvent instanceof PlayerChangedAreaEvent)
moveEvent = ((PlayerChangedAreaEvent) areaEvent).getMoveEvent();
defaultGameMode = Hooks.DefaultWorldGameMode.get(((PlayerChangedAreaEvent) areaEvent).getMoveEvent().getTo().getWorld());
else if (areaEvent instanceof PlayerNewLocationAreaEvent)
defaultGameMode = Hooks.DefaultWorldGameMode.get(((PlayerNewLocationAreaEvent) areaEvent).getNewLocation().getWorld());
else
defaultGameMode = Hooks.DefaultWorldGameMode.get(player.getWorld());
GameMode currentGameMode = player.getGameMode();
GameMode defaultGameMode = Hooks.DefaultWorldGameMode.get(moveEvent != null ? moveEvent.getTo().getWorld() : player.getWorld());
if (regionGameMode != null && currentGameMode != regionGameMode && !pmeta.isActiveRegionGameMode(regionGameMode)) {
if (mod.isDebug())
@ -88,9 +96,11 @@ public class RegionListener extends Listener {
pmeta.storeActiveRegionGameMode(regionGameMode); // have to be set, before setGameMode
if (!isOptional) {
if (Hooks.IsLoggedIn.test(player)) { // don't change gamemode on login
player.setGameMode(regionGameMode);
}
}
}
} else if (regionGameMode == null && player.getGameMode() != defaultGameMode && !pmeta.isInPermanentGameMode(currentGameMode) && pmeta.getActiveRegionGameMode() != null) {
if (mod.isDebug())
mod.getLog().debug(player.getName()+": leaving creative area");
@ -101,8 +111,10 @@ public class RegionListener extends Listener {
// result: change him back to default mode
if (checkSwitchFlight(areaEvent)) {
pmeta.storeActiveRegionGameMode(null);
if (Hooks.IsLoggedIn.test(player)) { // don't change gamemode on login
player.setGameMode(defaultGameMode);
}
}
} else if (regionGameMode == null && pmeta.isActiveRegionGameMode()) {
if (mod.isDebug())
mod.getLog().debug(player.getName()+": leaving creative area (while already in default gamemode)");

View file

@ -3,6 +3,7 @@ package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.permissions.PermissionDefault;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginPermissions;
import de.jaschastarke.minecraft.lib.permissions.BasicPermission;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.lib.permissions.IPermission;
@ -26,6 +27,7 @@ final public class RegionPermissions extends SimplePermissionContainerNode imple
/**
* Grants access to the /lcr command, which allows to define Limited Creatives region-flags
*/
@PluginPermissions
public static final RegionPermissions REGION = new RegionPermissions(Permissions.CONTAINER, "region");
/**

View file

@ -1,33 +1,40 @@
package de.jaschastarke.minecraft.limitedcreative.regions;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.World;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import de.jaschastarke.LocaleString;
import de.jaschastarke.bukkit.lib.chat.ChatFormattings;
import de.jaschastarke.bukkit.lib.commands.BukkitCommand;
import de.jaschastarke.bukkit.lib.commands.CommandContext;
import de.jaschastarke.bukkit.lib.commands.CommandException;
import de.jaschastarke.bukkit.lib.commands.HelpCommand;
import de.jaschastarke.bukkit.lib.commands.IHelpDescribed;
import de.jaschastarke.bukkit.lib.commands.MissingPermissionCommandException;
import de.jaschastarke.bukkit.lib.commands.*;
import de.jaschastarke.bukkit.lib.commands.annotations.IsCommand;
import de.jaschastarke.bukkit.lib.commands.annotations.Usages;
import de.jaschastarke.bukkit.lib.commands.parser.DefinedParameterParser;
import de.jaschastarke.bukkit.lib.commands.parser.TabCompletion;
import de.jaschastarke.bukkit.lib.commands.parser.TabCompletion.Completer;
import de.jaschastarke.bukkit.lib.commands.parser.TabCompletion.Context;
import de.jaschastarke.maven.ArchiveDocComments;
import de.jaschastarke.maven.PluginCommand;
import de.jaschastarke.minecraft.lib.permissions.IAbstractPermission;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.FlagList;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.FlagValue;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.Region;
import de.jaschastarke.modularize.ModuleEntry.ModuleState;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
/**
* LimitedCreative-Region-Command: configure creative regions
@ -35,16 +42,22 @@ import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.Region;
* @permission limitedcreative.region
*/
@ArchiveDocComments
@PluginCommand
public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
private final static String GLOBAL_REGION = "__global__";
private ModRegions mod;
private HelpCommand help;
private WorldGuardPlugin wg;
public RegionsCommand() {
this.help = this.getDefaultHelpCommand();
}
public RegionsCommand(ModRegions mod) {
this.mod = mod;
super(mod.getPlugin());
this.help = this.getDefaultHelpCommand();
this.mod = mod;
this.wg = (WorldGuardPlugin) mod.getPlugin().getServer().getPluginManager().getPlugin(WorldGuardIntegration.PLUGIN_NAME);
fullfillTabCompletion();
}
@Override
@ -57,6 +70,12 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
return new String[]{"/region"};
}
public boolean execute(final CommandContext context, final String[] args) throws MissingPermissionCommandException, CommandException {
if (mod.getModuleEntry().getState() != ModuleState.ENABLED)
throw new CommandException("Module " + mod.getName() + " is disabled");
return super.execute(context, args);
}
/**
* @internal has no effect, as not tested by any command handler
* @see IHelpDescribed
@ -86,6 +105,49 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
return RegionPermissions.REGION.getPermission(subPerm);
}*/
protected void fullfillTabCompletion() {
for (ICommand cmd : handler.getCommands()) {
if (cmd instanceof MethodCommand) {
if (cmd.getName().equals("info")) {
((MethodCommand) cmd).getCompleter().add(TabCompletion.forUsageLine("[region]"));
}
for (TabCompletion c : ((MethodCommand) cmd).getCompleter()) {
c.setCompleter("region", new RegionCompleter());
}
}
}
}
private class RegionCompleter implements Completer {
@Override
public List<String> get(Context context, String arg) {
int idx = -1;
String[] args = context.getHelper().getArguments();
for (int i = 0; i < args.length; i++) {
if (args[i].equals("world")) {
idx = i;
break;
}
}
World w = context.getCommandContext().isPlayer() ? context.getCommandContext().getPlayer().getWorld() : null;
if (idx > -1 && context.getArgument(idx) != null)
w = Bukkit.getWorld(context.getArgument(idx));
if (w != null) {
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionManager mgr = container.get(BukkitAdapter.adapt(w));
if (mgr != null) {
List<String> hints = new ArrayList<String>();
for (String rId : mgr.getRegions().keySet()) {
if (rId.toLowerCase().startsWith(arg.toLowerCase()))
hints.add(rId);
}
return hints;
}
}
return null;
}
}
/**
* Sets the Flag of a region to a new value. If no value given, the flag is removed.
* -g sets the affected group of the flag, instead the flag (equivalent to using flag-group as flag-name)
@ -108,7 +170,8 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
if (w == null)
throw new CommandException(L("command.worldguard.world_not_found"));
RegionManager mgr = mod.getWorldGuard().getGlobalRegionManager().get(w);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionManager mgr = container.get(BukkitAdapter.adapt(w));
ProtectedRegion region = mgr.getRegion(params.getArgument(0));
if (region == null && params.getArgument(0).equalsIgnoreCase("__global__")) {
region = new GlobalProtectedRegion(params.getArgument(0));
@ -124,12 +187,19 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
String msg = L("command.worldguard.unknown_flag") + params.getArgument(1) + "\n"
+ L("command.worldguard.available_flags") + FlagList.getStringListAvailableFlags(context.getSender());
throw new CommandException(msg);
} else if (params.getFlags().contains("g")) {
flag = flag.getRegionGroupFlag();
if (flag == null) {
String msg = L("command.worldguard.unknown_flag") + params.getArgument(1) + "-group\n"
+ L("command.worldguard.available_flags") + FlagList.getStringListAvailableFlags(context.getSender());
throw new CommandException(msg);
}
}
String value = params.getValue();
try {
if (value != null) {
reg.setFlag(flag, flag.parseInput(mod.getWorldGuard(), context.getSender(), value));
if (value != null && value.trim().length() > 0) {
reg.setFlag(flag, flag.parseInput(FlagContext.create().setInput(value).build()));
} else {
reg.setFlag(flag, null);
}
@ -144,7 +214,7 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
@IsCommand("info")
//@NeedsPermission("region")
@Usages("[world] [id]")
@Usages("[world] [region]")
public boolean getInfo(CommandContext context, String... args) throws CommandException {
DefinedParameterParser params = new DefinedParameterParser(args, new String[]{"s"}, 1);
@ -164,17 +234,20 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
throw new CommandException(L("command.worldguard.world_not_found"));
ProtectedRegion region = null;
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
if (params.getArgumentCount() == 0 && context.isPlayer()) {
RegionManager mgr = mod.getWorldGuard().getGlobalRegionManager().get(context.getPlayer().getWorld());
ApplicableRegionSet set = mgr.getApplicableRegions(context.getPlayer().getLocation());
RegionManager mgr = container.get(BukkitAdapter.adapt(context.getPlayer().getWorld()));
ApplicableRegionSet set = mgr.getApplicableRegions(BukkitAdapter.asBlockVector(context.getPlayer().getLocation()));
if (set.size() > 0) {
region = set.iterator().next();
} else {
region = container.get(BukkitAdapter.adapt(w)).getRegion(GLOBAL_REGION);
}
} else {
int rpc = params.getArgumentCount() > 1 ? 1 : 0;
RegionManager mgr = mod.getWorldGuard().getGlobalRegionManager().get(w);
RegionManager mgr = container.get(BukkitAdapter.adapt(w));
region = mgr.getRegion(params.getArgument(rpc));
if (region == null && params.getArgument(rpc).equalsIgnoreCase("__global__")) {
if (region == null && params.getArgument(rpc).equalsIgnoreCase(GLOBAL_REGION)) {
region = new GlobalProtectedRegion(params.getArgument(rpc));
mgr.addRegion(region);
}
@ -200,4 +273,8 @@ public class RegionsCommand extends BukkitCommand implements IHelpDescribed {
private String L(String msg, Object... args) {
return mod.getPlugin().getLocale().trans(msg, args);
}
private WorldGuardPlugin getWorldGuard() {
return wg;
}
}

View file

@ -0,0 +1,35 @@
package de.jaschastarke.minecraft.limitedcreative.regions;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import de.jaschastarke.minecraft.limitedcreative.Hooks;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.ApplicableRegions;
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.FlagList;
public class WorldGuardIntegration implements IWorldGuardIntegration {
public static final String PLUGIN_NAME = "WorldGuard";
private ModRegions mod;
public WorldGuardIntegration(ModRegions mod) {
this.mod = mod;
}
@Override
public void initFlagList() {
FlagList.addFlags(Flags.getList());
}
@Override
public boolean isRegionOptional(Player player, GameMode tgm) {
ApplicableRegions rs = mod.getRegionManager().getRegionSet(player.getLocation());
if (rs.allows(Flags.GAMEMODE_OPTIONAL)) {
if ((tgm == rs.getFlag(Flags.GAMEMODE, player)) || (tgm == Hooks.DefaultWorldGameMode.get(player.getWorld())))
return true;
}
return false;
}
}

View file

@ -22,6 +22,7 @@ import org.bukkit.entity.Player;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.StateFlag.State;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
public class ApplicableRegions {
@ -36,28 +37,28 @@ public class ApplicableRegions {
public boolean allows(StateFlag flag) {
extendRegionFlags();
boolean r = regions.allows(flag);
boolean r = regions.queryState(null, flag).equals(State.ALLOW);
contractRegionFlags();
return r;
}
public boolean allows(StateFlag flag, Player player) {
extendRegionFlags();
boolean r = regions.allows(flag, mgr.getWorldGuard().wrapPlayer(player));
boolean r = regions.queryState(mgr.getWorldGuard().wrapPlayer(player), flag).equals(State.ALLOW);
contractRegionFlags();
return r;
}
public <T extends Flag<V>, V> V getFlag(T flag) {
extendRegionFlags();
V r = regions.getFlag(flag);
V r = regions.queryValue(null, flag);
contractRegionFlags();
return r;
}
public <T extends Flag<V>, V> V getFlag(T flag, Player player) {
extendRegionFlags();
V r = regions.getFlag(flag, mgr.getWorldGuard().wrapPlayer(player));
V r = regions.queryValue(mgr.getWorldGuard().wrapPlayer(player), flag);
contractRegionFlags();
return r;
}

View file

@ -17,14 +17,16 @@
*/
package de.jaschastarke.minecraft.limitedcreative.regions.worldguard;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
import de.jaschastarke.minecraft.limitedcreative.regions.WorldGuardIntegration;
import de.jaschastarke.utils.StringUtil;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
@ -32,15 +34,9 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import com.sk89q.worldguard.bukkit.BukkitUtil;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.GlobalRegionManager;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import de.jaschastarke.minecraft.limitedcreative.ModRegions;
import de.jaschastarke.utils.StringUtil;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class CustomRegionManager {
protected YamlConfiguration c;
@ -107,7 +103,11 @@ public class CustomRegionManager {
ConfigurationSection fs = rs.contains("flags") ? rs.getConfigurationSection("flags") : rs.createSection("flags");
if (value == null) {
fs.set(flag.getName(), null);
} else {
fs.set(flag.getName(), flag.marshal((V) value));
}
try {
c.save(file);
@ -148,20 +148,22 @@ public class CustomRegionManager {
}
public WorldGuardPlugin getWorldGuard() {
return mod.getWorldGuard();
return CustomRegionManager.this.getWorldGuard();
}
}
public GlobalRegionManager getWGGlobalManager() {
return mod.getWorldGuard().getGlobalRegionManager();
private WorldGuardPlugin getWorldGuard() {
return ((WorldGuardPlugin) mod.getPlugin().getServer().getPluginManager().getPlugin(WorldGuardIntegration.PLUGIN_NAME));
}
public RegionManager getWGManager(World world) {
return mod.getWorldGuard().getRegionManager(world);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
return container.get(BukkitAdapter.adapt(world));
}
public String getRegionsHash(Location loc) {
StringBuilder hash = new StringBuilder(loc.getWorld().getName());
List<String> idlist = getWGGlobalManager().get(loc.getWorld()).getApplicableRegionsIDs(BukkitUtil.toVector(loc));
List<String> idlist = getWGManager(loc.getWorld()).getApplicableRegionsIDs(BukkitAdapter.asBlockVector(loc));
if (idlist.size() > 0) {
hash.append("#");
String[] ids = idlist.toArray(new String[idlist.size()]);
@ -174,7 +176,7 @@ public class CustomRegionManager {
}
public ApplicableRegions getRegionSet(Location loc) {
return new ApplicableRegions(getWGManager(loc.getWorld()).getApplicableRegions(loc), this.world(loc.getWorld()));
return new ApplicableRegions(getWGManager(loc.getWorld()).getApplicableRegions(BukkitAdapter.asBlockVector(loc)), this.world(loc.getWorld()));
}
public ApplicableRegions getRegionSet(Block block) {

View file

@ -49,14 +49,11 @@ public class Region {
}
public void setFlag(Flag<?> flag, Object value) {
if (value == null) {
removeFlag(flag);
} else {
if (flags != null)
if (flags != null && value != null)
flags.add(new FlagValue(flag, value));
mgr.storeFlag(this, flag, value);
}
}
public ProtectedRegion getProtectedRegion() {
return region;
}

View file

@ -69,4 +69,7 @@ public class PlayerNewLocationAreaEvent extends PlayerAreaEvent {
public static HandlerList getHandlerList() {
return handlers;
}
public Location getNewLocation() {
return location;
}
}

View file

@ -17,7 +17,6 @@
*/
package de.jaschastarke.minecraft.limitedcreative.regions.worldguard.events;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
@ -25,11 +24,11 @@ import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.ApplicableRe
import de.jaschastarke.minecraft.limitedcreative.regions.worldguard.CustomRegionManager;
public class PlayerUpdateAreaEvent extends PlayerAreaEvent {
private String player;
private Player player;
private String hash;
protected CustomRegionManager mgr;
public PlayerUpdateAreaEvent(CustomRegionManager mgr, String player, String hash) {
public PlayerUpdateAreaEvent(CustomRegionManager mgr, Player player, String hash) {
this.mgr = mgr;
this.player = player;
this.hash = hash;
@ -46,7 +45,7 @@ public class PlayerUpdateAreaEvent extends PlayerAreaEvent {
@Override
public Player getPlayer() {
return Bukkit.getServer().getPlayerExact(player);
return player;
}
private static final HandlerList handlers = new HandlerList();

View file

@ -1,55 +0,0 @@
basic.loaded.worldguard: Erfolgreich mit WorldGuard-Integration geladen
basic.loaded.no_worldguard: Erfolgreich geladen (ohne WorldGuard)
basic.loaded.module: Modul geladen.
basic.feature.store: Getrennte Inventare
basic.feature.limit: Kreativ-Einschränkungen
basic.feature.region: Kreativ-Regionen
basic.conflict: Wegen eines Konfliktes mit {0} ist die Funktion {1} deaktiviert
basic.warning.worldguard_not_found: WorldGuard wurd enicht gefunde, dahier ist die Funktion {0} deaktiviert
command.player: Spieler
command.switch.survival: Ändert den Spiel-Modus des Charakters zu überleben
command.switch.creative: Ändert den Spiel-Modus des Charakters zu Kreativ
command.switch.adventure: Ändert den Spiel-Modus des Charakters zu Abenteuer
command.switch.config.overview: "[Einstellung] - liste durch weglassen"
command.switch.config.settings: "Verfügbare Einstellungen: "
command.switch.config.reload: Lädt das Plugin neu (funktioniert nur teilweise)
command.gamemode.changed: "{0}'s Spiel-Modus wurde geändert"
command.gamemode.no_change: Bereits in diesem Spiel-Modus
command.option.done: Option geändert.
command.worldguard.alias: Alias für den //region-Befehl
command.worldguard.unknown_flag: Unbekanntes Attribut
command.worldguard.available_flags: Verfügbare Attribute
command.worldguard.region_not_found: Keine Region mit dieser ID gefunden
command.worldguard.world_not_found: Es konnte keine Welt mit diesem Namen gefunden werden
command.worldguard.no_flag_given: Es muss ein Attribut angegeben werden, dass gesetzt werden soll
command.worldguard.no_integration: Der worldguard-Befehl ist nicht verfügbar, da WorldGuard nicht gefunden wurde
command.worldguard.flag_set: "Das Attribut {0} wurde gesetzt"
command.worldguard.additional_flags: Zusätzliche Attribute
cmdblock.blocked: Dieser Befehl ist im Kreativ-Modus blockiert.
exception.command.lackingpermission: Kein Zugriff auf diesen Befehl
exception.command.toomuchparameter: Zuviele Argumente angegeben
exception.command.missingparameter: Nicht genügen Argumente angegeben
exception.command.playernotfound: Spieler nicht gefunden
exception.command.invalidoption: Unbkeannte Option
exception.config.savefail: Die Konfiguration konnte nicht gespeichert werden
exception.config.material_not_found: (Konfiguration) Material mit Name/ID "{0}" wurde nicht gefunden.
exception.storage.load: Fehler beim Laden des Inventars. Bitte einen Admin die Option "UnsafeStorege" in LimitedCreative zu aktivieren um ungültig verzauberte Gegenstände zu erlauben
exception.region.not_optional: "In dieser Region kannst du nicht im folgenden Modus sein: {0}"
blocked.chest: Zugriff auf Truhen ist im Kreativ-Modus nicht erlaubt
blocked.sign: Im Kreativ-Modus kann nicht mit Schildern interagiert werden
blocked.button: Im Kreativ-Modus kann nicht mit Buttons interagiert werden
blocked.lever: Im Kreativ-Modus kann nicht mit Schaltern interagiert werden
blocked.survival_flying: Du solltest auf dem Boden stehen wenn du Kreativ-Regionen verlässt
blocked.outside_place: Du kannst keine Blöcke auÿerhalb von Spiel-Modus-Regionen setzen
blocked.outside_break: Du kannst keine Blöcke auÿerhalb von Spiel-Modus-Regionen zerstören
blocked.inside_place: Du kannst keine Blöcke innerhalb von Spiel-Modus-Regionen setzen
blocked.inside_break: Du kannst keine Blöcke innerhalb von Spiel-Modus-Regionen zerstören
blocked.use: Du darfst diese Art von Gegenständen im Kreativ-Modus verwenden
blocked.place: Du darfst diese Art von Blöcken im Kreativ-Modus nicht setzen
blocked.break: Du darfst diese Art von Blöcken im Kreativ-Modus nicht zerstören
blocked.piston: Verschieben von Block {0} aus einer Spiel-Modus-Region bei {1} wurde blockiert
blocked.piston_in: Verschieben von Block {0} in eine Spiel-Modus-Region bei {1} wurde blockiert

View file

@ -0,0 +1,2 @@
# This file is empty for purpose, it is only there to prevent ResourceBundle-load-error
# The strings are generated from DocComments to META-INF/doccomments.properties

View file

@ -1,4 +1,5 @@
basic.loaded.module: Module loaded.
basic.feature.gamemodecommands: GameMode-Commands
inventory.warning.conflict: Due to conflict with the plugin {0}, the feature {1} is disabled
region.warning.worldguard_not_found: WorldGuard isn''t found, the feature {0} is disabled
@ -10,6 +11,7 @@ command.regions: LimitedCreative-Region-Command: configure creative regions
command.switch.survival: Changes the game mode of a player to survival
command.switch.creative: Changes the game mode of a player to creative
command.switch.adventure: Changes the game mode of a player to adventure
command.switch.spectator: Changes the game mode of a player to spectator
command.config.reload: Reloads configuration and re-initializes all active modules.
command.config.reload.success: The plugin was successfully reloaded.
command.gamemode.changed: {0}''s game mode has been changed
@ -23,19 +25,42 @@ command.worldguard.world_not_found: Could not find a world by that name
command.worldguard.flag_set: "The flag {0} was set"
command.worldguard.additional_flags: Additional flags:
command.blockstate: LimitedCreative-BlockState-Command: modify blockstate database to prevent drops of selected blocks (requires WorldEdit)
command.blockstate.world_ignored: The BlockState-Feature is disabled for this World ({0})
command.blockstate.requires_worldedit: This command requires WorldEdit-Plugin
command.blockstate.worledit_selection_empty: Select a region with WorldEdit first
command.blockstate.command_updated: Successfully updated {0} blocks.
command.blockstate.command_failed: Failed to update blocks. See server.log for details.
command.blockstate.migrate_started: Database migration from {0} to {1} started...
command.blockstate.migrate_connect_error: Connection to database failed with error: {0}
command.blockstate.migrate_importtype_error: Unknown --import-type: {0}
command.blockstate.migration_finished: Database migration of {0} records successful.
command.blockstate.migration_finished_restart: A Server-Restart is required!
command.blockstate.migration_error: Migration failed with error: {0}
command.blockstate.migrate_useronline_error: There are players on the Server. The migration shouldn't be run with active players.
command.blockstate.migrate_confirm: Are you sure you want to start the migration? It may take a very long time and much CPU. To confirm execution run the command with the following added: {0}
command.blockstate.nothing_to_cleanup: Nothing to cleanup
command.blockstate.cleanup_success: Successfully removed {0} entries from database
command.blockstate.cleanup_error: Error while cleaning database. Check server.log
cmdblock.blocked: This command is blocked while in creative mode.
cmdblock.blocked.requires_worldedit: WorlEdit is required to use this command
cmdblock.blocked.not_console: This command can not be used from console
exception.config.material_not_found: (Config) Material with name/id "{0}" was not found.
exception.region.not_optional: You can not be {0} in that area
blocked.inventory: Opening inventories is not allowed in creative mode
blocked.chest: Access to chests is not allowed in creative mode
blocked.survival_flying: You should stay on ground, when leaving a creative-area
blocked.outside_place: You can not place blocks outside of the gamemode-area
blocked.outside_break: You can not destroy blocks outside of the gamemode-area
blocked.outside_interact: You can not interact with those blocks outside of the gamemode-area
blocked.outside_interact_entity: You can not interact with out of the gamemode-area
blocked.inside_place: You can not place blocks inside of the gamemode-area
blocked.inside_break: You can not destroy blocks inside of the gamemode-area
blocked.inside_interact: You can not interact with those blocks inside of the gamemode-area
blocked.inside_interact_entity: You can not interact with this into gamemode-area
blocked.interact: You are not allowed to interact with this type of blocks
blocked.entity: You are not allowed to interact with this type of entity
blocked.use: You are not allowed to use this type of item
@ -45,8 +70,10 @@ blocked.break: You are not allowed to break this type of block
blocked.region.piston: Moving {0} block out of creative area was blocked at {1}
blocked.region.piston_in: Moving {0} block into creative area was blocked at {1}
block_state.warning.worldedit_sessionfactory_failed: Failed to hook into WorldEdit. WorldEdit-actions can''t be traced. Error: {0}
block_state.tool_info.seed: This {0}-Block is generated by the god who created this world
block_state.tool_info.player: This {0}-Block was created by ''{1}'' in {2}-mode on {3}
block_state.tool_info.edit: This {0}-Block was modified by the tool ''{1}'' or such at {3}
block_state.tool_info.edit: This {0}-Block was modified with WorldEdit by ''{1}'' on {3}
block_state.tool_info.command: This {0}-Block was manually set to {2}-mode via command by ''{1}'' on {3}
block_state.tool_info.unknown: The origin of this {0}-Block is unknown
block_state.error.sql_connection_failed: Failed to connect to Database. Check bukkit.yml

View file

@ -0,0 +1,79 @@
basic.loaded.module: Modul geladen.
basic.feature.gamemodecommands: Spielmodus-Befehle
inventory.warning.conflict: Wegen eines Konfliktes mit dem Plugin {0} wurde das Feature {1} deaktiviert
region.warning.worldguard_not_found: WorldGuard wurde nicht gefunden. Das Feature {0} wurde deaktiviert.
gmperm.warning.vault_not_found: Vault wurde nicht gefunden. Das Feature {0} wurde deaktiviert.
gmperm.warning.no_group_support: Das verwendete Permission-Plugin unterstüzzt keine Gruppen. Das Feature {0} wurde deaktiviert
command.general: LimitedCreative: GameMode-Wechsel, Kreativ-Regionen, Konfiguration und mehr
command.regions: LimitedCreative-Region-Kommando: Kreativ-Regionen konfigurieren
command.switch.survival: Ändert den Spielmodus des Spielers zu Überleben
command.switch.creative: Ändert den Spielmodus des Spielers zu Kreativ
command.switch.adventure: Ändert den Spielmodus des Spielers zu Abenteuer
command.switch.spectator: Ändert den Spielmodus des Spielers zu Beobachter
command.config.reload: Lädt die Konfiguration neu und initialisiert alle Module neu
command.config.reload.success: Das Plugin wurde erfolgreich neu geladen
command.gamemode.changed: {0}''s GameMode wurde geändert
command.gamemode.no_change: Ist bereits in diesem Modus
command.worldguard.alias: Alias für den //region-Befehl
command.worldguard.unknown_flag: Unbekanntes Attribut angegeben
command.worldguard.available_flags: Verfügbare Attribute:
command.worldguard.region_not_found: Konnte keine Region mit dieser ID finden
command.worldguard.world_not_found: Konnte keine Welt mit diesem namen finden
command.worldguard.flag_set: Das Attribut {0} wurde gesetzt
command.worldguard.additional_flags: Zusätzliche Attribute:
command.blockstate: LimitedCreative-BlockStatus-Kommando: Ändern der BlockStatus Datenbank um Beute aus den ausgewählten Blöcken zu verhindern (benötigt WorldEdit)
command.blockstate.world_ignored: Das BlockStatus-Modul ist für diese Welt deaktiviert ({0})
command.blockstate.requires_worldedit: Dieser Befehl benötigt WorldEdit
command.blockstate.worledit_selection_empty: Zuerst eine Region mit WorldEdit auswählen
command.blockstate.command_updated: Erfolgreich {0} Blöcke aktuallisiert
command.blockstate.command_failed: Fehler beim aktualisieren der Blöcke. Siehe server.log für Details
command.blockstate.migrate_started: Datenbank-Migration von {0} nach {1} gestartet...
command.blockstate.migrate_connect_error: Verbindung zur Datenbank mit folgendem Fehler fehlgeschlafen: {0}
command.blockstate.migrate_importtype_error: Unbekannter --import-Typ: {0}
command.blockstate.migration_finished: Datenbank-Migration von {0} Datensätzen erfolgreich
command.blockstate.migration_finished_restart: Server-Neustart notwendig!
command.blockstate.migration_error: Migration mit folgendem Fehler fehlgeschlagen: {0}
command.blockstate.migrate_useronline_error: Es sind Spieler auf dem Server. Die Migration sollte nicht mit aktiven Spielern ausgeführt werden.
command.blockstate.migrate_confirm: Bist du sicher. dass du die Migration starten willst? Dies dauert vermutlich sehr lange und benötigt viel Prozessor-Leistung. Um die Ausführung zu bestätigen führe den Befehl erneut mit folgendem Parameter aus: {0}
command.blockstate.nothing_to_cleanup: Nichts aufzuräumen
command.blockstate.cleanup_success: Erfolgreich {0} Datensätze aus der Datenbank gelöscht
command.blockstate.cleanup_error: Fehler beim Aufräumen der Datenbank. server.log prüfen
cmdblock.blocked: Dieses Kommando ist im Kreativ-Modus blockiert
cmdblock.blocked.requires_worldedit: WorldEdit wird für diesen Befehl benötigt
cmdblock.blocked.not_console: Dieser Befehl kann nicht in der Konsole ausgeführt werden
exception.config.material_not_found: (Konfiguration) Material mit dem Namen/der ID "{0}" wurde nicht gefunden
exception.region.not_optional: Du kannst in diesem Bereich nicht in den {0}-Modus
blocked.inventory: Inventar öffnen ist im Kreativ-Modus nicht gestattet
blocked.chest: Der Zugriff auf Truhen ist im Kreativ-Modus nicht gestattet.
blocked.survival_flying: Du solltest auf dem Boden stehen um einen Kreativ-Bereich zu verlassen
blocked.outside_place: Du kannst keine Blöcke aus einem GameMode-Bereich heraus bauen
blocked.outside_break: Du kannst keine Blöcke aus einem GameMode-Bereich heraus zerstören
blocked.outside_interact: Du kannst nicht mit Blöcken außerhalb eines GameMode-Bereichs interagieren
blocked.outside_interact_entity: Du kannst damit nicht aus einem GameMode-Bereich heraus interagieren
blocked.inside_place: Du kannst keine Blöcke in einen GameMode-Bereich herein bauen
blocked.inside_break: Du kannst von außerhalb keine Blöcke in einem GameMode-Bereich zerstören
blocked.inside_interact: Du kannst von außerhalb nicht mit Blöcken in einem GameMode-Bereich interagieren
blocked.inside_interact_entity: Du kannst damit nicht von außerhalb eines GameMode-Bereich interagieren
blocked.interact: Du darfst mit dieser Art Block nicht interagieren
blocked.entity: Du darfst nicht mit diesen Kreaturen interagieren
blocked.use: Du darfst diese Art Gegenstand nicht verwenden
blocked.place: Du darfst diese Art Block nicht platzieren
blocked.break: Du darfst diesen Block nicht zerstören
blocked.region.piston: Verschieben eines {0} Blocks aus einem GameMode-Bereich wurde bei {1} verhindet
blocked.region.piston_in: Verschieben eines {0} Blocks in einen GameMode-Bereich wurde bei {1} verhindet
block_state.warning.worldedit_sessionfactory_failed: Fehler beim Einhängen in WorldEdit. WorldEdit-Aktionen können nicht nachvollzogen werden. Fehler: {0}
block_state.tool_info.seed: Dieser {0}-Block wurde von dem Gott generiert der diese Welt erschuf
block_state.tool_info.player: Dieser {0}-Block wurde am {3} von ''{1}'' im {2}-Modus gebaut
block_state.tool_info.edit: Der {0}-Block wurde am {3} von ''{1}'' mit WorldEdit gesetzt
block_state.tool_info.command: Dieser {0}-Block wurde am {3} von ''{1}'' mittels Befehl manuell auf den {2}-Modus gesetzt
block_state.tool_info.unknown: Der Ursprung dieses {0}-Blocks ist unbekannt
block_state.error.sql_connection_failed: Verbindung zur Datenbank fehlgeschlagen.

View file

@ -1,2 +0,0 @@
piwik_url = http://stats.ja-s.de/piwikProxy.php
piwik_site_id = 2