Commit Graph

368 Commits

Author SHA1 Message Date
Zach Brown
ecefa79676
Add usage message to ReloadCommand
Used when the wrong arguments are supplied, missed when we added the
permissions reload functionality.
2016-10-30 00:14:17 -05:00
Zach Brown
0860727dae
Update upstream S 2016-10-26 16:05:22 -05:00
Zach Brown
92567cc43a
Update upstream B/CB 2016-10-21 15:28:44 -05:00
AlphaBlend
96b534f1f1
Add hit entity to ProjectileHitEvent 2016-10-05 16:07:58 -05:00
Zach Brown
18799efd0d
Update upstream B/CB/S 2016-10-01 11:47:56 -05:00
kashike
3d5f59c855 Fix @aikar's oops with verbose timings 2016-09-23 23:19:15 +00:00
Zach Brown
f7cfe1f769
Add javax.annotations to the API
Used this set specifically because they are present in NMS already.
2016-09-16 14:38:52 -05:00
Zach Brown
2e880e7676
Make UseItem rate limiting stricter, configurable 2016-09-10 23:27:07 -05:00
Zach Brown
f5d7e2067d
Update upstream B/CB/S 2016-09-05 14:21:03 -05:00
kashike
8f91416dcb @Zbob750 missed a few name changes 2016-09-04 06:35:42 +00:00
Zach Brown
f9f96ea3a5
Update upstream B/CB/S 2016-09-02 22:44:52 -05:00
Zach Brown
b170e8cedb
Update upstream B/CB/S
Remove two features added upstream
2016-08-27 18:41:58 -05:00
Aikar
323c18dd65 Timings v2: confirm before reset. Add delays before report generation
Require user to confirm the timings reset, warning them that they should not be doing this.
Also require Timings to have ran for 3 minutes before allowing the report command.
Also require 1 minute intervals between reports to stop report spam.
2016-08-19 23:42:38 -04:00
Zach Brown
17c9d7d9da
Kick git and rebuild patches 2016-08-15 19:22:10 -05:00
Zach Brown
15f3ca7ecb
Update upstream B/CB 2016-08-07 00:01:31 -05:00
Zach Brown
01a09f8ff1
Update maven repo urls 2016-08-06 16:49:55 -05:00
Zach Brown
8f6208b1d3
Send a fake team as needed for the collision rule 2016-07-30 17:04:39 -05:00
Zach Brown
46bfd418a8
Update upstream B/CB/S 2016-07-30 18:02:34 -05:00
Zach Brown
f9f1a2e97e
Cleanup obfuscation helper comment format 2016-07-28 19:09:54 -05:00
Aikar
106787f894 Timings v2 cleanups - potential overflow fix and fix bad hostnames
if hostname is invalid on system, just use a static string

also cleans up visibility of a lot of code, hopefully will help jvm optimize more.
2016-06-30 01:32:00 -04:00
Zach Brown
83472d4c99
Update upstream B/CB/S 2016-06-26 14:13:34 -05:00
Zach Brown
45d9b4c497
Update to MC 1.10.2 2016-06-25 12:21:26 -05:00
Aikar
0152e0f616 Update Entity AddTo|RemoveFrom World events to be EntityEvents 2016-06-24 00:17:23 -04:00
DemonWav
8862652351
Add repo to handle the bungee-cord chat dependency 2016-06-23 00:34:56 -05:00
Zach Brown
14ffaf5d2c
Update upstream B/CB 2016-06-11 22:22:27 -05:00
Zach Brown
c442e96eb9
Update to Minecraft 1.10 2016-06-08 23:42:46 -05:00
Zach Brown
dbbf2eb27b
Fix a few global configuration options being unavailable 2016-06-04 17:26:11 -05:00
Aikar
f4a43ec92d Update Upstream 2016-06-04 11:41:04 -04:00
Aikar
433489ea32 Timings v2: Start methods return self for use in try-with-resources
try (Timing ignored = timing) {
  // Code to time
}
// auto stops timing, even if you return in 42 other places in the block
2016-05-15 17:34:26 -04:00
Zach Brown
2304826f19
Move bad command registration workaround into SMP#dispatch
Fixes GH-274
2016-05-13 00:13:42 -05:00
Aikar
b59e2a51de Paper 1.9.4 Update 2016-05-12 01:01:13 -04:00
Aikar
211cba970b LootTable API & Replenishable Lootables Feature
Provides an API to control the loot table for an object.
Also provides a feature that any Lootable Inventory (Chests in Structures)
can automatically replenish after a given time.

