(+) Extend/alter slightly, e.g. added a regex example.
Replacement characters are not needed, and default values won't keep
reappearing.
Tests pending, e.g. dump with the upcoming registry log.
Benefits:
* Improves performance, where permission lookup has major impact, with
timeout based lookup, static permissions (skip permission check
entirely), and world/offline based invalidation. (Once fully
implemented.)
* Hopefully more efficient: use Bukkit Permission for faster defaults.
* (Allows control over how which permission is to be
updated/invalidated, which is useful per se.)
Risks:
* Complex changes yield bugs.
* Other plugins depending on NCP might break.
* Cache incoherence might happen (permissions are changed dynamically +-
unintended malconfiguration, or in case of bugs).
* (Endless loops certainly have all been fixed.)
Breaking:
* Lots of more or less internal API has been changed or removed: Check,
CheckType, CheckUtils, TickTask, ...
* Permission checking behavior has been altered.
Rough points:
* Implement a permission cache within PlayerData.
* Remove the player tasks and permission updates in favour of handling
those within DataManager and PlayerData.
* Adjust everything else to it (partly TBD).
* Updating sets of permissions (e.g. for CHAT) is done more lazily now,
i.e. one per 10 ticks). An actual permission check would still yield an
update next tick (asynchronous).
* Fixed/extended random spots (DualCollection, MiniListener registration
support, StringUtil).
Missing:
* Basic implementation
* Cleanup after logout (stages: 1. non-essential like permissions,
2. unrecoverable like set-back location, 3. complete data removal).
* Coverage
* Might have missed spots.
* NoCheatPlus.nameSetPerms should be replaced by caching + default
config for world-wise updating.
* Command permissions are always checked. At least for players,
cache based lookup should get implemented.
* More unit tests.
* Extended configurability: Per-world settings/policies.
* Efficiency
* Not all parts of the implementation are 100%/optimal yet.
The old ListenerManager is removed, new system in place. Removed
doesManageListeners(). (The new system isn't that new, but it's been
fixed and adapted to using RegistrationOrder.)
New
* Register all Bukkit events via the new EventRegistryBukkit.
* This way listeners can be ordered by numeric priority and tags
(regular expressions for beforeTag and afterTag).
* Unregistering listeners is possible (a listener node stays in the
Bukkit registry, but only one per event).
* It's possible to add listeners with minimal impact (MiniListener).
* The registry registers by event class 'hard' i.e., no relations
between already registered classes are checked.
* Order isn't necessarily stable nor even reproducible for randomized
start conditions with the same elements.
Point
* Compatibility hooks can easily place event listeners
before/after/between NCP default listeners, without resorting to tricks
like 'load-before'.
* Future registry of NCP itself: unregistering listeners is necessary
for runtime-removable checks, order is useful if not necessary, to be
able to add check listeners at any point of time.
Breaks:
* Anything relying on the previous (optional) managelisteners feature.
Missing:
* Lots of testing/inspection.
* Ensure all NCP listeners are coming with name/tag at least.
* Provide meaningful tags/RegistrationOrder for fine grained access
(e.g. after feature.moving but before feature.inventory).
* Change cncp to hard depend on NCP and use listener priorities.
This way testing changes to the core checks will be easier:
* By default NCPCompatNonFree is fetched from the repository (prevent
via -Dno_nonfree).
* To build "non free" modules, -P nonfree_build is needed. In addition
you need to specify the profiles for what to build, such as -P all an
the like.
* Reduce details and only send a configurable amount of lines in
notify/chat, default to 5, just state to check logs in the end,
instead of lengthy hints.
* Log detailed output to STATUS (file/s).
* Fix wrong build number printed to set configversion.created to.
The per-config-path notifications would keep showing up, even if you
removed the paths, then run 'ncp reload', then alter any of them and run
'ncp reload'.
To fix this, the configversion.created value is set to the current
build, if no config warnings are there - which is the same, as what the
notification suggests as an alternative to removing the paths and
running 'ncp reload'.
To do this, isConfigUpToDate had to be moved from Updates to
ConfigManager, which makes more sense anyway. In addition the 'created'
and saved 'values' are set to the biggest thing found, instead of the
prehistoric static value.
Further a negative 'created' value will not be overridden anymore,
allowing to silence the config notifications forever. Not necessarily
recommended for the general case, but it can be useful/necessary with
maintained blueprints, e.g. with administering multiple servers.
One of the next steps will be to remove the DefaultConfig.buildNumber in
favor of setting a build number for each and every path added. All
provided we don't run into nasty issues here.
Another follow up could be to create an extra registry/config log file
and write all the values there, and only print the first 5 in ingame
chat.
Instead of maps for each individual purpose, and the rather expensive
TickListener adding and removing, player specific task will be done via
one PlayerTickListener that can be registered with the TickTask. Thus
PlayerData has the access methods requestUpdateInventory and
requestPlayerSetBack, and so on, later more. For the
DataManager.playerData map it'll be UUID first now.
Consequently some calls have been altered to prefer passing Player or
UUID for PlayerData getting.
Breaks: DataManager.getPlayerData(String, boolean) has been removed, new
methods added to do the same without boolean or with UUID passed extra.
Following changes may repeatedly/randomly break PlayerData and check
data access (unless you use CheckType.getDataFactory), this may not
follow directly, but more or less soon. Even Later, CheckType will get
broken too :), in favor of class instances with dynamic registration
ability.
Basic direction is to concentrate stuff in PlayerData, getting rid of
all the static data stores, but also making access to shared data
more efficient (e.g. store last world id + name and permission cache in
PlayerData). Access will be more thread safe (only for PlayerData,
permissions cache, likely for fetching check data too, however returned
objects may have their own contracts).
Tested with a pig. It's not nice.
* Vehicle envelope needs a lot of overhaul.
* Force fall set backs may be more nice to have for in-air downwards.
* The set back locations can be from seconds ago, with different
passengers than at the time of the set-back.
* Auto generate the sub-module file structure.
* Add rest manually.
Rest
* Enter new classes into factories.
* Add entries for modules and dependencies to the root pon and the
NCPPlugin pom, to make the new module represent 1.10 R1.
* Point the 1.10_r1 build profiles to the new module.
* Add a new module for 1.11, point to cbdev (which still is 1.10.2,
though).
Next steps (next MC release, probably):
* At least auto generate a file, containing all entries to make for the
new module, for convenient use with copy and paste.
* (Later: alter the files automatically, possibly interactive. Needs
more care, e.g. if profile entries already exist. The factory entries
can have a marker each.)
Not sure if this really pays, if most people use protocol-support
plugins that limit packets anyway. There could be some future use, e.g.
generic rate limiting with configurable implementation.
Other:
* New methods for RawConfigFile+ConfigManager to check for
AlmostBooleanS.
* Add all net check permissions to plugin.yml.
Using a LinkedHashMapCOW for now, fetching instances should be
thread-safe. This isn't such a big issue, but there might be handles in
asynchronously processed threads later on, and the handle will
initialize lazily. Copy on write won't be nice during registry setup, if
we have hundreds of objects registered at some point in the future,
neither would locking be too nice to have - but locking could be
acceptable with using handles, as those get updated by overriding the
instance field. Using locking would affect static utilities, but this
could be mended. An alternative could be to have some registration stage
'setup', during which fetching will yield the old state, while new
registrations will be added to a new map. Upon changing the registration
stage to 'live', the map reference is switched simply, this could be
acceptable even with a completely new setup after reloading the
configuration.
* Only unregister once really.
* Don't count to below 0.
* Throw a RuntimeException in getNewHandle, if already disabled.
(+ Allow checking if disabled for sub classes.