This feature is good for long term worlds so that newer players
do not suffer with "Every chest has been looted"

API and Event added to control the Auto Replenish feature for players.
2016-05-04 19:46:28 -04:00
Aikar
776e0784af Try to determine plugin name on bad plugin command registration 2016-04-30 12:53:20 -04:00
Zach Brown
5f98ec08a5
Timings v2: Plugins don't always register commands properly
*mumbles*
2016-04-30 00:09:29 -05:00
willies952002
02494f5be7
Reimplement PlayerEditBookEvent 2016-04-26 23:04:20 -04:00
kashike
0cfd3c0dc6 Merge pull request #230 from kashike/feature/arrow-pickup
Arrow pickup rule API
2016-04-25 13:27:51 -07:00
Aikar
9381554475 update upstream 2016-04-23 22:41:46 -04:00
Zach Brown
3591fb7ed9
Update upstream Spigot and rebuild 2016-04-22 22:21:10 -05:00
Zach Brown
4f7b7bb31a
Fix EntityDismountEvent and VehicleExitEvent cancellation
Perhaps "workaround" would be the better term
2016-04-22 15:45:22 -05:00
kashike
7ac2b8139e Arrow pickup rule API 2016-04-22 00:07:58 -07:00
Zach Brown
a6536804fd
EntityHealthRegain isFastRegen API 2016-04-22 01:48:49 -05:00
Zach Brown
1bce5c2438
Here have a rebuild while we're at it 2016-04-18 09:43:19 -05:00
Zach Brown
68cdc4fa90
Remove non-zero BlockIterator block and Loading chunks earlier in player TP patches
Allowing only non-zero BlockIterators breaks an API contract explicitly allowing them
(*eyeroll*)

And loading chunks earlier in the TP patch did not resolve the original issue, and now
that it is resolved, shouldn't actually provide any tangible benefits
2016-04-18 09:41:11 -05:00
Spottedleaf
6876b1d7a6 Also fix javadocs in the Server interface 2016-04-17 13:35:49 -05:00
Spottedleaf
dc9ab4dafc Fix silly Javadocs in Bukkit.broadcast 2016-04-16 09:23:37 -07:00
Zach
2924ae631e Merge pull request #205 from kashike/feature/handshake
Add handshake event
2016-04-13 23:10:34 -05:00
kashike
66d3688b39
Add handshake event to allow plugins to handle client handshaking logic themselves 2016-04-13 21:12:57 -07:00
Zach Brown
d07eac31bc
Update bungeecord chat API graduations 2016-04-13 22:21:42 -05:00
Zach Brown
a406f34921
Only allow non-zero value maxDistances for BlockIterators
Prevents them from iterating infinitely and hanging the server
2016-04-12 23:10:04 -05:00
Zach Brown
ef3f6a481a
Update upstreams 2016-04-11 10:30:12 -05:00
Zach Brown
6dae26cf14 Use 'Paper' for our config file in timings 2016-04-05 23:27:53 -05:00
Aikar
98ea811d9b Update Timings to use Region based chunk reporting
This will drastically reduce file size on large servers and help
avoid the parser failing to load the report.

This will also reduce memory usage of timings data.
2016-04-05 01:20:25 -04:00
kashike
871920f2f5 Add PlayerUseUnknownEntityEvent 2016-04-02 18:10:41 -07:00
Aikar
c92ce02363 Move fastutil from a patch file to a library, and improve EAR 2016-04-01 00:18:18 -04:00
Aikar
38df6e505c Paper 1.9.2 Update 2016-03-30 20:50:23 -04:00
Aikar
f051ea2ab3 Use FastUtil Long/Int HashMap's
For DataWatcher, swap out plain Integer key HashMap for a Int2ObjectOpenHashMap
For ChunkProviderServer, swap out CB's custom LongHashMap with Long2ObjectOpenHashMap

These collections are super fast as seen
http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/
2016-03-30 09:43:11 -05:00
DemonWav
4bf9c3c177 Add getEntity by UUID API 2016-03-30 01:20:36 -05:00
Aikar
31a482e9f0 Move Timings v2 TimingHandler to FastUtil Int map 2016-03-30 01:59:47 -04:00
Aikar
c2f872aed3 Add Minimal FastUtil int/long collections.
Importing the full library would double the jar size... its way too large.
So lets just import the basic int/long based collections to then use
to improve performance on these kind of collections.
2016-03-30 01:57:56 -04:00
Aikar
48dff29f31 Remove, not invalidate, Metadata on reload
Objects loaded over different class loaders are not the same. Nasty dragons lie here.

Also clean up the previous patch to no longer butcher imports.
2016-03-28 22:43:05 -04:00
Aikar
3d61632b53 Remove last patch, doesn't exactly do what I thought it was doing 2016-03-28 22:28:52 -04:00
Aikar
e77e65499f Remove Invalidated Metadata
Bukkit was using an unimplemented method to invalidate plugin meta.
2016-03-28 22:15:23 -04:00
crast
6a54004bb4 Reduce thread synchronization in MetadataStoreBase
Use ConcurrentHashMap to allow thread-safe access methods and very
limited synchronized portions to allow much higher concurrency in
MetadataStore as well as far less locking, especially on reads
2016-03-28 22:10:01 -04:00
Aikar
e90cdc3639 Remove some code from Timings v2 that was only for EMC. 2016-03-28 21:41:17 -04:00
Aikar
b99e8381ab EntityPathfindEvent
Fires when an Entity decides to start moving to a location.

This is not the same as a move event. This only fires when an entity chooses
to start moving to a location, and allows cancelling that pathfind.

Additionally, only get is supported for now. Unsure if changing target location
is safe to do.
2016-03-28 21:24:45 -04:00
Aikar
22b248d631 Entity AddTo/RemoveFrom World Events
These events will give plugins a reliable way to track every entity that is added
or removed from a world, so that one may always ensure they are in a desired state.
2016-03-28 20:33:10 -04:00
Zach Brown
b210aa7dfe Update upstream B/CB/Spigot and rebuild 2016-03-27 20:48:50 -05:00
Zach
5108183346 Merge pull request #153 from kashike/feature/slot
Access items by EquipmentSlot
2016-03-27 02:24:12 -05:00
Zach Brown
85ee80938b Update upstream and rebuild 2016-03-27 01:40:17 -05:00
kashike
eeb64630cd Access items by EquipmentSlot 2016-03-26 22:23:42 -07:00
Byteflux
ced183982a Add Entity Origin API
This replaces the TNT and Falling Block Source Location API with a more
general purpose API that works with all entities.
2016-03-25 02:24:27 -07:00
Byteflux
1d88720b2c Relocate Timings v2 patch 2016-03-24 22:04:44 -07:00
Aikar
e091466f34 Allow command line arg to allow normal reload 2016-03-21 21:56:52 -04:00
Aikar
646b62a220 Make /reload require typing confirm to actually reload 2016-03-21 21:40:29 -04:00
willies952002
62580304f4 Add Bukkit#reloadPermissions()
Fix issues with Paper build #544
2016-03-21 21:29:41 -04:00
Aikar
def021fb9b fix rebuild patches and rebuild current patches 2016-03-21 20:46:54 -04:00
Daniel Ennis
8616dc012c Merge pull request #91 from willies952002/feature/permReload
Allow Reloading of Custom Permissions - resolves #49
2016-03-21 20:24:27 -04:00
William
869ab5202e Allow Reloading of Custom Permissions
Add the ability to reload the custom permissions file by doing "/reload permissions"

Implements Feature Request: https://github.com/PaperMC/Paper/issues/49
2016-03-21 19:28:52 -04:00
kashike
3b15da52db Custom replacement for eaten items 2016-03-19 17:31:06 -05:00
Aikar
82db846be6 set default goals on all pom poms </cheer> 2016-03-18 02:13:51 -04:00
Aikar
1bd454082e Add sender name to commands.yml replacement
This allows you to use $sender in commands.yml definitions to make
commands that auto target self.
2016-03-18 00:29:35 -04:00
Aikar
b4d1aa418a Add event call helper
This simplifies new event calling by reducing the diff to actually fire the event and check for cancelled state.
2016-03-18 00:29:11 -04:00
Zach Brown
80b1308735 Update and rebuild patches 2016-03-12 13:52:49 -06:00
Techcable
752452373d Handle static methods 2016-03-12 09:43:39 -07:00
Zach Brown
244196f8cb Rebuild some patches 2016-03-12 00:40:16 -06:00
Techcable
386693ee50 Use ASM for event execution
Reflection (although highly optimized), has noticable overhead.
It also creates noticable GC overhead by allocating arrays with arguments, as @Aikar has said.

Based on WaterfallMC/Waterfall@1692934370

Merge pull request #45 from Techcable/feature/asm-executors
2016-03-12 00:26:02 -06:00
Techcable
b4bf59de2e Improve Paper's version checking system
Will now check commit hashes from this repo as a fallback when it is unable to find a build from our CI server. Because not everyone uses it directly
2016-03-11 22:30:43 -06:00
Zach Brown
e208ee6102 Update patch numbers for PR merges 2016-03-09 19:48:14 -06:00
Zach Brown
b4e8b79728 Merge pull request #73 from kashike/feature/you-are-very-resourceful-you-know-yes-you-are-very-resourceful-yes 2016-03-09 19:45:55 -06:00
kashike
9216a46316 Add more complete resource pack API 2016-03-08 22:24:16 -08:00
kashike
a8ecaee65f Add methods for working with arrows stuck in living entities 2016-03-08 21:11:46 -08:00
kashike
9a9033c6c1 Add BaseComponent sendMessage methods to CommandSender 2016-03-08 13:16:54 -08:00
Zach Brown
a54fb8d270 Silence BeaconEffectEvent, swallow exception in version checking 2016-03-03 04:48:46 -06:00
Zach Brown
6287e97b6b Update for upstream changes 2016-03-03 04:07:25 -06:00
Zach Brown
99fec76702 Paper 1.9 2016-03-03 03:46:49 -06:00
Joseph Hirschfeld
010c651473 Add exception reporting events 2016-03-03 03:46:48 -06:00
Aikar
4c5668268b Fix ServerListPingEvent flagging as Async 2016-03-03 03:46:48 -06:00
Aikar
0ba78fc192 Make Timings use less passes in its benchmark 2016-03-03 03:46:48 -06:00
Techcable
dcad4c6ea7 Improve title API
Uses title objects instead of individual update methods
2016-03-03 03:46:48 -06:00
Zach Brown
2a67f0182f Proper maven repo details 2016-02-21 04:12:03 -06:00
Jedediah Smith
ee63dbebdc Player Tab List and Title APIs 2016-02-16 20:01:30 -06:00
Zach Brown
52398f034c Move bungeecord chat APIs out of spigot subclasses 2016-02-16 19:55:05 -06:00
Zach Brown
2eb853b0af There wasn't anything here
http://i.imgur.com/AxtzziK.gif
2016-02-15 20:10:47 -06:00
DemonWav
9c166f741d Fix tab completeion ignoring the old non-location tab complete
Closes GH-28
2016-02-15 19:52:53 -06:00
Zach
7bea05be51 Merge pull request #27 from kashike/feature/commandmap
Expose server CommandMap
2016-02-15 12:07:29 -06:00
kashike
edc2cd686e Expose server CommandMap 2016-02-15 07:13:16 -08:00
Zach Brown
577418ea75 Ignore version formatting errors
We have so many random strings around at the moment this will be better for now
2016-02-15 08:31:45 -06:00
Zach Brown
2cf460f29e Update version handling for our new build system
CC GH-19
2016-02-15 06:02:47 -06:00
Aikar
afde4c2f8b Automatically disable plugins that fail to load 2016-02-13 19:41:55 -06:00
Nik Gil
b9d98ad6e8 Make EntityDismountEvent Cancellable 2016-02-01 23:57:27 -07:00
Zach Brown
43876bb104 Squash these tab complete patches 2016-01-31 17:00:30 -06:00
DemonWav
00f91edaec Fix infinite recursion with plugin tab completers
Make block location tab completion be a per-world configurable value
2016-01-31 01:21:47 -06:00
DemonWav
7a0c30a707 Add Location support to tab-completes
This is a feature in vanilla Minecraft that has somehow been missing from CraftBukkit for years
2016-01-30 19:20:18 -06:00
Zach Brown
972d71a30b Squash Java 8 patches into pom changes patches 2016-01-29 02:51:53 -06:00
Zach Brown
861d6c6247 Java 8 javadoc lint bypass. Until we can fix this properly (massive patch for old bukkit ???!?!?!?!) this will have to do 2016-01-21 17:39:56 -06:00
Literallie
5faccece77 Fix JavaDoc errors introduced in Timings v1 2016-01-21 17:32:34 -06:00
Zach Brown
85dd26898d Migrate timings classes to new package 2016-01-10 01:33:27 -06:00
Zach Brown
9af2ba76ad Just a bit more information for those skript classes 2016-01-10 01:08:22 -06:00
Zach Brown
414a748893 Skript event executor classes do not have an enclosing method 2016-01-09 18:43:35 -06:00
Zach Brown
9172103531 Migrate PaperSpigot to Timings version 2 2016-01-09 00:32:38 -06:00
Zach Brown
e9c23b0c38 Require Java 8 - Tell your shitty hosts to update 2016-01-09 00:13:58 -06:00
Steve Anton
5063a0613d Add PlayerInitialSpawnEvent 2015-12-22 22:06:43 -06:00
Zach Brown
ea565eff61 Rebuild patches 2015-09-18 20:44:37 -05:00
Zach Brown
f243a4024d Remove several broken or unnecessary patches.
Removes PlayerMicroMoveEvent API, the ability to disable the AsyncCatcher, and the TeleportPassengerVehicleWithPlayer patch
2015-09-12 19:57:39 -05:00
Zach Brown
0febdc8b44 Rebuild patches 2015-08-02 01:56:08 -05:00
Zach Brown
881dfe09c2 Update PaperSpigot to 1.8.8 2015-07-27 17:26:21 -05:00
Byteflux
83aa27a29d Add javadocs to BeaconEffectEvent 2015-07-23 21:41:35 -07:00
Byteflux
7d9632e328 Add BeaconEffectEvent 2015-07-23 12:57:12 -07:00
Byteflux
16ab69f11b Fix package naming of PaperSpigot events to be consistent with Bukkit/Spigot
Right now this only affects the recently added PlayerMicroMoveEvent. I
figured this should be done to keep the events organized in the same way
Bukkit and Spigot do. This should lead to a less cluttered event package
when we do add more events.
2015-07-23 09:56:24 -07:00
Techcable
23f4ae7bbd Add PlayerMicroMoveEvent 2015-07-23 04:30:13 -07:00
Byteflux
8de3946478 Nerfed spawner mobs should use PathfinderGoalFloat to swim if available 2015-07-14 10:51:38 -07:00
Byteflux
c17e209dc1 Rebuild patches 2015-07-14 08:59:57 -07:00
Byteflux
7f032d52e6 Add player view distance API 2015-07-01 01:01:42 -07:00
Zach Brown
5d7c5da500 Rebuild patches 2015-06-20 22:05:36 -05:00
Zach Brown
6b6eb8f7f7 Rebuild patches for upstream API addition
Removes ArmorStand Marker API as that was added to Bukkit
2015-06-10 22:35:26 -05:00
Byteflux
f6bd873c1d Update to 1.8.7 2015-06-05 05:45:30 -07:00
Zach Brown
a193a0a898 Rebuild patch 2015-05-28 20:38:53 -05:00
Zach Brown
efaef117d3 Rebuild patches for upstream changes 2015-05-28 00:11:18 -05:00
Zach Brown
dfdbaa3bd8 Update to 1.8.6 2015-05-25 15:59:30 -05:00
Zach Brown
d69690af14 Update PaperSpigot to 1.8.5 2015-05-23 12:09:55 -05:00
Zach Brown
4c8a717466 Update PaperSpigot to 1.8.4 2015-05-18 18:41:57 -05:00
Zach Brown
9012499383 Add ArmorStand Marker NBT API 2015-05-03 17:47:28 -05:00
Isaac Moore
4651b50153 Add PlayerLocaleChangeEvent 2015-04-27 21:44:11 -05:00
Byteflux
8bd77dff5a Add FallingBlock source location API 2015-04-18 14:46:35 -05:00
Zach Brown
78fa2af57a Update PaperSpigot to Minecraft 1.8.3 2015-03-08 05:17:04 -05:00
Zach Brown
b7ea61e56b Fix parent warning in PaperSpigot-API... and rebuild other patches 2015-01-11 01:10:11 -06:00
Zach Brown
6c95b61fd5 Rebuild patches for upstream changes 2015-01-06 22:13:40 -06:00
Zach Brown
9ba61a6dd0 Update version checking patch 2014-12-28 16:37:21 -06:00
Zach Brown
e74ba3a4ec Check PaperSpigot versions with the /ver command 2014-12-27 17:21:50 -06:00
Zach Brown
ed8119ad4d Rebuild our patches for upstream changes 2014-12-18 17:35:10 -06:00
Zach Brown
11b53f20cf Rebuild our patches for upstream changes 2014-12-14 16:25:11 -06:00
Zach Brown
8326a255d5 Update our patches for upstream changes 2014-12-09 20:08:12 -06:00
Zach Brown
9d7fbd476f Update our patches for the latest changes
/ver is no longer useless! Meaninful version tracking yay!
2014-12-02 00:45:25 -06:00
Aikar
2a326d9446 Add TNT source location API 2014-11-30 22:58:51 -06:00
Zach Brown
99e3002266 Regen our patches 2014-11-30 16:21:39 -06:00
Zach Brown
de86706b70 Update PaperSpigot to Minecraft 1.8 2014-11-28 15:01:21 -06:00
Aikar
b697c4d506 Add Async Chunk Load API 2014-11-28 14:19:09 -06:00
Aikar
25c5c2cb16 Implement performance improvements from the EMC-CraftBukkit fork
See the individual patch files for more details
2014-11-28 14:19:09 -06:00
Zach Brown
4555490e4b Remove 1.8 blocks/items patches
For those interested in these features, you can continue to use these patches in your own builds or use a plugin, such as Carbon, to add them
2014-11-28 14:19:09 -06:00
Zach Brown
39fef35e10 Rebuild an API patch we missed 2014-11-28 14:19:09 -06:00
Zach Brown
e60db6a306 Add a few 1.8 features/blocks/items/whatever 2014-11-28 14:19:08 -06:00
Zach Brown
15b553bed3 Update from upstream SpigotMC
Fix double plants having the incorrect top half SpigotMC/Spigot@377b69d787
Fix boats thinking that they were always on land for 1.8 clients SpigotMC/Spigot@4a083f819e
Correct the action used in updateGamemode. this isn't used by the ser... SpigotMC/Spigot@face904a9a
Allow the updated version of protocollib to be enabled SpigotMC/Spigot@4614a615cc
2014-11-28 14:19:07 -06:00
Minecrell
85eb25863a Fix ProtocolLib compatibility 2014-11-28 14:19:07 -06:00
Zach Brown
c777f40058 Update from upstream SpigotMC
Add unbreakable API to item meta SpigotMC/Spigot@b1af008222
Configure how often EntityHangings calculate if they should die. SpigotMC/Spigot@ac6e1fc32d
Copy ItemStacks in DataWatcher to prevent ConcurrentModificationExcep… SpigotMC/Spigot@2af28ffbd1
Add the spigot.yml into the timings paste SpigotMC/Spigot@d61f38bd58

Note: This commit moves the entity-hanging tick into Spigot's spigot.yml and out of our paper.yml
2014-08-25 16:33:18 -05:00
drXor
d95ac585d4 Configurable hanging tick
EntityHangings make a somewhat extensive calculation ever 100 ticks to check if they should die (obstruction etc). This patch makes this magic number configurable, allowing server owners to pick how often they want EntityHangings (e.g. ItemFrames) to tick. Higher values may provide a performance boost for Hanging-heavy servers.
2014-08-09 17:28:09 -05:00
Jedediah Smith
9fdc6b05f9 Add player affects spawning API
Test plugin here: https://github.com/Zbob750/AffectsSpawning
I believe this originated with SportBukkit, slightly modified for our (and potentially upstream's) usage
2014-08-08 23:27:47 -05:00
Zach Brown
dc3ae42b52 Stop using spigotmc.org as a redirect for timings 2014-07-28 03:29:08 -05:00
Zach Brown
7b0c576798 Restructure PaperSpigot as a new set of modules
Allows us much greater control over the Spigot portion of the code
and makes us more "proper"
Credit to @Dmck2b for originally passing the idea along a while back
2014-07-21 15:46:54 -05:00