Repository: DenizenScript/Denizen Branch: dev Commit: ed356260423a Files: 1151 Total size: 7.6 MB Directory structure: gitextract_bj40aszd/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ └── ISSUE_TEMPLATE/ │ ├── bug-report.md │ ├── feature-request.md │ └── i-m-having-trouble.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── dist/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── dist/ │ └── Dist.java ├── paper/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── paper/ │ ├── PaperEventHelpers.java │ ├── PaperModule.java │ ├── datacomponents/ │ │ ├── ComponentAdaptersRegistry.java │ │ ├── DataComponentAdapter.java │ │ ├── FoodAdapter.java │ │ ├── GliderAdapter.java │ │ ├── ItemModelAdapter.java │ │ ├── MaxDurabilityAdapter.java │ │ ├── MaxStackSizeAdapter.java │ │ └── RarityAdapter.java │ ├── events/ │ │ ├── AnvilBlockDamagedScriptEvent.java │ │ ├── AreaEnterExitScriptEventPaperImpl.java │ │ ├── BellRingScriptEvent.java │ │ ├── BlockPreDispenseScriptEvent.java │ │ ├── CreeperIgnitesScriptEvent.java │ │ ├── DragonEggFormScriptEvent.java │ │ ├── EntityAddToWorldScriptEvent.java │ │ ├── EntityKnocksbackEntityScriptEvent.java │ │ ├── EntityLoadCrossbowScriptEvent.java │ │ ├── EntityPathfindScriptEvent.java │ │ ├── EntityRemoveFromWorldScriptEvent.java │ │ ├── EntityStepsOnScriptEvent.java │ │ ├── EntityTeleportedByPortalScriptEvent.java │ │ ├── ExperienceOrbMergeScriptEvent.java │ │ ├── PlayerAbsorbsExperienceScriptEvent.java │ │ ├── PlayerBeaconEffectScriptEvent.java │ │ ├── PlayerChangesFramedItemScriptEvent.java │ │ ├── PlayerChoosesArrowScriptEvent.java │ │ ├── PlayerChunkUnloadScriptEvent.java │ │ ├── PlayerClicksFakeEntityScriptEvent.java │ │ ├── PlayerClicksInRecipeBookScriptEvent.java │ │ ├── PlayerClientOptionsChangeScriptEvent.java │ │ ├── PlayerCompletesAdvancementScriptEventPaperImpl.java │ │ ├── PlayerDeepSleepScriptEvent.java │ │ ├── PlayerElytraBoostScriptEvent.java │ │ ├── PlayerEquipsArmorScriptEvent.java │ │ ├── PlayerGrantedAdvancementCriterionScriptEvent.java │ │ ├── PlayerInventorySlotChangeScriptEvent.java │ │ ├── PlayerItemTakesDamageScriptEventPaperImpl.java │ │ ├── PlayerJumpsScriptEventPaperImpl.java │ │ ├── PlayerLecternPageChangeScriptEvent.java │ │ ├── PlayerLoomPatternSelectScriptEvent.java │ │ ├── PlayerNamesEntityScriptEvent.java │ │ ├── PlayerOpenSignScriptEvent.java │ │ ├── PlayerPreparesGrindstoneCraftScriptEvent.java │ │ ├── PlayerQuitsScriptEventPaperImpl.java │ │ ├── PlayerRaiseLowerItemScriptEventPaperImpl.java │ │ ├── PlayerReceivesLinksScriptEvent.java │ │ ├── PlayerSelectsStonecutterRecipeScriptEvent.java │ │ ├── PlayerSetSpawnScriptEvent.java │ │ ├── PlayerShieldDisableScriptEvent.java │ │ ├── PlayerSpectatesEntityScriptEvent.java │ │ ├── PlayerStopsSpectatingScriptEvent.java │ │ ├── PlayerTracksEntityScriptEvent.java │ │ ├── PlayerTradesWithMerchantScriptEvent.java │ │ ├── PreEntitySpawnScriptEvent.java │ │ ├── PrePlayerAttackEntityScriptEvent.java │ │ ├── ProjectileCollideScriptEvent.java │ │ ├── ServerListPingScriptEventPaperImpl.java │ │ ├── ServerResourcesReloadedScriptEvent.java │ │ ├── SkeletonHorseTrapScriptEvent.java │ │ ├── TNTPrimesScriptEvent.java │ │ ├── TargetBlockHitScriptEvent.java │ │ ├── UnknownCommandScriptEvent.java │ │ ├── VaultChangesStateScriptEvent.java │ │ ├── WardenChangesAngerLevelScriptEvent.java │ │ └── WorldGameRuleChangeScriptEvent.java │ ├── properties/ │ │ ├── EntityArmsRaised.java │ │ ├── EntityAutoExpire.java │ │ ├── EntityBodyStingers.java │ │ ├── EntityCanTick.java │ │ ├── EntityCarryingEgg.java │ │ ├── EntityDrinkingPotion.java │ │ ├── EntityEggLayTime.java │ │ ├── EntityFriction.java │ │ ├── EntityLeftHanded.java │ │ ├── EntityReputation.java │ │ ├── EntityShouldBurn.java │ │ ├── EntitySneaking.java │ │ ├── EntityWitherInvulnerable.java │ │ ├── ItemArmorStand.java │ │ ├── ItemRemovedComponents.java │ │ ├── PaperElementExtensions.java │ │ ├── PaperEntityExtensions.java │ │ ├── PaperItemExtensions.java │ │ ├── PaperPlayerExtensions.java │ │ └── PaperWorldExtensions.java │ ├── tags/ │ │ └── PaperTagBase.java │ └── utilities/ │ ├── BlockTagsSetter.java │ └── PaperAPIToolsImpl.java ├── plugin/ │ ├── lib/ │ │ └── Vault.jar │ ├── pom.xml │ └── src/ │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── denizenscript/ │ │ └── denizen/ │ │ ├── Denizen.java │ │ ├── events/ │ │ │ ├── BukkitScriptEvent.java │ │ │ ├── ScriptEventRegistry.java │ │ │ ├── block/ │ │ │ │ ├── BellRingScriptEvent.java │ │ │ │ ├── BlockBuiltScriptEvent.java │ │ │ │ ├── BlockBurnsScriptEvent.java │ │ │ │ ├── BlockCooksSmeltsItemScriptEvent.java │ │ │ │ ├── BlockDestroyedByExplosionEvent.java │ │ │ │ ├── BlockDispensesScriptEvent.java │ │ │ │ ├── BlockEquipsItemScriptEvent.java │ │ │ │ ├── BlockExplodesScriptEvent.java │ │ │ │ ├── BlockFadesScriptEvent.java │ │ │ │ ├── BlockFallsScriptEvent.java │ │ │ │ ├── BlockFormsScriptEvent.java │ │ │ │ ├── BlockGrowsScriptEvent.java │ │ │ │ ├── BlockIgnitesScriptEvent.java │ │ │ │ ├── BlockPhysicsScriptEvent.java │ │ │ │ ├── BlockShearEntityScriptEvent.java │ │ │ │ ├── BlockSpreadsScriptEvent.java │ │ │ │ ├── BrewingStandFueledScriptEvent.java │ │ │ │ ├── BrewingStartsScriptEvent.java │ │ │ │ ├── BrewsScriptEvent.java │ │ │ │ ├── CauldronLevelChangeScriptEvent.java │ │ │ │ ├── CrafterCraftsScriptEvent.java │ │ │ │ ├── DragonEggMovesScriptEvent.java │ │ │ │ ├── FurnaceBurnsItemScriptEvent.java │ │ │ │ ├── FurnaceStartsSmeltingScriptEvent.java │ │ │ │ ├── LeafDecaysScriptEvent.java │ │ │ │ ├── LiquidLevelChangeScriptEvent.java │ │ │ │ ├── LiquidSpreadScriptEvent.java │ │ │ │ ├── LootDispensesFromBlockScriptEvent.java │ │ │ │ ├── MoistureChangeScriptEvent.java │ │ │ │ ├── NoteBlockPlaysNoteScriptEvent.java │ │ │ │ ├── PistonExtendsScriptEvent.java │ │ │ │ ├── PistonRetractsScriptEvent.java │ │ │ │ ├── RedstoneScriptEvent.java │ │ │ │ ├── SpongeAbsorbsScriptEvent.java │ │ │ │ ├── TNTPrimesScriptEvent.java │ │ │ │ └── VaultDisplaysItemScriptEvent.java │ │ │ ├── bukkit/ │ │ │ │ ├── ExhaustedNPCEvent.java │ │ │ │ ├── SavesReloadEvent.java │ │ │ │ └── ScriptReloadEvent.java │ │ │ ├── entity/ │ │ │ │ ├── AreaEffectCloudApplyScriptEvent.java │ │ │ │ ├── AreaEnterExitScriptEvent.java │ │ │ │ ├── CreeperPoweredScriptEvent.java │ │ │ │ ├── DragonPhaseChangeScriptEvent.java │ │ │ │ ├── EntityAirLevelChangeScriptEvent.java │ │ │ │ ├── EntityBreaksHangingScriptEvent.java │ │ │ │ ├── EntityBreedScriptEvent.java │ │ │ │ ├── EntityChangesBlockScriptEvent.java │ │ │ │ ├── EntityChangesPoseScriptEvent.java │ │ │ │ ├── EntityCombustsScriptEvent.java │ │ │ │ ├── EntityCreatePortalScriptEvent.java │ │ │ │ ├── EntityDamagedScriptEvent.java │ │ │ │ ├── EntityDeathScriptEvent.java │ │ │ │ ├── EntityDespawnScriptEvent.java │ │ │ │ ├── EntityDropsItemScriptEvent.java │ │ │ │ ├── EntityEntersPortalScriptEvent.java │ │ │ │ ├── EntityEntersVehicleScriptEvent.java │ │ │ │ ├── EntityExitsPortalScriptEvent.java │ │ │ │ ├── EntityExitsVehicleScriptEvent.java │ │ │ │ ├── EntityExplodesScriptEvent.java │ │ │ │ ├── EntityExplosionPrimesScriptEvent.java │ │ │ │ ├── EntityFoodLevelChangeScriptEvent.java │ │ │ │ ├── EntityFormsBlockScriptEvent.java │ │ │ │ ├── EntityGlideScriptEvent.java │ │ │ │ ├── EntityGoesIntoBlockScriptEvent.java │ │ │ │ ├── EntityHealsScriptEvent.java │ │ │ │ ├── EntityInteractScriptEvent.java │ │ │ │ ├── EntityKilledScriptEvent.java │ │ │ │ ├── EntityPicksUpItemScriptEvent.java │ │ │ │ ├── EntityPotionEffectScriptEvent.java │ │ │ │ ├── EntityResurrectScriptEvent.java │ │ │ │ ├── EntityShootsBowScriptEvent.java │ │ │ │ ├── EntitySpawnScriptEvent.java │ │ │ │ ├── EntitySpawnerSpawnScriptEvent.java │ │ │ │ ├── EntitySpellCastScriptEvent.java │ │ │ │ ├── EntitySwimScriptEvent.java │ │ │ │ ├── EntityTamesScriptEvent.java │ │ │ │ ├── EntityTargetsScriptEvent.java │ │ │ │ ├── EntityTeleportScriptEvent.java │ │ │ │ ├── EntityTransformScriptEvent.java │ │ │ │ ├── EntityUnleashedScriptEvent.java │ │ │ │ ├── ExperienceBottleBreaksScriptEvent.java │ │ │ │ ├── FireworkBurstsScriptEvent.java │ │ │ │ ├── HangingBreaksScriptEvent.java │ │ │ │ ├── HorseJumpsScriptEvent.java │ │ │ │ ├── PigZappedScriptEvent.java │ │ │ │ ├── PiglinBarterScriptEvent.java │ │ │ │ ├── ProjectileHitScriptEvent.java │ │ │ │ ├── ProjectileLaunchedScriptEvent.java │ │ │ │ ├── SheepDyedScriptEvent.java │ │ │ │ ├── SheepRegrowsScriptEvent.java │ │ │ │ ├── SlimeSplitsScriptEvent.java │ │ │ │ ├── VillagerAcquiresTradeScriptEvent.java │ │ │ │ ├── VillagerChangesProfessionScriptEvent.java │ │ │ │ └── VillagerReplenishesTradeScriptEvent.java │ │ │ ├── item/ │ │ │ │ ├── InventoryPicksUpItemScriptEvent.java │ │ │ │ ├── ItemDespawnsScriptEvent.java │ │ │ │ ├── ItemEnchantedScriptEvent.java │ │ │ │ ├── ItemMergesScriptEvent.java │ │ │ │ ├── ItemMoveScriptEvent.java │ │ │ │ ├── ItemRecipeFormedScriptEvent.java │ │ │ │ └── ItemSpawnsScriptEvent.java │ │ │ ├── npc/ │ │ │ │ ├── NPCNavigationScriptEvent.java │ │ │ │ ├── NPCOpensScriptEvent.java │ │ │ │ ├── NPCSpawnScriptEvent.java │ │ │ │ └── NPCStuckScriptEvent.java │ │ │ ├── player/ │ │ │ │ ├── BiomeEnterExitScriptEvent.java │ │ │ │ ├── BlockDropsItemScriptEvent.java │ │ │ │ ├── ChatScriptEvent.java │ │ │ │ ├── HotbarScrollScriptEvent.java │ │ │ │ ├── PlayerAnimatesScriptEvent.java │ │ │ │ ├── PlayerArmorStandManipulateScriptEvent.java │ │ │ │ ├── PlayerBreaksBlockScriptEvent.java │ │ │ │ ├── PlayerBreaksItemScriptEvent.java │ │ │ │ ├── PlayerChangesGamemodeScriptEvent.java │ │ │ │ ├── PlayerChangesMainHandScriptEvent.java │ │ │ │ ├── PlayerChangesSignScriptEvent.java │ │ │ │ ├── PlayerChangesWorldScriptEvent.java │ │ │ │ ├── PlayerChangesXPScriptEvent.java │ │ │ │ ├── PlayerClicksBlockScriptEvent.java │ │ │ │ ├── PlayerClicksInInventoryScriptEvent.java │ │ │ │ ├── PlayerClosesInvScriptEvent.java │ │ │ │ ├── PlayerCompletesAdvancementScriptEvent.java │ │ │ │ ├── PlayerConsumesScriptEvent.java │ │ │ │ ├── PlayerCraftsItemScriptEvent.java │ │ │ │ ├── PlayerDamagesBlockScriptEvent.java │ │ │ │ ├── PlayerDragsInInvScriptEvent.java │ │ │ │ ├── PlayerEditsBookScriptEvent.java │ │ │ │ ├── PlayerEmptiesBucketScriptEvent.java │ │ │ │ ├── PlayerEntersBedScriptEvent.java │ │ │ │ ├── PlayerFillsBucketScriptEvent.java │ │ │ │ ├── PlayerFishesScriptEvent.java │ │ │ │ ├── PlayerFlyingScriptEvent.java │ │ │ │ ├── PlayerHearsSoundScriptEvent.java │ │ │ │ ├── PlayerIncreasesExhaustionLevelScriptEvent.java │ │ │ │ ├── PlayerInputScriptEvent.java │ │ │ │ ├── PlayerItemTakesDamageScriptEvent.java │ │ │ │ ├── PlayerJoinsScriptEvent.java │ │ │ │ ├── PlayerJumpScriptEvent.java │ │ │ │ ├── PlayerKickedScriptEvent.java │ │ │ │ ├── PlayerLeashesEntityScriptEvent.java │ │ │ │ ├── PlayerLeavesBedScriptEvent.java │ │ │ │ ├── PlayerLevelsUpScriptEvent.java │ │ │ │ ├── PlayerLocaleChangeScriptEvent.java │ │ │ │ ├── PlayerLoginScriptEvent.java │ │ │ │ ├── PlayerMendsItemScriptEvent.java │ │ │ │ ├── PlayerOpensInvScriptEvent.java │ │ │ │ ├── PlayerPickupArrowScriptEvent.java │ │ │ │ ├── PlayerPlacesBlockScriptEvent.java │ │ │ │ ├── PlayerPlacesHangingScriptEvent.java │ │ │ │ ├── PlayerPreLoginScriptEvent.java │ │ │ │ ├── PlayerPreparesAnvilCraftScriptEvent.java │ │ │ │ ├── PlayerPreparesEnchantScriptEvent.java │ │ │ │ ├── PlayerPreparesSmithingTableScriptEvent.java │ │ │ │ ├── PlayerQuitsScriptEvent.java │ │ │ │ ├── PlayerRaiseLowerItemScriptEvent.java │ │ │ │ ├── PlayerReceivesActionbarScriptEvent.java │ │ │ │ ├── PlayerReceivesCommandsScriptEvent.java │ │ │ │ ├── PlayerReceivesMessageScriptEvent.java │ │ │ │ ├── PlayerReceivesPacketScriptEvent.java │ │ │ │ ├── PlayerReceivesTablistUpdateScriptEvent.java │ │ │ │ ├── PlayerRecipeDiscoverScriptEvent.java │ │ │ │ ├── PlayerRespawnsScriptEvent.java │ │ │ │ ├── PlayerRightClicksEntityScriptEvent.java │ │ │ │ ├── PlayerRiptideScriptEvent.java │ │ │ │ ├── PlayerSendPacketScriptEvent.java │ │ │ │ ├── PlayerShearsScriptEvent.java │ │ │ │ ├── PlayerSmithsItemScriptEvent.java │ │ │ │ ├── PlayerSneakScriptEvent.java │ │ │ │ ├── PlayerSprintScriptEvent.java │ │ │ │ ├── PlayerStandsOnScriptEvent.java │ │ │ │ ├── PlayerStatisticIncrementsScriptEvent.java │ │ │ │ ├── PlayerSteersEntityScriptEvent.java │ │ │ │ ├── PlayerStepsOnScriptEvent.java │ │ │ │ ├── PlayerStopsDamagingBlockScriptEvent.java │ │ │ │ ├── PlayerSwapsItemsScriptEvent.java │ │ │ │ ├── PlayerTakesFromFurnaceScriptEvent.java │ │ │ │ ├── PlayerTakesFromLecternScriptEvent.java │ │ │ │ ├── PlayerThrowsEggScriptEvent.java │ │ │ │ ├── PlayerTriggersRaidScriptEvent.java │ │ │ │ ├── PlayerUsesPortalScriptEvent.java │ │ │ │ ├── PlayerWalkScriptEvent.java │ │ │ │ ├── PlayerWalksOverScriptEvent.java │ │ │ │ └── ResourcePackStatusScriptEvent.java │ │ │ ├── server/ │ │ │ │ ├── CommandScriptEvent.java │ │ │ │ ├── InternalEventScriptEvent.java │ │ │ │ ├── ListPingScriptEvent.java │ │ │ │ ├── ServerPrestartScriptEvent.java │ │ │ │ ├── ServerStartScriptEvent.java │ │ │ │ └── TabCompleteScriptEvent.java │ │ │ ├── vehicle/ │ │ │ │ ├── VehicleCollidesBlockScriptEvent.java │ │ │ │ ├── VehicleCollidesEntityScriptEvent.java │ │ │ │ ├── VehicleCreatedScriptEvent.java │ │ │ │ ├── VehicleDamagedScriptEvent.java │ │ │ │ ├── VehicleDestroyedScriptEvent.java │ │ │ │ └── VehicleMoveScriptEvent.java │ │ │ └── world/ │ │ │ ├── ChunkLoadEntitiesScriptEvent.java │ │ │ ├── ChunkLoadScriptEvent.java │ │ │ ├── ChunkUnloadEntitiesScriptEvent.java │ │ │ ├── ChunkUnloadScriptEvent.java │ │ │ ├── GenericGameEventScriptEvent.java │ │ │ ├── LightningStrikesScriptEvent.java │ │ │ ├── LingeringPotionSplashScriptEvent.java │ │ │ ├── LootGenerateScriptEvent.java │ │ │ ├── PortalCreateScriptEvent.java │ │ │ ├── PotionSplashScriptEvent.java │ │ │ ├── RaidFinishesScriptEvent.java │ │ │ ├── RaidScriptEvent.java │ │ │ ├── RaidSpawnsWaveScriptEvent.java │ │ │ ├── RaidStopsScriptEvent.java │ │ │ ├── SpawnChangeScriptEvent.java │ │ │ ├── StructureGrowsScriptEvent.java │ │ │ ├── ThunderChangesScriptEvent.java │ │ │ ├── TimeChangeScriptEvent.java │ │ │ ├── WeatherChangesScriptEvent.java │ │ │ ├── WorldInitsScriptEvent.java │ │ │ ├── WorldLoadsScriptEvent.java │ │ │ ├── WorldSavesScriptEvent.java │ │ │ └── WorldUnloadsScriptEvent.java │ │ ├── nms/ │ │ │ ├── NMSHandler.java │ │ │ ├── NMSVersion.java │ │ │ ├── abstracts/ │ │ │ │ ├── AnimationHelper.java │ │ │ │ ├── BiomeNMS.java │ │ │ │ ├── BlockLight.java │ │ │ │ ├── ImprovedOfflinePlayer.java │ │ │ │ ├── ProfileEditor.java │ │ │ │ └── Sidebar.java │ │ │ ├── enums/ │ │ │ │ └── CustomEntityType.java │ │ │ ├── interfaces/ │ │ │ │ ├── AdvancementHelper.java │ │ │ │ ├── BlockHelper.java │ │ │ │ ├── ChunkHelper.java │ │ │ │ ├── CustomEntity.java │ │ │ │ ├── CustomEntityHelper.java │ │ │ │ ├── EnchantmentHelper.java │ │ │ │ ├── EntityAnimation.java │ │ │ │ ├── EntityHelper.java │ │ │ │ ├── FakeArrow.java │ │ │ │ ├── FakePlayer.java │ │ │ │ ├── FishingHelper.java │ │ │ │ ├── ItemHelper.java │ │ │ │ ├── ItemProjectile.java │ │ │ │ ├── PacketHelper.java │ │ │ │ ├── PlayerHelper.java │ │ │ │ ├── WorldHelper.java │ │ │ │ └── packets/ │ │ │ │ ├── PacketInResourcePackStatus.java │ │ │ │ ├── PacketInSteerVehicle.java │ │ │ │ ├── PacketOutChat.java │ │ │ │ ├── PacketOutSetSlot.java │ │ │ │ ├── PacketOutSpawnEntity.java │ │ │ │ ├── PacketOutTradeList.java │ │ │ │ └── PacketOutWindowItems.java │ │ │ └── util/ │ │ │ ├── Advancement.java │ │ │ ├── PlayerProfile.java │ │ │ └── TradeOffer.java │ │ ├── npc/ │ │ │ ├── DenizenNPCHelper.java │ │ │ ├── TraitRegistry.java │ │ │ ├── actions/ │ │ │ │ └── ActionHandler.java │ │ │ ├── speech/ │ │ │ │ └── DenizenSpeechContext.java │ │ │ └── traits/ │ │ │ ├── AssignmentTrait.java │ │ │ ├── ConstantsTrait.java │ │ │ ├── DenizenFlagsTrait.java │ │ │ ├── FishingTrait.java │ │ │ ├── HealthTrait.java │ │ │ ├── HungerTrait.java │ │ │ ├── InvisibleTrait.java │ │ │ ├── MirrorEquipmentTrait.java │ │ │ ├── MirrorNameTrait.java │ │ │ ├── MirrorTrait.java │ │ │ ├── MobproxTrait.java │ │ │ ├── NicknameTrait.java │ │ │ ├── PushableTrait.java │ │ │ ├── SittingTrait.java │ │ │ ├── SleepingTrait.java │ │ │ ├── SneakingTrait.java │ │ │ └── TriggerTrait.java │ │ ├── objects/ │ │ │ ├── AreaContainmentObject.java │ │ │ ├── BiomeTag.java │ │ │ ├── ChunkTag.java │ │ │ ├── CuboidTag.java │ │ │ ├── EllipsoidTag.java │ │ │ ├── EnchantmentTag.java │ │ │ ├── EntityFormObject.java │ │ │ ├── EntityTag.java │ │ │ ├── InventoryTag.java │ │ │ ├── ItemTag.java │ │ │ ├── LocationTag.java │ │ │ ├── MaterialTag.java │ │ │ ├── NPCTag.java │ │ │ ├── PlayerTag.java │ │ │ ├── PluginTag.java │ │ │ ├── PolygonTag.java │ │ │ ├── TradeTag.java │ │ │ ├── WorldTag.java │ │ │ └── properties/ │ │ │ ├── PropertyRegistry.java │ │ │ ├── bukkit/ │ │ │ │ ├── BukkitBinaryTagExtensions.java │ │ │ │ ├── BukkitColorExtensions.java │ │ │ │ ├── BukkitElementExtensions.java │ │ │ │ ├── BukkitListExtensions.java │ │ │ │ ├── BukkitMapExtensions.java │ │ │ │ ├── BukkitQueueExtensions.java │ │ │ │ └── BukkitScriptExtensions.java │ │ │ ├── entity/ │ │ │ │ ├── EntityAI.java │ │ │ │ ├── EntityAge.java │ │ │ │ ├── EntityAgeLocked.java │ │ │ │ ├── EntityAggressive.java │ │ │ │ ├── EntityAnger.java │ │ │ │ ├── EntityAngry.java │ │ │ │ ├── EntityAreaEffectCloud.java │ │ │ │ ├── EntityArmorBonus.java │ │ │ │ ├── EntityArmorPose.java │ │ │ │ ├── EntityArms.java │ │ │ │ ├── EntityArrowDamage.java │ │ │ │ ├── EntityArrowPierceLevel.java │ │ │ │ ├── EntityAttributeBaseValues.java │ │ │ │ ├── EntityAttributeModifiers.java │ │ │ │ ├── EntityAwake.java │ │ │ │ ├── EntityAware.java │ │ │ │ ├── EntityBackgroundColor.java │ │ │ │ ├── EntityBasePlate.java │ │ │ │ ├── EntityBeamTarget.java │ │ │ │ ├── EntityBoatType.java │ │ │ │ ├── EntityBodyArrows.java │ │ │ │ ├── EntityBoundingBox.java │ │ │ │ ├── EntityBrightness.java │ │ │ │ ├── EntityCanBreakDoors.java │ │ │ │ ├── EntityCanJoinRaid.java │ │ │ │ ├── EntityCannotEnterHive.java │ │ │ │ ├── EntityCharged.java │ │ │ │ ├── EntityChestCarrier.java │ │ │ │ ├── EntityColor.java │ │ │ │ ├── EntityConversionPlayer.java │ │ │ │ ├── EntityConversionTime.java │ │ │ │ ├── EntityCritical.java │ │ │ │ ├── EntityCustomName.java │ │ │ │ ├── EntityCustomNameVisible.java │ │ │ │ ├── EntityDarkDuration.java │ │ │ │ ├── EntityDefaultBackground.java │ │ │ │ ├── EntityDirection.java │ │ │ │ ├── EntityDisabledSlots.java │ │ │ │ ├── EntityDisplay.java │ │ │ │ ├── EntityDropsItem.java │ │ │ │ ├── EntityEquipment.java │ │ │ │ ├── EntityEquipmentDropChance.java │ │ │ │ ├── EntityExploredLocations.java │ │ │ │ ├── EntityExplosionFire.java │ │ │ │ ├── EntityExplosionRadius.java │ │ │ │ ├── EntityEyeTargetLocation.java │ │ │ │ ├── EntityFirework.java │ │ │ │ ├── EntityFireworkLifetime.java │ │ │ │ ├── EntityFixed.java │ │ │ │ ├── EntityFlags.java │ │ │ │ ├── EntityFlower.java │ │ │ │ ├── EntityFramed.java │ │ │ │ ├── EntityFreezeDuration.java │ │ │ │ ├── EntityGlowColor.java │ │ │ │ ├── EntityGravity.java │ │ │ │ ├── EntityHasNectar.java │ │ │ │ ├── EntityHasStung.java │ │ │ │ ├── EntityHealth.java │ │ │ │ ├── EntityHeight.java │ │ │ │ ├── EntityHive.java │ │ │ │ ├── EntityHorns.java │ │ │ │ ├── EntityImmune.java │ │ │ │ ├── EntityInWaterTime.java │ │ │ │ ├── EntityInterpolationDuration.java │ │ │ │ ├── EntityInterpolationStart.java │ │ │ │ ├── EntityInventory.java │ │ │ │ ├── EntityInvulnerable.java │ │ │ │ ├── EntityIsShowingBottom.java │ │ │ │ ├── EntityItem.java │ │ │ │ ├── EntityItemInHand.java │ │ │ │ ├── EntityItemInOffHand.java │ │ │ │ ├── EntityJumpStrength.java │ │ │ │ ├── EntityKnockback.java │ │ │ │ ├── EntityLeftRotation.java │ │ │ │ ├── EntityLineWidth.java │ │ │ │ ├── EntityMarker.java │ │ │ │ ├── EntityMaterial.java │ │ │ │ ├── EntityMaxFuseTicks.java │ │ │ │ ├── EntityMaxTemper.java │ │ │ │ ├── EntityOnBack.java │ │ │ │ ├── EntityOpacity.java │ │ │ │ ├── EntityPainting.java │ │ │ │ ├── EntityPatrolLeader.java │ │ │ │ ├── EntityPatrolTarget.java │ │ │ │ ├── EntityPickupStatus.java │ │ │ │ ├── EntityPivot.java │ │ │ │ ├── EntityPlayerCreated.java │ │ │ │ ├── EntityPlayingDead.java │ │ │ │ ├── EntityPotion.java │ │ │ │ ├── EntityPotionEffects.java │ │ │ │ ├── EntityPotionType.java │ │ │ │ ├── EntityPowered.java │ │ │ │ ├── EntityProfession.java │ │ │ │ ├── EntityProperty.java │ │ │ │ ├── EntityRightRotation.java │ │ │ │ ├── EntityRiptide.java │ │ │ │ ├── EntityRolling.java │ │ │ │ ├── EntityRotation.java │ │ │ │ ├── EntityScale.java │ │ │ │ ├── EntityScoreboardTags.java │ │ │ │ ├── EntitySeeThrough.java │ │ │ │ ├── EntityShadowRadius.java │ │ │ │ ├── EntityShadowStrength.java │ │ │ │ ├── EntitySheared.java │ │ │ │ ├── EntityShivering.java │ │ │ │ ├── EntityShotAtAngle.java │ │ │ │ ├── EntityShulkerPeek.java │ │ │ │ ├── EntitySilent.java │ │ │ │ ├── EntitySitting.java │ │ │ │ ├── EntitySize.java │ │ │ │ ├── EntitySmall.java │ │ │ │ ├── EntitySneezing.java │ │ │ │ ├── EntitySpeed.java │ │ │ │ ├── EntitySpell.java │ │ │ │ ├── EntityState.java │ │ │ │ ├── EntityStepHeight.java │ │ │ │ ├── EntityStrength.java │ │ │ │ ├── EntityTame.java │ │ │ │ ├── EntityTeleportDuration.java │ │ │ │ ├── EntityTemper.java │ │ │ │ ├── EntityText.java │ │ │ │ ├── EntityTextShadowed.java │ │ │ │ ├── EntityTrades.java │ │ │ │ ├── EntityTranslation.java │ │ │ │ ├── EntityTrapTime.java │ │ │ │ ├── EntityTrapped.java │ │ │ │ ├── EntityVariant.java │ │ │ │ ├── EntityViewRange.java │ │ │ │ ├── EntityVillagerExperience.java │ │ │ │ ├── EntityVillagerLevel.java │ │ │ │ ├── EntityVisible.java │ │ │ │ ├── EntityVisualFire.java │ │ │ │ └── EntityWidth.java │ │ │ ├── inventory/ │ │ │ │ ├── InventoryContents.java │ │ │ │ ├── InventoryHolder.java │ │ │ │ ├── InventorySize.java │ │ │ │ ├── InventoryTitle.java │ │ │ │ ├── InventoryTrades.java │ │ │ │ └── InventoryUniquifier.java │ │ │ ├── item/ │ │ │ │ ├── ItemArmorPose.java │ │ │ │ ├── ItemAttributeModifiers.java │ │ │ │ ├── ItemAttributeNBT.java │ │ │ │ ├── ItemBaseColor.java │ │ │ │ ├── ItemBlockMaterial.java │ │ │ │ ├── ItemBook.java │ │ │ │ ├── ItemBookGeneration.java │ │ │ │ ├── ItemCanDestroy.java │ │ │ │ ├── ItemCanPlaceOn.java │ │ │ │ ├── ItemChargedProjectile.java │ │ │ │ ├── ItemColor.java │ │ │ │ ├── ItemComponentsPatch.java │ │ │ │ ├── ItemCustomData.java │ │ │ │ ├── ItemCustomModel.java │ │ │ │ ├── ItemDisplayname.java │ │ │ │ ├── ItemDurability.java │ │ │ │ ├── ItemEnchantments.java │ │ │ │ ├── ItemFirework.java │ │ │ │ ├── ItemFireworkPower.java │ │ │ │ ├── ItemFlags.java │ │ │ │ ├── ItemFrameInvisible.java │ │ │ │ ├── ItemHidden.java │ │ │ │ ├── ItemInstrument.java │ │ │ │ ├── ItemInventoryContents.java │ │ │ │ ├── ItemKnowledgeBookRecipes.java │ │ │ │ ├── ItemLock.java │ │ │ │ ├── ItemLodestoneLocation.java │ │ │ │ ├── ItemLodestoneTracked.java │ │ │ │ ├── ItemLore.java │ │ │ │ ├── ItemMap.java │ │ │ │ ├── ItemNBT.java │ │ │ │ ├── ItemPatterns.java │ │ │ │ ├── ItemPotion.java │ │ │ │ ├── ItemProperty.java │ │ │ │ ├── ItemQuantity.java │ │ │ │ ├── ItemRawNBT.java │ │ │ │ ├── ItemRepairCost.java │ │ │ │ ├── ItemScript.java │ │ │ │ ├── ItemSignContents.java │ │ │ │ ├── ItemSignIsWaxed.java │ │ │ │ ├── ItemSkullskin.java │ │ │ │ ├── ItemSpawnerCount.java │ │ │ │ ├── ItemSpawnerDelay.java │ │ │ │ ├── ItemSpawnerMaxNearbyEntities.java │ │ │ │ ├── ItemSpawnerPlayerRange.java │ │ │ │ ├── ItemSpawnerRange.java │ │ │ │ ├── ItemSpawnerType.java │ │ │ │ ├── ItemTrim.java │ │ │ │ └── ItemUnbreakable.java │ │ │ ├── material/ │ │ │ │ ├── MaterialAge.java │ │ │ │ ├── MaterialAttached.java │ │ │ │ ├── MaterialAttachmentFace.java │ │ │ │ ├── MaterialBlockType.java │ │ │ │ ├── MaterialBrewingStand.java │ │ │ │ ├── MaterialCampfire.java │ │ │ │ ├── MaterialCount.java │ │ │ │ ├── MaterialDelay.java │ │ │ │ ├── MaterialDirectional.java │ │ │ │ ├── MaterialDistance.java │ │ │ │ ├── MaterialDrags.java │ │ │ │ ├── MaterialFaces.java │ │ │ │ ├── MaterialHalf.java │ │ │ │ ├── MaterialHinge.java │ │ │ │ ├── MaterialInstrument.java │ │ │ │ ├── MaterialLeafSize.java │ │ │ │ ├── MaterialLevel.java │ │ │ │ ├── MaterialLightable.java │ │ │ │ ├── MaterialLocked.java │ │ │ │ ├── MaterialMode.java │ │ │ │ ├── MaterialNote.java │ │ │ │ ├── MaterialOminous.java │ │ │ │ ├── MaterialPersistent.java │ │ │ │ ├── MaterialPower.java │ │ │ │ ├── MaterialProperty.java │ │ │ │ ├── MaterialShape.java │ │ │ │ ├── MaterialSides.java │ │ │ │ ├── MaterialSnowable.java │ │ │ │ ├── MaterialSwitchable.java │ │ │ │ ├── MaterialUnstable.java │ │ │ │ └── MaterialWaterlogged.java │ │ │ └── trade/ │ │ │ ├── TradeDemand.java │ │ │ ├── TradeHasXp.java │ │ │ ├── TradeInputs.java │ │ │ ├── TradeMaxUses.java │ │ │ ├── TradePriceMultiplier.java │ │ │ ├── TradeProperty.java │ │ │ ├── TradeResult.java │ │ │ ├── TradeSpecialPrice.java │ │ │ ├── TradeUses.java │ │ │ └── TradeVillagerXP.java │ │ ├── scripts/ │ │ │ ├── commands/ │ │ │ │ ├── BukkitCommandRegistry.java │ │ │ │ ├── core/ │ │ │ │ │ ├── CooldownCommand.java │ │ │ │ │ ├── ResetCommand.java │ │ │ │ │ └── ZapCommand.java │ │ │ │ ├── entity/ │ │ │ │ │ ├── AgeCommand.java │ │ │ │ │ ├── AnimateCommand.java │ │ │ │ │ ├── AttachCommand.java │ │ │ │ │ ├── AttackCommand.java │ │ │ │ │ ├── BurnCommand.java │ │ │ │ │ ├── CastCommand.java │ │ │ │ │ ├── EquipCommand.java │ │ │ │ │ ├── FakeEquipCommand.java │ │ │ │ │ ├── FakeInternalDataCommand.java │ │ │ │ │ ├── FeedCommand.java │ │ │ │ │ ├── FlyCommand.java │ │ │ │ │ ├── FollowCommand.java │ │ │ │ │ ├── GlowCommand.java │ │ │ │ │ ├── HeadCommand.java │ │ │ │ │ ├── HealCommand.java │ │ │ │ │ ├── HealthCommand.java │ │ │ │ │ ├── HurtCommand.java │ │ │ │ │ ├── InvisibleCommand.java │ │ │ │ │ ├── KillCommand.java │ │ │ │ │ ├── LeashCommand.java │ │ │ │ │ ├── LookCommand.java │ │ │ │ │ ├── MountCommand.java │ │ │ │ │ ├── PushCommand.java │ │ │ │ │ ├── RemoveCommand.java │ │ │ │ │ ├── RenameCommand.java │ │ │ │ │ ├── RotateCommand.java │ │ │ │ │ ├── ShootCommand.java │ │ │ │ │ ├── SneakCommand.java │ │ │ │ │ ├── SpawnCommand.java │ │ │ │ │ ├── TeleportCommand.java │ │ │ │ │ ├── WalkCommand.java │ │ │ │ │ └── WalkCommandCitizensEvents.java │ │ │ │ ├── item/ │ │ │ │ │ ├── DisplayItemCommand.java │ │ │ │ │ ├── FakeItemCommand.java │ │ │ │ │ ├── GiveCommand.java │ │ │ │ │ ├── InventoryCommand.java │ │ │ │ │ ├── MapCommand.java │ │ │ │ │ └── TakeCommand.java │ │ │ │ ├── npc/ │ │ │ │ │ ├── ActionCommand.java │ │ │ │ │ ├── AnchorCommand.java │ │ │ │ │ ├── AssignmentCommand.java │ │ │ │ │ ├── BreakCommand.java │ │ │ │ │ ├── CreateCommand.java │ │ │ │ │ ├── DespawnCommand.java │ │ │ │ │ ├── DisengageCommand.java │ │ │ │ │ ├── EngageCommand.java │ │ │ │ │ ├── FishCommand.java │ │ │ │ │ ├── LookcloseCommand.java │ │ │ │ │ ├── NPCBossBarCommand.java │ │ │ │ │ ├── PauseCommand.java │ │ │ │ │ ├── PoseCommand.java │ │ │ │ │ ├── PushableCommand.java │ │ │ │ │ ├── SitCommand.java │ │ │ │ │ ├── SleepCommand.java │ │ │ │ │ ├── StandCommand.java │ │ │ │ │ ├── TraitCommand.java │ │ │ │ │ ├── TriggerCommand.java │ │ │ │ │ └── VulnerableCommand.java │ │ │ │ ├── player/ │ │ │ │ │ ├── ActionBarCommand.java │ │ │ │ │ ├── AdvancementCommand.java │ │ │ │ │ ├── BlockCrackCommand.java │ │ │ │ │ ├── ChatCommand.java │ │ │ │ │ ├── ClickableCommand.java │ │ │ │ │ ├── CompassCommand.java │ │ │ │ │ ├── DebugBlockCommand.java │ │ │ │ │ ├── DisguiseCommand.java │ │ │ │ │ ├── ExperienceCommand.java │ │ │ │ │ ├── FakeSpawnCommand.java │ │ │ │ │ ├── GroupCommand.java │ │ │ │ │ ├── ItemCooldownCommand.java │ │ │ │ │ ├── KickCommand.java │ │ │ │ │ ├── MoneyCommand.java │ │ │ │ │ ├── NarrateCommand.java │ │ │ │ │ ├── OpenTradesCommand.java │ │ │ │ │ ├── OxygenCommand.java │ │ │ │ │ ├── PermissionCommand.java │ │ │ │ │ ├── ResourcePackCommand.java │ │ │ │ │ ├── ShowFakeCommand.java │ │ │ │ │ ├── SidebarCommand.java │ │ │ │ │ ├── StatisticCommand.java │ │ │ │ │ ├── TablistCommand.java │ │ │ │ │ ├── TeamCommand.java │ │ │ │ │ ├── TitleCommand.java │ │ │ │ │ └── ToastCommand.java │ │ │ │ ├── server/ │ │ │ │ │ ├── AnnounceCommand.java │ │ │ │ │ ├── BanCommand.java │ │ │ │ │ ├── BossBarCommand.java │ │ │ │ │ ├── ExecuteCommand.java │ │ │ │ │ └── ScoreboardCommand.java │ │ │ │ └── world/ │ │ │ │ ├── AdjustBlockCommand.java │ │ │ │ ├── AnimateChestCommand.java │ │ │ │ ├── ChunkLoadCommand.java │ │ │ │ ├── CopyBlockCommand.java │ │ │ │ ├── CreateWorldCommand.java │ │ │ │ ├── DropCommand.java │ │ │ │ ├── ExplodeCommand.java │ │ │ │ ├── FireworkCommand.java │ │ │ │ ├── GameRuleCommand.java │ │ │ │ ├── LightCommand.java │ │ │ │ ├── MidiCommand.java │ │ │ │ ├── ModifyBlockCommand.java │ │ │ │ ├── PlayEffectCommand.java │ │ │ │ ├── PlaySoundCommand.java │ │ │ │ ├── SchematicCommand.java │ │ │ │ ├── SignCommand.java │ │ │ │ ├── StrikeCommand.java │ │ │ │ ├── SwitchCommand.java │ │ │ │ ├── TickCommand.java │ │ │ │ ├── TimeCommand.java │ │ │ │ ├── WeatherCommand.java │ │ │ │ └── WorldBorderCommand.java │ │ │ ├── containers/ │ │ │ │ ├── ContainerRegistry.java │ │ │ │ └── core/ │ │ │ │ ├── AssignmentScriptContainer.java │ │ │ │ ├── BookScriptContainer.java │ │ │ │ ├── BukkitWorldScriptHelper.java │ │ │ │ ├── CommandScriptContainer.java │ │ │ │ ├── CommandScriptHelper.java │ │ │ │ ├── EconomyScriptContainer.java │ │ │ │ ├── EnchantmentScriptContainer.java │ │ │ │ ├── EntityScriptContainer.java │ │ │ │ ├── EntityScriptHelper.java │ │ │ │ ├── InteractScriptContainer.java │ │ │ │ ├── InteractScriptHelper.java │ │ │ │ ├── InventoryScriptContainer.java │ │ │ │ ├── InventoryScriptHelper.java │ │ │ │ ├── ItemScriptContainer.java │ │ │ │ ├── ItemScriptHelper.java │ │ │ │ ├── MapScriptContainer.java │ │ │ │ └── VersionScriptContainer.java │ │ │ └── triggers/ │ │ │ ├── AbstractTrigger.java │ │ │ ├── TriggerRegistry.java │ │ │ └── core/ │ │ │ ├── ChatTrigger.java │ │ │ ├── ClickTrigger.java │ │ │ ├── DamageTrigger.java │ │ │ └── ProximityTrigger.java │ │ ├── tags/ │ │ │ ├── BukkitTagContext.java │ │ │ └── core/ │ │ │ ├── CustomColorTagBase.java │ │ │ ├── NPCTagBase.java │ │ │ ├── PlayerTagBase.java │ │ │ ├── ServerTagBase.java │ │ │ └── TextTagBase.java │ │ └── utilities/ │ │ ├── BukkitImplDeprecations.java │ │ ├── CommonRegistries.java │ │ ├── Conversion.java │ │ ├── DataPersistenceHelper.java │ │ ├── FormattedTextHelper.java │ │ ├── HoverFormatHelper.java │ │ ├── LegacyParticleNaming.java │ │ ├── LegacySavesUpdater.java │ │ ├── MultiVersionHelper1_18.java │ │ ├── MultiVersionHelper1_19.java │ │ ├── NotedAreaTracker.java │ │ ├── PaperAPITools.java │ │ ├── ScoreboardHelper.java │ │ ├── Settings.java │ │ ├── TextWidthHelper.java │ │ ├── Utilities.java │ │ ├── VanillaTagHelper.java │ │ ├── blocks/ │ │ │ ├── BlockSet.java │ │ │ ├── ChunkCoordinate.java │ │ │ ├── CuboidBlockSet.java │ │ │ ├── FakeBlock.java │ │ │ ├── FullBlockData.java │ │ │ ├── SpawnableHelper.java │ │ │ └── SpongeSchematicHelper.java │ │ ├── command/ │ │ │ ├── CommandEvents.java │ │ │ ├── DenizenCommandHandler.java │ │ │ ├── ExCommandHandler.java │ │ │ ├── ExSustainedCommandHandler.java │ │ │ ├── NPCCommandHandler.java │ │ │ ├── TabCompleteHelper.java │ │ │ ├── manager/ │ │ │ │ ├── Command.java │ │ │ │ ├── CommandAnnotationProcessor.java │ │ │ │ ├── CommandContext.java │ │ │ │ ├── CommandManager.java │ │ │ │ ├── Injector.java │ │ │ │ ├── Paginator.java │ │ │ │ ├── Requirements.java │ │ │ │ ├── RequirementsProcessor.java │ │ │ │ ├── exceptions/ │ │ │ │ │ ├── CommandException.java │ │ │ │ │ ├── CommandUsageException.java │ │ │ │ │ ├── NoPermissionsException.java │ │ │ │ │ ├── RequirementMissingException.java │ │ │ │ │ ├── ServerCommandException.java │ │ │ │ │ ├── UnhandledCommandException.java │ │ │ │ │ └── WrappedCommandException.java │ │ │ │ └── messaging/ │ │ │ │ ├── Colorizer.java │ │ │ │ └── Messaging.java │ │ │ └── scripted/ │ │ │ ├── DenizenAliasHelpTopic.java │ │ │ ├── DenizenCommand.java │ │ │ ├── DenizenCommandHelpTopic.java │ │ │ └── DenizenCommandSender.java │ │ ├── debugging/ │ │ │ ├── BStatsMetricsLite.java │ │ │ ├── Debug.java │ │ │ ├── DebugConsoleSender.java │ │ │ ├── DebugSubmit.java │ │ │ └── StatsRecord.java │ │ ├── depends/ │ │ │ └── Depends.java │ │ ├── entity/ │ │ │ ├── AreaEffectCloudHelper.java │ │ │ ├── BossBarHelper.java │ │ │ ├── DenizenEntityType.java │ │ │ ├── EntityAttachmentHelper.java │ │ │ ├── EntityMetadataCommandHelper.java │ │ │ ├── FakeEntity.java │ │ │ ├── Gravity.java │ │ │ ├── HideEntitiesHelper.java │ │ │ ├── Position.java │ │ │ ├── SpawnEntityHelper.java │ │ │ └── Velocity.java │ │ ├── flags/ │ │ │ ├── DataPersistenceFlagTracker.java │ │ │ ├── LocationFlagSearchHelper.java │ │ │ ├── PlayerFlagHandler.java │ │ │ └── WorldFlagHandler.java │ │ ├── implementation/ │ │ │ ├── BukkitScriptEntryData.java │ │ │ └── DenizenCoreImplementation.java │ │ ├── inventory/ │ │ │ ├── InventoryTrackerSystem.java │ │ │ ├── InventoryViewUtil.java │ │ │ ├── RecipeHelper.java │ │ │ └── SlotHelper.java │ │ ├── maps/ │ │ │ ├── DenizenMapManager.java │ │ │ ├── DenizenMapRenderer.java │ │ │ ├── MapCursor.java │ │ │ ├── MapDot.java │ │ │ ├── MapImage.java │ │ │ ├── MapObject.java │ │ │ └── MapText.java │ │ ├── midi/ │ │ │ ├── MidiUtil.java │ │ │ ├── NoteBlockReceiver.java │ │ │ └── ToneUtil.java │ │ ├── nbt/ │ │ │ ├── CustomNBT.java │ │ │ └── LeatherColorer.java │ │ ├── packets/ │ │ │ ├── DenizenPacketHandler.java │ │ │ ├── HideParticles.java │ │ │ ├── ItemChangeMessage.java │ │ │ ├── NetworkInterceptCodeGen.java │ │ │ └── NetworkInterceptHelper.java │ │ └── world/ │ │ ├── GameRuleReflect.java │ │ ├── PathFinder.java │ │ ├── VoidGenerator.java │ │ └── WorldListChangeTracker.java │ └── resources/ │ ├── Denizen.mid │ ├── config.yml │ └── plugin.yml ├── pom.xml ├── v1_17/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── nms/ │ └── v1_17/ │ ├── Handler.java │ ├── ReflectionMappingsInfo.java │ ├── helpers/ │ │ ├── AdvancementHelperImpl.java │ │ ├── AnimationHelperImpl.java │ │ ├── BlockHelperImpl.java │ │ ├── ChunkHelperImpl.java │ │ ├── CustomEntityHelperImpl.java │ │ ├── EnchantmentHelperImpl.java │ │ ├── EntityHelperImpl.java │ │ ├── FishingHelperImpl.java │ │ ├── ItemHelperImpl.java │ │ ├── NBTAdapter.java │ │ ├── PacketHelperImpl.java │ │ ├── PlayerHelperImpl.java │ │ └── WorldHelperImpl.java │ └── impl/ │ ├── BiomeNMSImpl.java │ ├── ImprovedOfflinePlayerImpl.java │ ├── ProfileEditorImpl.java │ ├── SidebarImpl.java │ ├── blocks/ │ │ └── BlockLightImpl.java │ ├── entities/ │ │ ├── CraftFakeArrowImpl.java │ │ ├── CraftFakePlayerImpl.java │ │ ├── CraftItemProjectileImpl.java │ │ ├── EntityFakeArrowImpl.java │ │ ├── EntityFakePlayerImpl.java │ │ └── EntityItemProjectileImpl.java │ └── network/ │ ├── fakes/ │ │ ├── FakeChannelImpl.java │ │ ├── FakeNetworkManagerImpl.java │ │ └── FakePlayerConnectionImpl.java │ ├── handlers/ │ │ ├── AbstractListenerPlayInImpl.java │ │ ├── DenizenNetworkManagerImpl.java │ │ ├── DenizenPacketListenerImpl.java │ │ └── FakeBlockHelper.java │ └── packets/ │ ├── PacketInResourcePackStatusImpl.java │ ├── PacketInSteerVehicleImpl.java │ ├── PacketOutChatImpl.java │ ├── PacketOutSetSlotImpl.java │ ├── PacketOutSpawnEntityImpl.java │ ├── PacketOutTradeListImpl.java │ └── PacketOutWindowItemsImpl.java ├── v1_18/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── nms/ │ └── v1_18/ │ ├── Handler.java │ ├── ReflectionMappingsInfo.java │ ├── helpers/ │ │ ├── AdvancementHelperImpl.java │ │ ├── AnimationHelperImpl.java │ │ ├── BlockHelperImpl.java │ │ ├── ChunkHelperImpl.java │ │ ├── CustomEntityHelperImpl.java │ │ ├── EnchantmentHelperImpl.java │ │ ├── EntityHelperImpl.java │ │ ├── FishingHelperImpl.java │ │ ├── ItemHelperImpl.java │ │ ├── NBTAdapter.java │ │ ├── PacketHelperImpl.java │ │ ├── PlayerHelperImpl.java │ │ └── WorldHelperImpl.java │ └── impl/ │ ├── BiomeNMSImpl.java │ ├── ImprovedOfflinePlayerImpl.java │ ├── ProfileEditorImpl.java │ ├── SidebarImpl.java │ ├── blocks/ │ │ └── BlockLightImpl.java │ ├── entities/ │ │ ├── CraftFakeArrowImpl.java │ │ ├── CraftFakePlayerImpl.java │ │ ├── CraftItemProjectileImpl.java │ │ ├── EntityFakeArrowImpl.java │ │ ├── EntityFakePlayerImpl.java │ │ └── EntityItemProjectileImpl.java │ └── network/ │ ├── fakes/ │ │ ├── FakeChannelImpl.java │ │ ├── FakeNetworkManagerImpl.java │ │ └── FakePlayerConnectionImpl.java │ ├── handlers/ │ │ ├── AbstractListenerPlayInImpl.java │ │ ├── DenizenNetworkManagerImpl.java │ │ ├── DenizenPacketListenerImpl.java │ │ └── FakeBlockHelper.java │ └── packets/ │ ├── PacketInResourcePackStatusImpl.java │ ├── PacketInSteerVehicleImpl.java │ └── PacketOutChatImpl.java ├── v1_19/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── nms/ │ └── v1_19/ │ ├── Handler.java │ ├── ReflectionMappingsInfo.java │ ├── helpers/ │ │ ├── AdvancementHelperImpl.java │ │ ├── AnimationHelperImpl.java │ │ ├── BlockHelperImpl.java │ │ ├── ChunkHelperImpl.java │ │ ├── CustomEntityHelperImpl.java │ │ ├── EnchantmentHelperImpl.java │ │ ├── EntityHelperImpl.java │ │ ├── FishingHelperImpl.java │ │ ├── ItemHelperImpl.java │ │ ├── NBTAdapter.java │ │ ├── PacketHelperImpl.java │ │ ├── PlayerHelperImpl.java │ │ └── WorldHelperImpl.java │ └── impl/ │ ├── BiomeNMSImpl.java │ ├── ImprovedOfflinePlayerImpl.java │ ├── ProfileEditorImpl.java │ ├── SidebarImpl.java │ ├── blocks/ │ │ └── BlockLightImpl.java │ ├── entities/ │ │ ├── CraftFakeArrowImpl.java │ │ ├── CraftFakePlayerImpl.java │ │ ├── CraftItemProjectileImpl.java │ │ ├── EntityFakeArrowImpl.java │ │ ├── EntityFakePlayerImpl.java │ │ └── EntityItemProjectileImpl.java │ └── network/ │ ├── fakes/ │ │ ├── FakeChannelImpl.java │ │ ├── FakeNetworkManagerImpl.java │ │ └── FakePlayerConnectionImpl.java │ ├── handlers/ │ │ ├── AbstractListenerPlayInImpl.java │ │ ├── DenizenNetworkManagerImpl.java │ │ ├── DenizenPacketListenerImpl.java │ │ └── FakeBlockHelper.java │ └── packets/ │ ├── PacketInResourcePackStatusImpl.java │ ├── PacketInSteerVehicleImpl.java │ └── PacketOutChatImpl.java ├── v1_20/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── nms/ │ └── v1_20/ │ ├── Handler.java │ ├── ReflectionMappingsInfo.java │ ├── helpers/ │ │ ├── AdvancementHelperImpl.java │ │ ├── AnimationHelperImpl.java │ │ ├── BlockHelperImpl.java │ │ ├── ChunkHelperImpl.java │ │ ├── CustomEntityHelperImpl.java │ │ ├── EnchantmentHelperImpl.java │ │ ├── EntityDataNameMapper.java │ │ ├── EntityHelperImpl.java │ │ ├── FishingHelperImpl.java │ │ ├── ItemHelperImpl.java │ │ ├── NBTAdapter.java │ │ ├── PacketHelperImpl.java │ │ ├── PlayerHelperImpl.java │ │ └── WorldHelperImpl.java │ └── impl/ │ ├── BiomeNMSImpl.java │ ├── ImprovedOfflinePlayerImpl.java │ ├── ProfileEditorImpl.java │ ├── SidebarImpl.java │ ├── blocks/ │ │ └── BlockLightImpl.java │ ├── entities/ │ │ ├── CraftFakeArrowImpl.java │ │ ├── CraftFakePlayerImpl.java │ │ ├── CraftItemProjectileImpl.java │ │ ├── EntityFakeArrowImpl.java │ │ ├── EntityFakePlayerImpl.java │ │ └── EntityItemProjectileImpl.java │ └── network/ │ ├── fakes/ │ │ ├── FakeChannelImpl.java │ │ ├── FakeNetworkManagerImpl.java │ │ └── FakePlayerConnectionImpl.java │ ├── handlers/ │ │ ├── AbstractListenerPlayInImpl.java │ │ ├── DenizenNetworkManagerImpl.java │ │ ├── DenizenPacketListenerImpl.java │ │ ├── FakeBlockHelper.java │ │ └── packet/ │ │ ├── ActionBarEventPacketHandlers.java │ │ ├── AttachPacketHandlers.java │ │ ├── BlockLightPacketHandlers.java │ │ ├── DenizenPacketHandlerPacketHandlers.java │ │ ├── DisguisePacketHandlers.java │ │ ├── EntityMetadataPacketHandlers.java │ │ ├── FakeBlocksPacketHandlers.java │ │ ├── FakeEquipmentPacketHandlers.java │ │ ├── FakePlayerPacketHandlers.java │ │ ├── HiddenEntitiesPacketHandlers.java │ │ ├── HideParticlesPacketHandlers.java │ │ ├── PlayerHearsSoundEventPacketHandlers.java │ │ └── TablistUpdateEventPacketHandlers.java │ └── packets/ │ ├── PacketInResourcePackStatusImpl.java │ ├── PacketInSteerVehicleImpl.java │ └── PacketOutChatImpl.java ├── v1_21/ │ ├── pom.xml │ └── src/ │ └── main/ │ └── java/ │ └── com/ │ └── denizenscript/ │ └── denizen/ │ └── nms/ │ └── v1_21/ │ ├── Handler.java │ ├── ReflectionMappingsInfo.java │ ├── helpers/ │ │ ├── AdvancementHelperImpl.java │ │ ├── AnimationHelperImpl.java │ │ ├── BlockHelperImpl.java │ │ ├── ChunkHelperImpl.java │ │ ├── CustomEntityHelperImpl.java │ │ ├── EnchantmentHelperImpl.java │ │ ├── EntityDataNameMapper.java │ │ ├── EntityHelperImpl.java │ │ ├── FishingHelperImpl.java │ │ ├── ItemHelperImpl.java │ │ ├── NBTAdapter.java │ │ ├── PacketHelperImpl.java │ │ ├── PlayerHelperImpl.java │ │ └── WorldHelperImpl.java │ └── impl/ │ ├── BiomeNMSImpl.java │ ├── ImprovedOfflinePlayerImpl.java │ ├── ProfileEditorImpl.java │ ├── SidebarImpl.java │ ├── blocks/ │ │ └── BlockLightImpl.java │ ├── entities/ │ │ ├── CraftFakeArrowImpl.java │ │ ├── CraftFakePlayerImpl.java │ │ ├── CraftItemProjectileImpl.java │ │ ├── EntityFakeArrowImpl.java │ │ ├── EntityFakePlayerImpl.java │ │ └── EntityItemProjectileImpl.java │ └── network/ │ ├── fakes/ │ │ ├── FakeChannelImpl.java │ │ ├── FakeNetworkManagerImpl.java │ │ └── FakePlayerConnectionImpl.java │ ├── handlers/ │ │ ├── AbstractListenerPlayInImpl.java │ │ ├── DenizenNetworkManagerImpl.java │ │ ├── DenizenPacketListenerImpl.java │ │ ├── FakeBlockHelper.java │ │ └── packet/ │ │ ├── ActionBarEventPacketHandlers.java │ │ ├── AttachPacketHandlers.java │ │ ├── BlockLightPacketHandlers.java │ │ ├── DenizenPacketHandlerPacketHandlers.java │ │ ├── DisguisePacketHandlers.java │ │ ├── EntityMetadataPacketHandlers.java │ │ ├── FakeBlocksPacketHandlers.java │ │ ├── FakeEquipmentPacketHandlers.java │ │ ├── FakePlayerPacketHandlers.java │ │ ├── HiddenEntitiesPacketHandlers.java │ │ ├── HideParticlesPacketHandlers.java │ │ ├── PlayerHearsSoundEventPacketHandlers.java │ │ └── TablistUpdateEventPacketHandlers.java │ └── packets/ │ ├── PacketInResourcePackStatusImpl.java │ ├── PacketInSteerVehicleImpl.java │ └── PacketOutChatImpl.java └── v26_1/ ├── pom.xml └── src/ └── main/ └── java/ └── com/ └── denizenscript/ └── denizen/ └── nms/ └── v26_1/ ├── Handler.java ├── helpers/ │ ├── AdvancementHelperImpl.java │ ├── AnimationHelperImpl.java │ ├── BlockHelperImpl.java │ ├── ChunkHelperImpl.java │ ├── CustomEntityHelperImpl.java │ ├── EnchantmentHelperImpl.java │ ├── EntityDataNameMapper.java │ ├── EntityHelperImpl.java │ ├── FishingHelperImpl.java │ ├── ItemHelperImpl.java │ ├── NBTAdapter.java │ ├── PacketHelperImpl.java │ ├── PlayerHelperImpl.java │ └── WorldHelperImpl.java └── impl/ ├── BiomeNMSImpl.java ├── ImprovedOfflinePlayerImpl.java ├── ProfileEditorImpl.java ├── SidebarImpl.java ├── blocks/ │ └── BlockLightImpl.java ├── entities/ │ ├── CraftFakeArrowImpl.java │ ├── CraftFakePlayerImpl.java │ ├── CraftItemProjectileImpl.java │ ├── EntityFakeArrowImpl.java │ ├── EntityFakePlayerImpl.java │ └── EntityItemProjectileImpl.java └── network/ ├── fakes/ │ ├── FakeChannelImpl.java │ ├── FakeNetworkManagerImpl.java │ └── FakePlayerConnectionImpl.java ├── handlers/ │ ├── AbstractListenerPlayInImpl.java │ ├── DenizenNetworkManagerImpl.java │ ├── DenizenPacketListenerImpl.java │ ├── FakeBlockHelper.java │ └── packet/ │ ├── ActionBarEventPacketHandlers.java │ ├── AttachPacketHandlers.java │ ├── BlockLightPacketHandlers.java │ ├── DenizenPacketHandlerPacketHandlers.java │ ├── DisguisePacketHandlers.java │ ├── EntityMetadataPacketHandlers.java │ ├── FakeBlocksPacketHandlers.java │ ├── FakeEquipmentPacketHandlers.java │ ├── FakePlayerPacketHandlers.java │ ├── HiddenEntitiesPacketHandlers.java │ ├── HideParticlesPacketHandlers.java │ ├── PlayerHearsSoundEventPacketHandlers.java │ └── TablistUpdateEventPacketHandlers.java └── packets/ ├── PacketInResourcePackStatusImpl.java ├── PacketInSteerVehicleImpl.java └── PacketOutChatImpl.java ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Disable LF normalization for all files * -text ================================================ FILE: .github/FUNDING.yml ================================================ github: mcmonkey4eva ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.md ================================================ --- name: Bug Report about: Describe an issue with Denizen not working as expected. DO NOT POST HERE UNLESS SOMEONE TOLD YOU TO ON DISCORD. --- The output of `/version` on my server is: **paste here** The output of `/version denizen` on my server is: **paste here** (If relevant) A link to a paste of a script demonstrating the issue: **paste here** The issue is: **Describe your issue in full here** ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.md ================================================ --- name: Feature Request about: Suggest something new to add. DO NOT POST HERE UNLESS SOMEONE TOLD YOU TO ON DISCORD. --- ================================================ FILE: .github/ISSUE_TEMPLATE/i-m-having-trouble.md ================================================ --- name: I'm Having Trouble about: Make an issue post that seems to be trouble on your end (not a bug in Denizen itself) - ASK ON DISCORD https://discord.gg/Q6pZGSR --- **STOP** You shouldn't be on GitHub issues! Ask for help on Discord: https://discord.gg/Q6pZGSR ================================================ FILE: .gitignore ================================================ # Maven target/ dependency-reduced-pom.xml # IntelliJ .idea/ *.iml # Temporary/etc. *.bak *.exe .DS_Store ================================================ FILE: CONTRIBUTING.md ================================================ Contribution to Denizen ----------------------- Please talk to us on Discord @ https://discord.gg/Q6pZGSR prior to contributing. ## Signing Please sign [the Contributor License Agreement](https://cla-assistant.io/DenizenScript/Denizen-For-Bukkit). ## Pull Requests For pull requests: - You MUST: own the code you submit OR it is free/open/safe to use, EG it is in the public domain. Code gathered from within any open source DenizenScript project is valid to include here as well. - If your code is under any pre-existing license, you MUST note it in the pull request. - Any and all code you submit is subject to the mini-license below. - In general, you should confirm your PR is functional in any ways that it may vary. - EG if your code adds an NMS call, it should be tested across multiple game versions. - USUALLY, your pull request should fix an open issue or feature request made in a Discord thread. - If there is no issue or thread for it, please open a thread. - If issues or threads for it have been closed with a refusal statement, ensure you want to be making a PR at all before bothering with it. Generally, refused requests means PRs are also refused. - The exception to this is when an issue is only partially related to what you're doing, or you believe in good faith that the issue was refused on grounds made irrelevant by your adaptation of it. - In these cases, please open a new issue or thread. - Do NOT click the `Resolve conversation` button on any PR comments. Ever. ## Code Style / Formatting Match the general format/style of existing code within the project. For the most part, this is standard Oracle Java code conventions. As a particular difference from some standards, there must always be a newline after `}`. ## Mini-license pre-warning By contributing to the project, you give up all rights to your contribution\*. If you later decide you don't want us using your code - you may make a polite request and it will be treated as such, but that is the extent of your abilities. \* This does not include your rights to continue making use of any involved code yourself, which you of course may continue to do. You give up specifically your rights to the contribution *within this project*. Or to put it another way: your rights to the specific copy of the contribution that is now contained within this project, as specifically opposed to ideas and/or expressions thereof within the code or other work contributed, which you remain free to do with as you wish (excluding actions that conflict with our ownership of the copy given to us). ### You agree by contributing: - That you have read and agree to this document. - To not attempt to "revoke rights to your code" or any similar action. - That you have the right to publicly contribute any assets/code given. (IE, no contributing someone else's code without their permission) - That the code submitted is either your own work, dedicated now to this project, OR it is under a license specified directly in the contribution. ================================================ FILE: LICENSE.txt ================================================ The MIT License (MIT) Copyright (c) 2019-2026 The Denizen Script Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ The Denizen Scripting Language - Spigot Impl -------------------------------------------- An implementation of the Denizen Scripting Language for Spigot servers, with strong Citizens interlinks to emphasize the power of using Denizen with NPCs! **Version 1.3.2**: Compatible with Spigot 1.17.1, 1.18.2, 1.19.4, 1.20.6, 1.21.11, and 26.1.2! **Learn about Denizen from the Beginner's guide:** https://guide.denizenscript.com/guides/background/index.html #### Download Links: - **Release builds**: https://ci.citizensnpcs.co/job/Denizen/ - **Developmental builds**: https://ci.citizensnpcs.co/job/Denizen_Developmental/ - **SpigotMC - VERY SLOW releases**: https://www.spigotmc.org/resources/denizen.21039/ #### Need help using Denizen? Try one of these places: - **Discord** - chat room (Modern, strongly recommended): https://discord.gg/Q6pZGSR - **Denizen Home Page** - a link directory (Modern): https://denizenscript.com/ - **Forum and script sharing** (Modern): https://forum.denizenscript.com/ - **Meta Documentation** - command/tag/event/etc. search (Modern): https://meta.denizenscript.com/ - **Beginner's Guide** - text form (Modern): https://guide.denizenscript.com/ #### Also check out: - **Citizens2 (NPC support)**: https://github.com/CitizensDev/Citizens2/ - **Depenizen (Other plugin support)**: https://github.com/DenizenScript/Depenizen - **dDiscordBot (Adds a Discord bot to Denizen)**: https://github.com/DenizenScript/dDiscordBot - **DenizenCore (Our core, needed for building)**: https://github.com/DenizenScript/Denizen-Core - **DenizenVSCode (extension for writing Denizen scripts in VS Code)**: https://github.com/DenizenScript/DenizenVSCode ### Building - Built against JDK 17, using maven `pom.xml` as project file. - Requires building all listed versions of Spigot via Spigot BuildTools: https://www.spigotmc.org/wiki/buildtools/ ### Maven ```xml citizens-repo https://maven.citizensnpcs.co/repo com.denizenscript denizen 1.3.2-SNAPSHOT jar provided * * ``` ### Licensing pre-note: This is an open source project, provided entirely freely, for everyone to use and contribute to. If you make any changes that could benefit the community as a whole, please contribute upstream. ### The short of the license is: You can do basically whatever you want, except you may not hold any developer liable for what you do with the software. ### Previous License Copyright (C) 2012-2013 Aufdemrand, All Rights Reserved. Copyright (C) 2013-2019 The Denizen Script Team, All Rights Reserved. ### The long version of the license follows: The MIT License (MIT) Copyright (c) 2019-2026 The Denizen Script Team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: dist/pom.xml ================================================ com.denizenscript denizen-parent 1.3.2-SNAPSHOT 4.0.0 denizen-dist UTF-8 Unknown CUSTOM com.denizenscript denizencore 1.91.0-SNAPSHOT compile com.denizenscript denizen ${project.parent.version} compile com.denizenscript denizen-v1_17 ${project.parent.version} compile com.denizenscript denizen-v1_18 ${project.parent.version} compile com.denizenscript denizen-v1_19 ${project.parent.version} compile com.denizenscript denizen-v1_20 ${project.parent.version} compile com.denizenscript denizen-v1_21 ${project.parent.version} compile com.denizenscript denizen-v26_1 ${project.parent.version} compile com.denizenscript denizen-paper ${project.parent.version} compile src/main/java false ${basedir}/src/main/resources *.mid true ${basedir}/src/main/resources *.yml *.dsc org.apache.maven.plugins maven-shade-plugin 3.4.1 package shade true com.denizenscript:denizencore ** com.denizenscript:denizen ** org.json:json ** com.denizenscript:denizen-v** ** com.denizenscript:denizen-paper ** com.denizenscript:denizen-nmshandler ** net.kyori:adventure-nbt ** com.freneticllc com.denizenscript.shaded.com.freneticllc org.json com.denizenscript.shaded.org.json org.ow2.asm com.denizenscript.shaded.org.ow2.asm org.objectweb com.denizenscript.shaded.org.objectweb org.apache com.denizenscript.shaded.org.apache net.kyori.option com.denizenscript.shaded.net.kyori.option net.kyori.adventure.nbt com.denizenscript.shaded.net.adventure.nbt org.apache.maven.plugins maven-jar-plugin 3.3.0 Denizen-${DENIZEN_VERSION}-b${BUILD_NUMBER}-${BUILD_CLASS} ../target true Denizen/lib/ org.apache.maven.plugins maven-compiler-plugin 3.10.1 16 16 ================================================ FILE: dist/src/main/java/com/denizenscript/denizen/dist/Dist.java ================================================ package com.denizenscript.denizen.dist; public class Dist { // Empty class just to make things work. } ================================================ FILE: paper/pom.xml ================================================ 4.0.0 com.denizenscript denizen-paper 1.3.2-SNAPSHOT papermc https://repo.papermc.io/repository/maven-public/ com.denizenscript denizen ${project.version} compile io.papermc.paper paper-api [26.1.2.build,) provided net.citizensnpcs citizens-main 2.0.42-SNAPSHOT jar provided * * org.apache.maven.plugins maven-compiler-plugin 3.10.1 16 16 ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/PaperEventHelpers.java ================================================ package com.denizenscript.denizen.paper; import com.denizenscript.denizen.objects.InventoryTag; import com.denizenscript.denizen.scripts.containers.core.InventoryScriptContainer; import com.denizenscript.denizen.utilities.VanillaTagHelper; import com.denizenscript.denizen.utilities.inventory.InventoryViewUtil; import com.denizenscript.denizencore.objects.core.ScriptTag; import com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent; import io.papermc.paper.event.server.ServerResourcesReloadedEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; public class PaperEventHelpers implements Listener { @EventHandler public void onRecipeBookClick(PlayerRecipeBookClickEvent event) { InventoryTag inventory = InventoryTag.mirrorBukkitInventory(InventoryViewUtil.getTopInventory(event.getPlayer().getOpenInventory())); if (inventory.getIdHolder() instanceof ScriptTag) { if (((InventoryScriptContainer) ((ScriptTag) inventory.getIdHolder()).getContainer()).gui) { event.setCancelled(true); } } } @EventHandler(priority = EventPriority.LOWEST) public void onServerResourcesReloaded(ServerResourcesReloadedEvent event) { VanillaTagHelper.loadTagsCache(); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/PaperModule.java ================================================ package com.denizenscript.denizen.paper; import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.nms.interfaces.packets.PacketOutChat; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.paper.datacomponents.ComponentAdaptersRegistry; import com.denizenscript.denizen.paper.events.*; import com.denizenscript.denizen.paper.properties.*; import com.denizenscript.denizen.paper.tags.PaperTagBase; import com.denizenscript.denizen.paper.utilities.PaperAPIToolsImpl; import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; public class PaperModule { public static void init() { Debug.log("Loading Paper support module..."); ScriptEvent.notNameParts.add(0, "PaperImpl"); // Events ScriptEvent.registerScriptEvent(AnvilBlockDamagedScriptEvent.class); ScriptEvent.registerScriptEvent(AreaEnterExitScriptEventPaperImpl.class); if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_18)) { ScriptEvent.registerScriptEvent(BellRingScriptEvent.class); } ScriptEvent.registerScriptEvent(BlockPreDispenseScriptEvent.class); ScriptEvent.registerScriptEvent(CreeperIgnitesScriptEvent.class); ScriptEvent.registerScriptEvent(DragonEggFormScriptEvent.class); ScriptEvent.registerScriptEvent(EntityAddToWorldScriptEvent.class); ScriptEvent.registerScriptEvent(EntityKnocksbackEntityScriptEvent.class); ScriptEvent.registerScriptEvent(EntityLoadCrossbowScriptEvent.class); ScriptEvent.registerScriptEvent(EntityPathfindScriptEvent.class); ScriptEvent.registerScriptEvent(EntityRemoveFromWorldScriptEvent.class); ScriptEvent.registerScriptEvent(EntityStepsOnScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { ScriptEvent.registerScriptEvent(EntityTeleportedByPortalScriptEvent.class); } ScriptEvent.registerScriptEvent(ExperienceOrbMergeScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerAbsorbsExperienceScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerBeaconEffectScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { ScriptEvent.registerScriptEvent(PlayerChangesFramedItemScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerChoosesArrowScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerChunkUnloadScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerClicksFakeEntityScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerClicksInRecipeBookScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerClientOptionsChangeScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerCompletesAdvancementScriptEventPaperImpl.class); ScriptEvent.registerScriptEvent(PlayerDeepSleepScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerElytraBoostScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerEquipsArmorScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerGrantedAdvancementCriterionScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { ScriptEvent.registerScriptEvent(PlayerInventorySlotChangeScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerItemTakesDamageScriptEventPaperImpl.class); ScriptEvent.registerScriptEvent(PlayerJumpsScriptEventPaperImpl.class); ScriptEvent.registerScriptEvent(PlayerLecternPageChangeScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerLoomPatternSelectScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerNamesEntityScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { ScriptEvent.registerScriptEvent(PlayerOpenSignScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerPreparesGrindstoneCraftScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerQuitsScriptEventPaperImpl.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { ScriptEvent.registerScriptEvent(PlayerRaiseLowerItemScriptEventPaperImpl.class); } if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { ScriptEvent.registerScriptEvent(PlayerReceivesLinksScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerSelectsStonecutterRecipeScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerSetSpawnScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { ScriptEvent.registerScriptEvent(PlayerShieldDisableScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerSpectatesEntityScriptEvent.class); ScriptEvent.registerScriptEvent(PlayerStopsSpectatingScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { ScriptEvent.registerScriptEvent(PlayerTracksEntityScriptEvent.class); } ScriptEvent.registerScriptEvent(PlayerTradesWithMerchantScriptEvent.class); ScriptEvent.registerScriptEvent(PreEntitySpawnScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { ScriptEvent.registerScriptEvent(PrePlayerAttackEntityScriptEvent.class); } ScriptEvent.registerScriptEvent(ProjectileCollideScriptEvent.class); ScriptEvent.registerScriptEvent(ServerListPingScriptEventPaperImpl.class); ScriptEvent.registerScriptEvent(ServerResourcesReloadedScriptEvent.class); ScriptEvent.registerScriptEvent(SkeletonHorseTrapScriptEvent.class); ScriptEvent.registerScriptEvent(TargetBlockHitScriptEvent.class); if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_18)) { ScriptEvent.registerScriptEvent(TNTPrimesScriptEvent.class); } ScriptEvent.registerScriptEvent(UnknownCommandScriptEvent.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { ScriptEvent.registerScriptEvent(VaultChangesStateScriptEvent.class); } if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { ScriptEvent.registerScriptEvent(WardenChangesAngerLevelScriptEvent.class); } ScriptEvent.registerScriptEvent(WorldGameRuleChangeScriptEvent.class); // Properties PropertyParser.registerProperty(EntityArmsRaised.class, EntityTag.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { PropertyParser.registerProperty(EntityAutoExpire.class, EntityTag.class); } PropertyParser.registerProperty(EntityBodyStingers.class, EntityTag.class); PropertyParser.registerProperty(EntityCarryingEgg.class, EntityTag.class); PropertyParser.registerProperty(EntityCanTick.class, EntityTag.class); PropertyParser.registerProperty(EntityDrinkingPotion.class, EntityTag.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { PropertyParser.registerProperty(EntityEggLayTime.class, EntityTag.class); PropertyParser.registerProperty(EntityFriction.class, EntityTag.class); } PropertyParser.registerProperty(EntityLeftHanded.class, EntityTag.class); PropertyParser.registerProperty(EntityReputation.class, EntityTag.class); PropertyParser.registerProperty(EntityShouldBurn.class, EntityTag.class); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { PropertyParser.registerProperty(EntitySneaking.class, EntityTag.class); } PropertyParser.registerProperty(EntityWitherInvulnerable.class, EntityTag.class); PropertyParser.registerProperty(ItemArmorStand.class, ItemTag.class); // Components system if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { PropertyParser.registerProperty(ItemRemovedComponents.class, ItemTag.class); ComponentAdaptersRegistry.register(); } // Paper object extensions PaperElementExtensions.register(); PaperEntityExtensions.register(); PaperItemExtensions.register(); PaperPlayerExtensions.register(); PaperWorldExtensions.register(); // Paper Tags new PaperTagBase(); // Other helpers Bukkit.getPluginManager().registerEvents(new PaperEventHelpers(), Denizen.getInstance()); PaperAPITools.instance = new PaperAPIToolsImpl(); PacketOutChat.convertComponentToJsonString = (o) -> componentToJson((Component) o); } public static Component parseFormattedText(String text, ChatColor baseColor) { if (text == null) { return null; } try { return jsonToComponent(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(text, baseColor))); } catch (Exception ex) { Debug.verboseLog("Failed to parse formatted text: " + text.replace(ChatColor.COLOR_CHAR, '&')); throw ex; } } public static String stringifyComponent(Component component) { if (component == null) { return null; } return FormattedTextHelper.stringify(FormattedTextHelper.parseJson(componentToJson(component))); } public static Component jsonToComponent(String json) { if (json == null) { return null; } try { return GsonComponentSerializer.gson().deserialize(json); } catch (Exception ex) { Debug.verboseLog("Failed to parse json to component: " + json); throw ex; } } public static String componentToJson(Component component) { if (component == null) { return null; } return GsonComponentSerializer.gson().serialize(component); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/ComponentAdaptersRegistry.java ================================================ package com.denizenscript.denizen.paper.datacomponents; public class ComponentAdaptersRegistry { public static void register() { DataComponentAdapter.register(new FoodAdapter()); DataComponentAdapter.register(new GliderAdapter()); DataComponentAdapter.register(new ItemModelAdapter()); DataComponentAdapter.register(new MaxDurabilityAdapter()); DataComponentAdapter.register(new MaxStackSizeAdapter()); DataComponentAdapter.register(new RarityAdapter()); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/DataComponentAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.properties.item.ItemComponentsPatch; import com.denizenscript.denizen.objects.properties.item.ItemProperty; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.utilities.CoreUtilities; import io.papermc.paper.datacomponent.DataComponentType; import org.bukkit.Registry; import org.bukkit.inventory.ItemStack; import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; public abstract class DataComponentAdapter { // <--[language] // @name Item Components // @group Minecraft Logic // @description // Minecraft item components (see <@link url https://minecraft.wiki/w/Data_component_format>) are managed as follows: // Each item type has a default set of component values; a food item will have food components by default, a tool item will have tool components by default, etc. // Different items can override their type's default components, either by setting values that weren't there previously (e.g. making an inedible item edible), or by removing values that are there by default (e.g. making a shield item that can't block). // Items' overrides can later be reset, making them use their type's default values again. // // In Denizen, different item components are represented by item properties. // These properties allow both setting a component override on an item, and clearing/resetting it by providing no input. // Item properties' name will generally match their respective item component's name, but not always! // Due to this, features that take item component names as input (such as <@link tag ItemTag.is_overridden>) accept both Minecraft component names and Denizen property names. // // Here is an example of applying all of this in a script: // // # We define a default apple item // - define apple // # We remove the apple's "food" component, making eating it restore no food points (it is still consumable due to the "consumable" component). // - adjust def:apple remove_component:food // # This check will pass, as the apple's "food" component is overridden to have no value. // - if <[apple].is_overridden[food]>: // - narrate "The apple has a modified food component! It will behave differently to a normal apple." // # We reset the apple item's food component by adjusting with no value, making it a normal apple. // - adjust def:apple food: // // --> public static final Map COMPONENTS_BY_PROPERTY = new HashMap<>(); public static final String[] EMPTY_STRING_ARRAY = new String[0]; public static DataComponentType getComponentType(String name) { String nameLower = CoreUtilities.toLowerCase(name); DataComponentType componentType = Registry.DATA_COMPONENT_TYPE.get(Utilities.parseNamespacedKey(nameLower)); if (componentType == null) { componentType = COMPONENTS_BY_PROPERTY.get(nameLower); } return componentType; } public static void register(DataComponentAdapter adapter) { DataComponentAdapter.Property.currentlyRegisteringComponentAdapter = adapter; PropertyParser.registerPropertyGetter( item -> !item.getItemStack().isEmpty() ? adapter.new Property(item) : null, ItemTag.class, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, DataComponentAdapter.Property.class); DataComponentAdapter.Property.currentlyRegisteringComponentAdapter = null; String componentName = adapter.componentType.key().asMinimalString(); ItemComponentsPatch.registerHandledComponent(componentName); if (!adapter.name.equals(componentName)) { COMPONENTS_BY_PROPERTY.put(adapter.name, adapter.componentType); } } static { // <--[tag] // @attribute ]> // @returns ElementTag(Boolean) // @description // Returns whether an item has a specific item component type overridden, see <@link language Item Components>. // --> ItemTag.tagProcessor.registerTag(ElementTag.class, ElementTag.class, "is_overridden", (attribute, object, param) -> { DataComponentType componentType = getComponentType(param.asString()); if (componentType == null) { attribute.echoError("Invalid type specified, must be a valid item component type or property name."); return null; } return new ElementTag(object.getItemStack().isDataOverridden(componentType)); }); } public final C componentType; public final Class denizenType; public final String name; public DataComponentAdapter(C componentType, Class denizenType, String name) { this.componentType = componentType; this.denizenType = denizenType; this.name = name; } public abstract D getValue(ItemStack item); public abstract void setValue(ItemStack item, D value, Mechanism mechanism); public boolean isDefaultValue(D value) { return false; } public static abstract class NonValued extends DataComponentAdapter { public NonValued(DataComponentType.NonValued componentType, String name) { super(componentType, ElementTag.class, name); } @Override public ElementTag getValue(ItemStack item) { return new ElementTag(item.hasData(componentType)); } @Override public void setValue(ItemStack item, ElementTag value, Mechanism mechanism) { if (!mechanism.requireBoolean()) { return; } if (value.asBoolean()) { item.setData(componentType); } else { item.unsetData(componentType); } } // Overridden and false = removed, managed by ItemTag.removed_components @Override public boolean isDefaultValue(ElementTag value) { return !value.asBoolean(); } } public static abstract class Valued extends DataComponentAdapter> { public static void setIfValid(Consumer setter, MapTag data, String key, Class objectType, Predicate checker, Function converter, String type, Mechanism mechanism) { D value = data.getObjectAs(key, objectType, mechanism.context); if (value == null) { return; } T converted; if ((checker != null && !checker.test(value)) || (converted = converter.apply(value)) == null) { mechanism.echoError("Invalid '" + key + "' specified: must be a " + type + '.'); return; } setter.accept(converted); } public Valued(Class denizenType, DataComponentType.Valued

componentType, String name) { super(componentType, denizenType, name); } public abstract D toDenizen(P value); public abstract P fromDenizen(D value, Mechanism mechanism); @Override public D getValue(ItemStack item) { P data = item.getData(componentType); return data != null ? toDenizen(data) : null; } @Override public void setValue(ItemStack item, D value, Mechanism mechanism) { P converted = fromDenizen(value, mechanism); if (converted != null) { item.setData(componentType, converted); } } } public class Property extends ItemProperty { private static DataComponentAdapter currentlyRegisteringComponentAdapter; public Property(ItemTag item) { this.object = item; } @Override public D getPropertyValue() { return getValue(getItemStack()); } @Override public D getPropertyValueNoDefault() { if (!getItemStack().isDataOverridden(componentType)) { return null; } return super.getPropertyValueNoDefault(); } @Override public boolean isDefaultValue(D value) { return DataComponentAdapter.this.isDefaultValue(value); } @Override public void setPropertyValue(D value, Mechanism mechanism) { if (value == null) { getItemStack().resetData(componentType); return; } setValue(getItemStack(), value, mechanism); } @Override public String getPropertyId() { return name; } public static void register() { autoRegisterNullable(currentlyRegisteringComponentAdapter.name, DataComponentAdapter.Property.class, currentlyRegisteringComponentAdapter.denizenType, false); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/FoodAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.item.FoodProperties; public class FoodAdapter extends DataComponentAdapter.Valued { // <--[property] // @object ItemTag // @name food // @input MapTag // @description // Controls an item's food <@link language Item Components>. // The map includes keys: // - "nutrition", ElementTag(Number) representing the amount of food points restored by this item. // - "saturation", ElementTag(Decimal) representing the amount of saturation points restored by this item. // - "can_always_eat", ElementTag(Boolean) controlling whether the item can always be eaten, even if the player isn't hungry. // @mechanism // Provide no input to reset the item to its default value. // --> public FoodAdapter() { super(MapTag.class, DataComponentTypes.FOOD, "food"); } @Override public MapTag toDenizen(FoodProperties value) { MapTag foodData = new MapTag(); foodData.putObject("nutrition", new ElementTag(value.nutrition())); foodData.putObject("saturation", new ElementTag(value.saturation())); foodData.putObject("can_always_eat", new ElementTag(value.canAlwaysEat())); return foodData; } @Override public FoodProperties fromDenizen(MapTag value, Mechanism mechanism) { FoodProperties.Builder builder = FoodProperties.food(); setIfValid(builder::nutrition, value, "nutrition", ElementTag.class, ElementTag::isInt, ElementTag::asInt, "number", mechanism); setIfValid(builder::saturation, value, "saturation", ElementTag.class, ElementTag::isFloat, ElementTag::asFloat, "decimal number", mechanism); setIfValid(builder::canAlwaysEat, value, "can_always_eat", ElementTag.class, ElementTag::isBoolean, ElementTag::asBoolean, "boolean", mechanism); return builder.build(); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/GliderAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import io.papermc.paper.datacomponent.DataComponentTypes; public class GliderAdapter extends DataComponentAdapter.NonValued { // <--[property] // @object ItemTag // @name glider // @input ElementTag(Boolean) // @description // Controls whether an item can be used to glide when equipped (like elytras by default), see <@link language Item Components>. // @mechanism // Provide no input to reset the item to its default value. // --> public GliderAdapter() { super(DataComponentTypes.GLIDER, "glider"); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/ItemModelAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.datacomponent.DataComponentTypes; import net.kyori.adventure.key.Key; public class ItemModelAdapter extends DataComponentAdapter.Valued { // <--[property] // @object ItemTag // @name item_model // @input ElementTag // @description // Controls an item's model <@link language Item Components> in namespaced key format. // The default namespace is "minecraft", so for example an input of "stone" becomes "minecraft:stone", and will set the item model to a stone block. // This can also be used to display item models from your own custom resource packs. // @mechanism // Provide no input to reset the item to its default value. // --> public ItemModelAdapter() { super(ElementTag.class, DataComponentTypes.ITEM_MODEL, "item_model"); } @Override public ElementTag toDenizen(Key value) { return new ElementTag(value.asMinimalString(), true); } @Override public Key fromDenizen(ElementTag value, Mechanism mechanism) { return Utilities.parseNamespacedKey(value.asString()); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxDurabilityAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.datacomponent.DataComponentTypes; public class MaxDurabilityAdapter extends DataComponentAdapter.Valued { // <--[property] // @object ItemTag // @name max_durability // @input ElementTag(Number) // @description // Controls an item's max durability <@link language Item Components>. // @mechanism // Provide no input to reset the item to its default value. // --> public MaxDurabilityAdapter() { super(ElementTag.class, DataComponentTypes.MAX_DAMAGE, "max_durability"); } @Override public ElementTag toDenizen(Integer value) { return new ElementTag(value); } @Override public Integer fromDenizen(ElementTag value, Mechanism mechanism) { return mechanism.requireInteger() ? value.asInt() : null; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/MaxStackSizeAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.datacomponent.DataComponentTypes; public class MaxStackSizeAdapter extends DataComponentAdapter.Valued { // <--[property] // @object ItemTag // @name max_stack_size // @input ElementTag(Number) // @description // Controls an item's max stack size <@link language Item Components>. // @mechanism // Provide no input to reset the item to its default value. // --> public MaxStackSizeAdapter() { super(ElementTag.class, DataComponentTypes.MAX_STACK_SIZE, "max_stack_size"); } @Override public ElementTag toDenizen(Integer value) { return new ElementTag(value); } @Override public Integer fromDenizen(ElementTag value, Mechanism mechanism) { return mechanism.requireInteger() ? value.asInt() : null; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/datacomponents/RarityAdapter.java ================================================ package com.denizenscript.denizen.paper.datacomponents; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.datacomponent.DataComponentTypes; import org.bukkit.inventory.ItemRarity; public class RarityAdapter extends DataComponentAdapter.Valued { // <--[property] // @object ItemTag // @name rarity // @input ElementTag // @description // Controls an item's rarity <@link language Item Components>. // See <@link url https://jd.papermc.io/paper/org/bukkit/inventory/ItemRarity.html> for valid rarity values. // @mechanism // Provide no input to reset the item to its default value. // --> public RarityAdapter() { super(ElementTag.class, DataComponentTypes.RARITY, "rarity"); } @Override public ElementTag toDenizen(ItemRarity value) { return new ElementTag(value); } @Override public ItemRarity fromDenizen(ElementTag value, Mechanism mechanism) { return mechanism.requireEnum(ItemRarity.class) ? value.asEnum(ItemRarity.class) : null; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/AnvilBlockDamagedScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.InventoryTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizen.utilities.inventory.InventoryViewUtil; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.block.AnvilDamagedEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class AnvilBlockDamagedScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // anvil block damaged|breaks // // @Group Paper // // @Location true // // @Plugin Paper // // @Cancellable true // // @Switch state: to only process the event if the anvil's new damage state matches the specified state. // // @Triggers when an anvil is damaged from being used. // // @Context // returns an ElementTag of the anvil's new damage state. Refer to <@link url https://jd.papermc.io/paper/1.19/com/destroystokyo/paper/event/block/AnvilDamagedEvent.DamageState.html>. // returns an ElementTag(Boolean) that signifies whether the anvil will break. // returns the InventoryTag of the anvil's inventory. // // @Determine // "STATE:" to set the anvil's new damage state. // "BREAK:" to set weather the anvil will break. // --> public AnvilBlockDamagedScriptEvent() { registerCouldMatcher("anvil block damaged|breaks"); registerSwitches("state"); this.registerOptionalDetermination("state", ElementTag.class, (evt, context, state) -> { if (state.matchesEnum(AnvilDamagedEvent.DamageState.class)) { evt.event.setDamageState(state.asEnum(AnvilDamagedEvent.DamageState.class)); return true; } return false; }); this.registerOptionalDetermination("break", ElementTag.class, (evt, context, value) -> { if (value.isBoolean()) { evt.event.setBreaking(value.asBoolean()); return true; } return false; }); } public AnvilDamagedEvent event; @Override public boolean matches(ScriptPath path) { if (path.eventArgLowerAt(2).equals("breaks") && !event.isBreaking()) { return false; } if (!runInCheck(path, event.getInventory().getLocation())) { return false; } if (!runGenericSwitchCheck(path, "state", event.getDamageState().name())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "state" -> new ElementTag(event.getDamageState()); case "inventory" -> InventoryTag.mirrorBukkitInventory(event.getInventory()); case "break" -> new ElementTag(event.isBreaking()); default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(InventoryViewUtil.getPlayer(event.getView())); } @EventHandler public void onAnvilDamaged(AnvilDamagedEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/AreaEnterExitScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.entity.AreaEnterExitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.event.entity.EntityMoveEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDeathEvent; public class AreaEnterExitScriptEventPaperImpl extends AreaEnterExitScriptEvent { @Override public ObjectTag getContext(String name) { if (name.equals("cause") && currentEvent instanceof EntityMoveEvent) { return new ElementTag("WALK"); } else if (name.equals("from") && currentEvent instanceof EntityMoveEvent) { return new LocationTag(((EntityMoveEvent) currentEvent).getFrom()); } return super.getContext(name); } @Override public void registerCorrectClass() { if (onlyTrackPlayers) { initListener(new SpigotListeners()); } else { initListener(new PaperListeners()); } } public class PaperListeners extends SpigotListeners { @EventHandler public void onEntityMove(EntityMoveEvent event) { if (event.getEntity().isValid()) { processNewPosition(new EntityTag(event.getEntity()), event.getTo(), event); } } @EventHandler public void onEntityDeath(EntityDeathEvent event) { processNewPosition(new EntityTag(event.getEntity()), null, event); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/BellRingScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.block.BellRingEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class BellRingScriptEvent extends BukkitScriptEvent implements Listener { public BellRingScriptEvent() { registerCouldMatcher("bell rings"); } public BellRingEvent event; public LocationTag location; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getEntity()); } @Override public ObjectTag getContext(String name) { switch (name) { case "entity": return event.getEntity() == null ? null : new EntityTag(event.getEntity()).getDenizenObject(); case "location": return location; } return super.getContext(name); } @EventHandler public void bellRingEvent(BellRingEvent event) { this.event = event; location = new LocationTag(event.getBlock().getLocation()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/BlockPreDispenseScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.event.block.BlockPreDispenseEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class BlockPreDispenseScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // tries to dispense // // @Group Block // // @Location true // // @Cancellable true // // @Triggers before a block dispenses an item. // This event fires before the dispenser fully processes a drop, allowing access to the dispensing slot and cancellation of sound effects. // // @Context // returns the LocationTag of the dispenser. // returns the ItemTag of the item about to be dispensed. // returns a ElementTag(Number) of the slot that will be dispensed from. // // --> public BlockPreDispenseScriptEvent() { registerCouldMatcher(" tries to dispense "); } public BlockPreDispenseEvent event; public ItemTag item; public LocationTag location; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } if (!path.tryArgObject(0, location)) { return false; } if (!path.tryArgObject(4, item)) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "item" -> item; case "location" -> location; case "slot" -> new ElementTag(event.getSlot() + 1); default -> super.getContext(name); }; } @EventHandler public void onBlockPreDispense(BlockPreDispenseEvent event) { this.event = event; item = new ItemTag(event.getItemStack()); location = new LocationTag(event.getBlock().getLocation()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/CreeperIgnitesScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.ObjectTag; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import com.destroystokyo.paper.event.entity.CreeperIgniteEvent; public class CreeperIgnitesScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // creeper ignites // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Triggers when a creeper is ignited by flint and steel, or by certain plugin-based activations. // // @Context // returns the EntityTag of the creeper. // returns true if the creeper is ignited, or false if not. NOTE: In most cases, this will return true. // // --> public CreeperIgnitesScriptEvent() { registerCouldMatcher("creeper ignites"); } public EntityTag entity; public CreeperIgniteEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, entity.getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { switch (name) { case "entity": return entity; case "ignited": return new ElementTag(event.isIgnited()); } return super.getContext(name); } @EventHandler public void onCreeperIgnites(CreeperIgniteEvent event) { entity = new EntityTag(event.getEntity()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/DragonEggFormScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import io.papermc.paper.event.block.DragonEggFormEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class DragonEggFormScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // dragon egg forms // // @Plugin Paper // // @Group Paper // // @Location true // // @Triggers when the ender dragon is defeated and the dragon egg forms. // // @Context // returns the EntityTag of the ender dragon right before it's removed. // returns the LocationTag of the dragon egg. // returns the LocationTag of the end portal. // returns an ElementTag(Boolean) of whether the dragon has been previously killed. // returns an ElementTag of the respawn phase. Valid values can be found at <@link url https://jd.papermc.io/paper/1.21.3/org/bukkit/boss/DragonBattle.RespawnPhase.html>. // returns a ListTag(EntityTag) of the healing end crystals. // returns a ListTag(EntityTag) of the respawn end crystals. // // --> public DragonEggFormScriptEvent() { registerCouldMatcher("dragon egg forms"); } public LocationTag location; public EntityTag entity; public DragonEggFormEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; case "location" -> location; case "end_portal_location" -> new LocationTag(event.getDragonBattle().getEndPortalLocation()); case "previously_killed" -> new ElementTag(event.getDragonBattle().hasBeenPreviouslyKilled()); case "respawn_phase" -> new ElementTag(event.getDragonBattle().getRespawnPhase()); case "healing_crystals" -> new ListTag(event.getDragonBattle().getHealingCrystals(), EntityTag::new); case "respawn_crystals" -> new ListTag(event.getDragonBattle().getRespawnCrystals(), EntityTag::new); default -> super.getContext(name); }; } @EventHandler public void onDragonEggForms(DragonEggFormEvent event) { location = new LocationTag(event.getBlock().getLocation()); entity = new EntityTag(event.getDragonBattle().getEnderDragon()); this.event = event; EntityTag.rememberEntity(entity.getBukkitEntity()); fire(event); EntityTag.forgetEntity(entity.getBukkitEntity()); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityAddToWorldScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityAddToWorldScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // added to world // // @Plugin Paper // // @Group Paper // // @Location true // // @Triggers any time an entity is added to the world for any reason, including chunks loading pre-existing entities. // // @Context // returns the EntityTag that will be added. Note that this entity will not necessarily be fully spawned yet, so usage will be limited. // returns the LocationTag that the entity will be added at. // // --> public EntityAddToWorldScriptEvent() { registerCouldMatcher(" added to world"); } public EntityTag entity; public LocationTag location; public EntityAddToWorldEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(0, entity)) { return false; } if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(null, null); } @Override public ObjectTag getContext(String name) { switch (name) { case "entity": return entity; case "location": return location; } return super.getContext(name); } @EventHandler public void onPreCreatureSpawn(EntityAddToWorldEvent event) { this.entity = new EntityTag(event.getEntity()); this.location = new LocationTag(event.getEntity().getLocation()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityKnocksbackEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityKnocksbackEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // knocks back // // @Location true // // @Warning this event may in some cases double-fire, requiring usage of the 'ratelimit' command (like 'ratelimit 1t') to prevent doubling actions. // // @Switch with: to only process the event when the item used to cause damage (in the damager's hand) is a specified item. // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when an entity is knocked back from the hit of another entity. // // @Context // returns the EntityTag that was knocked back. // returns the EntityTag of the one who knocked. // returns the knockback applied as a vector. // returns the cause of the knockback (only on MC 1.20+). Causes list: <@link url https://jd.papermc.io/paper/1.21.1/io/papermc/paper/event/entity/EntityKnockbackEvent.Cause.html> // // @Determine // LocationTag as a vector to change the acceleration applied. // // @Player when the damager or damaged entity is a player. Cannot be both. // // @NPC when the damager or damaged entity is an NPC. Cannot be both. // // --> public EntityKnocksbackEntityScriptEvent() { registerCouldMatcher(" knocks back "); registerSwitches("with"); } public EntityTag entity; public EntityTag hitBy; public ItemTag held; public EntityKnockbackByEntityEvent event; @Override public boolean matches(ScriptPath path) { String attacker = path.eventArgLowerAt(0); String target = path.eventArgLowerAt(3); if (!hitBy.tryAdvancedMatcher(attacker, path.context) || (!entity.tryAdvancedMatcher(target, path.context))) { return false; } if (!runInCheck(path, entity.getLocation())) { return false; } if (!runWithCheck(path, held)) { return false; } return super.matches(path); } @Override public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { if (determinationObj.canBeType(LocationTag.class)) { event.getAcceleration().copy(determinationObj.asType(LocationTag.class, getTagContext(path)).toVector()); return true; } return super.applyDetermination(path, determinationObj); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData( hitBy.isPlayer() ? hitBy.getDenizenPlayer() : entity.isPlayer() ? entity.getDenizenPlayer() : null, hitBy.isCitizensNPC() ? hitBy.getDenizenNPC() : entity.isCitizensNPC() ? entity.getDenizenNPC() : null); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity.getDenizenObject(); case "damager" -> hitBy.getDenizenObject(); case "acceleration" -> new LocationTag(event.getAcceleration()); case "cause" -> new ElementTag(event.getCause().name(), true); // TODO: once 1.20 is the minimum supported version, use the enum constructor default -> super.getContext(name); }; } @EventHandler public void onEntityKnockbackEntity(EntityKnockbackByEntityEvent event) { entity = new EntityTag(event.getEntity()); hitBy = new EntityTag(event.getHitBy()); held = hitBy.getItemInHand(); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityLoadCrossbowScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.entity.EntityLoadCrossbowEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityLoadCrossbowScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // loads crossbow // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Switch crossbow: to only process the event if the crossbow is a specified item. // // @Triggers when a living entity loads a crossbow with a projectile. // // @Context // returns the EntityTag that is loading the crossbow. // returns the ItemTag of the crossbow. // returns true if the loading will consume a projectile item, otherwise false. // returns "HAND" or "OFF_HAND" depending on which hand is holding the crossbow item. // // @Determine // "KEEP_ITEM" to keep the projectile item in the shooter's inventory. // // @Player when the entity is a player. // // @NPC when the entity is an NPC. // // --> public EntityLoadCrossbowScriptEvent() { registerCouldMatcher(" loads crossbow"); registerSwitches("crossbow"); this.registerTextDetermination("keep_item", (evt) -> { evt.event.setConsumeItem(false); }); } public EntityLoadCrossbowEvent event; public EntityTag entity; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(0, entity)) { return false; } if (!runWithCheck(path, new ItemTag(event.getCrossbow()), "crossbow")) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(entity); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity.getDenizenObject(); case "crossbow" -> new ItemTag(event.getCrossbow()); case "hand" -> new ElementTag(event.getHand()); case "consumes" -> new ElementTag(event.shouldConsumeItem()); default -> super.getContext(name); }; } @EventHandler public void onLoadCrossbow(EntityLoadCrossbowEvent event) { this.event = event; this.entity = new EntityTag(event.getEntity()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityPathfindScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.EntityPathfindEvent; import org.bukkit.entity.Entity; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityPathfindScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // pathfinds // // @Location true // @Switch to: to only process the event if the entity is pathfinding into a specified area. // @Switch at: to only process the event when the entity is pathfinding at a specified entity. // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when an entity starts pathfinding towards a location or entity. // // @Context // returns the EntityTag that is pathfinding. // returns the LocationTag that is being pathfound to. // returns the EntityTag that is being targeted, if any. // // @Player when the target entity is a player. // // @NPC when the target entity is an NPC. // // --> public EntityPathfindScriptEvent() { registerCouldMatcher(" pathfinds"); registerSwitches("to", "at"); } public EntityTag entity; public EntityTag target; public EntityPathfindEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(0, entity)) { return false; } if (!runInCheck(path, entity.getLocation())) { return false; } if (!runInCheck(path, event.getLoc(), "to")) { return false; } if (!path.tryObjectSwitch("at", target)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(target); } @Override public ObjectTag getContext(String name) { if (name.equals("entity")) { return entity.getDenizenObject(); } else if (name.equals("target") && target != null) { return target.getDenizenObject(); } else if (name.equals("location")) { return new LocationTag(event.getLoc()); } return super.getContext(name); } @EventHandler public void onEntityPathfind(EntityPathfindEvent event) { this.event = event; this.entity = new EntityTag(event.getEntity()); Entity target = event.getTargetEntity(); this.target = target != null ? new EntityTag(target) : null; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityRemoveFromWorldScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityRemoveFromWorldScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // removed from world // // @Plugin Paper // // @Group Paper // // @Location true // // @Triggers any time an entity is removed from the world for any reason, including chunks unloading. // // @Context // returns the EntityTag that will be removed. Note that this entity will not necessarily be fully spawned at time of firing, so usage will be limited. // // --> public EntityRemoveFromWorldScriptEvent() { registerCouldMatcher(" removed from world"); } public EntityTag entity; public EntityRemoveFromWorldEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(0, entity)) { return false; } if (!runInCheck(path, entity.getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(null, null); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; default -> super.getContext(name); }; } @EventHandler public void onPreCreatureSpawn(EntityRemoveFromWorldEvent event) { this.entity = new EntityTag(event.getEntity()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityStepsOnScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.MaterialTag; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizencore.objects.ObjectTag; import io.papermc.paper.event.entity.EntityMoveEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityStepsOnScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // entity steps on block // steps on // // @Location true // // @Group Paper // // @Plugin Paper // // @Warning This event may fire very rapidly. // // @Cancellable true // // @Triggers when a non-player entity steps onto a specific block material. For players, use <@link event player steps on block>. // // @Context // returns an EntityTag of the entity stepping onto the block. // returns a LocationTag of the block the entity is stepping on. // returns a LocationTag of where the entity was before stepping onto the block. // returns a LocationTag of where the entity is now. // // @Example // # Announce the name of the entity stepping on the block and the material of block. // on entity steps on block: // - announce " stepped on a !" // // @Example // # Announce the material of the block a sheep has stepped on. // on sheep steps on block: // - announce "A sheep has stepped on a !" // // @Example // # Announce that a sheep has stepped on a diamond block. // on sheep steps on diamond_block: // - announce "A sheep has stepped on a diamond block! Must be a wealthy sheep!" // --> public EntityStepsOnScriptEvent() { registerCouldMatcher(" steps on "); } public EntityMoveEvent event; public EntityTag entity; public LocationTag location; public MaterialTag material; @Override public boolean couldMatch(ScriptPath path) { if (!super.couldMatch(path)) { return false; } if (path.eventLower.startsWith("player")) { return false; } return true; } @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } if (!path.tryArgObject(0, entity)) { return false; } if (!path.tryArgObject(3, material)) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; case "location" -> location; case "previous_location" -> new LocationTag(event.getFrom()); case "new_location" -> new LocationTag(event.getTo()); default -> super.getContext(name); }; } @EventHandler public void entityStepsOnBlockEvent(EntityMoveEvent event) { if (!event.hasChangedBlock()) { return; } location = new LocationTag(event.getTo().clone().subtract(0.0, 0.05, 0.0)); if (!Utilities.isLocationYSafe(location)) { return; } material = new MaterialTag(location.getBlock()); entity = new EntityTag(event.getEntity()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/EntityTeleportedByPortalScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.WorldTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.event.entity.EntityPortalReadyEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class EntityTeleportedByPortalScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // teleported by portal // // @Switch to: to only process the event if the world the entity is being teleported to matches the specified WorldTag matcher. // @Switch portal_type: to only process the event if the portal's type matches the specified portal type. // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Triggers When an entity is about to be teleported by a portal (currently only fires for nether portals). // // @Context // returns an EntityTag of the entity being teleported. // returns a WorldTag of the world the entity is being teleported to. // returns an ElementTag of the portal's type. Will be one of <@link url https://jd.papermc.io/paper/1.19/org/bukkit/PortalType.html>. // // @Determine // "TARGET_WORLD:" to set the world the entity will be teleported to. // "REMOVE_TARGET_WORLD" to remove the target world. Should usually cancel the event instead of using this. // // --> public EntityTeleportedByPortalScriptEvent() { registerCouldMatcher(" teleported by portal"); registerSwitches("to", "portal_type"); this.registerDetermination("target_world", WorldTag.class, (evt, context, targetWorld) -> { evt.event.setTargetWorld(targetWorld.getWorld()); }); this.registerTextDetermination("remove_target_world", (evt) -> { evt.event.setTargetWorld(null); }); } EntityPortalReadyEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryObjectSwitch("to", event.getTargetWorld() == null ? null : new WorldTag(event.getTargetWorld()))) { return false; } if (!runGenericSwitchCheck(path, "portal_type", event.getPortalType().name())) { return false; } if (!path.tryArgObject(0, new EntityTag(event.getEntity()))) { return false; } if (!runInCheck(path, event.getEntity().getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> new EntityTag(event.getEntity()); case "target_world" -> event.getTargetWorld() != null ? new WorldTag(event.getTargetWorld()) : null; case "portal_type" -> new ElementTag(event.getPortalType()); default -> super.getContext(name); }; } @EventHandler public void onEntityPortalReady(EntityPortalReadyEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/ExperienceOrbMergeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.ExperienceOrbMergeEvent; import org.bukkit.entity.Entity; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class ExperienceOrbMergeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // experience orbs merge // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when two experience orbs are about to merge. // // @Context // returns the EntityTag of the orb that will absorb the other experience orb. // returns the EntityTag of the orb that will be removed and merged into the target. // // --> public ExperienceOrbMergeScriptEvent() { registerCouldMatcher("experience orbs merge"); } public ExperienceOrbMergeEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getMergeTarget().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(null, null); } @Override public ObjectTag getContext(String name) { if (name.equals("target")) { return new EntityTag(event.getMergeTarget()).getDenizenObject(); } else if (name.equals("source")) { return new EntityTag(event.getMergeSource()).getDenizenObject(); } return super.getContext(name); } @EventHandler public void experienceOrbsMerge(ExperienceOrbMergeEvent event) { this.event = event; Entity target = event.getMergeTarget(); EntityTag.rememberEntity(target); fire(event); EntityTag.forgetEntity(target); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerAbsorbsExperienceScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerPickupExperienceEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerAbsorbsExperienceScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player absorbs experience // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player is absorbing an experience orb. // // @Context // returns the EntityTag of the experience orb. // // @Player Always. // // --> public PlayerAbsorbsExperienceScriptEvent() { registerCouldMatcher("player absorbs experience"); } public PlayerPickupExperienceEvent event; @Override public boolean matches(ScriptEvent.ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { if (name.equals("entity")) { return new EntityTag(event.getExperienceOrb()); } return super.getContext(name); } @EventHandler public void absorbsExperience(PlayerPickupExperienceEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerBeaconEffectScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.properties.item.ItemPotion; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.block.BeaconEffectEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerBeaconEffectScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player beacon effect applied // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a beacon applies an effect to a player. // // @Context // returns the LocationTag of the beacon applying an effect. // returns a MapTag of the potion effect in <@link language Potion Effect Format>. // returns an ElementTag of the effect type. // returns an ElementTag(Boolean) of whether the beacon effect is the primary effect. // // @Determine // ElementTag to change the applied potion effect (in the same format as <@link tag EntityTag.list_effects>). // // @Player Always. // // --> public PlayerBeaconEffectScriptEvent() { registerCouldMatcher("player beacon effect applied"); } public BeaconEffectEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { try { event.setEffect(ItemPotion.parseLegacyEffectString(determinationObj.toString(), getTagContext(path))); return true; } catch (Exception e) { Debug.echoError(e); } return super.applyDetermination(path, determinationObj); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "location" -> new LocationTag(event.getBlock().getLocation()); case "effect" -> new ElementTag(ItemPotion.effectToLegacyString(event.getEffect(), null)); case "effect_data" -> ItemPotion.effectToMap(event.getEffect(), true); case "effect_type" -> new ElementTag(event.getEffect().getType().getName()); case "is_primary" -> new ElementTag(event.isPrimary()); default -> super.getContext(name); }; } @EventHandler public void beaconEffectEvent(BeaconEffectEvent event) { if (EntityTag.isNPC(event.getPlayer())) { return; } this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerChangesFramedItemScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerChangesFramedItemScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player changes framed // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player interacts with an item frame by adding, removing, or rotating the item held in it. // // @Switch frame: to only process the event if the item frame entity being matches the input. // @Switch action: to only process the event if the change matches the input. // // @Context // returns the EntityTag of the item frame. // returns the ItemTag of the item held in the item frame. // returns the ElementTag of the action being performed, based on <@link url https://jd.papermc.io/paper/1.20/io/papermc/paper/event/player/PlayerItemFrameChangeEvent.ItemFrameChangeAction.html> // // @Determine // "ITEM:" to change the item held by the item frame. If there is an item already in the frame, it will be replaced. To remove the item, set it to air. // // @Player Always. // --> public PlayerChangesFramedItemScriptEvent() { registerCouldMatcher("player changes framed "); registerSwitches("frame", "action"); this.registerDetermination("item", ItemTag.class, (evt, context, item) -> { evt.event.setItemStack(item.getItemStack()); }); } public ItemTag item; public EntityTag frame; public ElementTag action; public PlayerItemFrameChangeEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(3, item)) { return false; } if (!path.tryObjectSwitch("frame", frame)) { return false; } if (!path.tryObjectSwitch("action", action)) { return false; } if (!runInCheck(path, frame.getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "frame" -> frame; case "item" -> new ItemTag(event.getItemStack()); case "action" -> action; default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @EventHandler public void onPlayerChangesFramedItem(PlayerItemFrameChangeEvent event) { item = new ItemTag(event.getItemStack()); frame = new EntityTag(event.getItemFrame()); action = new ElementTag(event.getAction()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerChoosesArrowScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.*; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerReadyArrowEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerChoosesArrowScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player chooses arrow // // @Cancellable true // // @Group Player // // @Location true // // @Plugin Paper // // @Triggers when a player chooses an arrow to load a bow/crossbow. // // @Switch arrow: to only process the event when the players chosen arrow matches the input. // @Switch bow: to only process the event when the players bow matches the input. // // @Context // returns the ItemTag of the arrow that was chosen. // returns the ItemTag of the bow that is about to get loaded. // // @Player Always. // // @Example // # This example prevents using any arrow but spectral_arrows. // on player chooses arrow arrow:!spectral_arrow: // - determine cancelled // --> public PlayerChoosesArrowScriptEvent() { registerCouldMatcher("player chooses arrow"); registerSwitches("arrow", "bow"); } public PlayerReadyArrowEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryObjectSwitch("arrow", new ItemTag(event.getArrow()))) { return false; } if (!path.tryObjectSwitch("bow", new ItemTag(event.getBow()))) { return false; } if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { switch (name) { case "arrow": return new ItemTag(event.getArrow()); case "bow": return new ItemTag(event.getBow()); } return super.getContext(name); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(new PlayerTag(event.getPlayer()), null); } @Override public void cancellationChanged() { if (cancelled) { final Player p = event.getPlayer(); Bukkit.getScheduler().scheduleSyncDelayedTask(Denizen.getInstance(), p::updateInventory, 1); } super.cancellationChanged(); } @EventHandler public void onPlayerChoosesArrow(PlayerReadyArrowEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerChunkUnloadScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.ChunkTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.packet.PlayerChunkUnloadEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerChunkUnloadScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player receives chunk unload // // @Group Paper // // @Location true // // @Plugin Paper // // @Warning This event will fire *extremely* rapidly and almost guarantees lag. Use with maximum caution. // // @Triggers when a Player receives a chunk unload packet. // Should only be used for packet/clientside related stuff. Not intended for modifying server side. // Generally prefer <@link event chunk unloads> in most cases. // // @Context // returns a ChunkTag of the chunk being unloaded. // // @Player Always. // --> public PlayerChunkUnloadScriptEvent() { registerCouldMatcher("player receives chunk unload"); } public PlayerChunkUnloadEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "chunk" -> new ChunkTag(event.getChunk()); default -> super.getContext(name); }; } @EventHandler public void playerChunkUnloadEvent(PlayerChunkUnloadEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerClicksFakeEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerUseUnknownEntityEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerClicksFakeEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player (right|left) clicks fake entity // // @Location true // // @Plugin Paper // // @Group Paper // // @Triggers when a player clicks a fake entity, one that is only shown to the player and not tracked by the server. // // @Context // returns the EntityTag of the entity that was clicked. Note that this entity is not being tracked by the server, so many operations may not be possible on it. // This will return null if the player clicks a fake entity that was not spawned via <@link command fakespawn>. // returns an ElementTag of the hand used to click. // returns an ElementTag of the click type (left/right). // // @Player Always. // // --> public PlayerClicksFakeEntityScriptEvent() { registerCouldMatcher("player (right|left) clicks fake entity"); } public PlayerUseUnknownEntityEvent event; @Override public boolean matches(ScriptEvent.ScriptPath path) { if (path.eventArgLowerAt(1).equals("left") && !event.isAttack()) { return false; } else if (path.eventArgLowerAt(1).equals("right") && event.isAttack()) { return false; } if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { switch (name) { case "entity": FakeEntity fakeEntity = FakeEntity.getFakeEntityFor(event.getPlayer().getUniqueId(), event.getEntityId()); if (fakeEntity != null) { return fakeEntity.entity; } break; case "hand": return new ElementTag(event.getHand()); case "click_type": return new ElementTag(event.isAttack() ? "left" : "right"); } return super.getContext(name); } @EventHandler public void clickFakeEntity(PlayerUseUnknownEntityEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerClicksInRecipeBookScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerRecipeBookClickEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerClicksInRecipeBookScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player uses recipe book // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player interacts with their recipe book. // // @Context // returns the key of the recipe that was clicked. // returns 'true' if the player is trying to make the maximum amount of items from the recipe, otherwise 'false'. // // @Player Always. // // --> public PlayerClicksInRecipeBookScriptEvent() { registerCouldMatcher("player uses recipe book"); } public PlayerRecipeBookClickEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { switch (name) { case "recipe": return new ElementTag(event.getRecipe().toString()); case "is_all": return new ElementTag(event.isMakeAll()); } return super.getContext(name); } @EventHandler public void playerUsesRecipeBook(PlayerRecipeBookClickEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerClientOptionsChangeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.SkinParts; import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerClientOptionsChangeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player client options change // // @Plugin Paper // // @Group Paper // // @Player Always. // // @Triggers when a player changes their client options. // // @Context // returns a ElementTag(Boolean) of whether the player has server listings enabled. Available only on MC 1.19+. // returns an ElementTag of the player's chat visibility. Valid chat visibility options can be found at <@link url https://jd.papermc.io/paper/1.20/com/destroystokyo/paper/ClientOption.ChatVisibility.html> // returns an ElementTag of the player's current locale. // returns a ElementTag of the player's main hand. Can either be LEFT or RIGHT. // returns a MapTag of whether the player's skin parts are enabled or not. For example: [cape=true;jacket=false;left_sleeve=true;right_sleeve=false;left_pants=true;right_pants=false;hat=true] // returns a ElementTag(Number) of the player's view distance. // returns a ElementTag(Boolean) of whether the player's server listings have changed. Available only on MC 1.19+. // returns a ElementTag(Boolean) of whether the player has chat colors enabled. // returns a ElementTag(Boolean) of whether the player has toggled their chat colors. // returns a ElementTag(Boolean) of whether the player's chat visibility has changed. Available only on MC 1.19+. // returns a ElementTag(Boolean) of whether the player's locale has changed. // returns a ElementTag(Boolean) of whether the player's main hand has changed. // returns a ElementTag(Boolean) of whether the player's skin parts have changed. // returns a ElementTag(Boolean) of whether the player's text filtering has changed. Available only on MC 1.19+. // returns a ElementTag(Boolean) of whether the player has text filtering enabled. Available only on MC 1.19+. // returns a ElementTag(Boolean) of whether the player's view distance has changed. // // @Player Always. // // --> public PlayerClientOptionsChangeScriptEvent() { registerCouldMatcher("player client options change"); } public PlayerClientOptionsChangeEvent event; @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "server_listings_enabled" -> NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) ? new ElementTag(event.allowsServerListings()) : null; case "chat_visibility" -> new ElementTag(event.getChatVisibility()); case "locale" -> new ElementTag(event.getLocale()); case "main_hand" -> new ElementTag(event.getMainHand()); case "skin_parts" -> { MapTag map = new MapTag(); SkinParts skinParts = event.getSkinParts(); map.putObject("cape", new ElementTag(skinParts.hasCapeEnabled())); map.putObject("jacket", new ElementTag(skinParts.hasJacketEnabled())); map.putObject("left_sleeve", new ElementTag(skinParts.hasLeftSleeveEnabled())); map.putObject("right_sleeve", new ElementTag(skinParts.hasRightSleeveEnabled())); map.putObject("left_pants", new ElementTag(skinParts.hasLeftPantsEnabled())); map.putObject("right_pants", new ElementTag(skinParts.hasRightPantsEnabled())); map.putObject("hat", new ElementTag(skinParts.hasHatsEnabled())); yield map; } case "view_distance" -> new ElementTag(event.getViewDistance()); case "server_listings_changed" -> NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) ? new ElementTag(event.hasAllowServerListingsChanged()) : null; case "chat_colors_enabled" -> new ElementTag(event.hasChatColorsEnabled()); case "chat_colors_changed" -> new ElementTag(event.hasChatColorsEnabledChanged()); case "chat_visibility_changed" -> NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) ? new ElementTag(event.hasChatVisibilityChanged()) : null; case "locale_changed" -> new ElementTag(event.hasLocaleChanged()); case "main_hand_changed" -> new ElementTag(event.hasMainHandChanged()); case "skin_parts_changed" -> new ElementTag(event.hasSkinPartsChanged()); case "text_filtering_changed" -> NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) ? new ElementTag(event.hasTextFilteringChanged()) : null; case "text_filtering_enabled" -> NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19) ? new ElementTag(event.hasTextFilteringEnabled()) : null; case "view_distance_changed" -> new ElementTag(event.hasViewDistanceChanged()); default -> super.getContext(name); }; } @EventHandler public void onPlayerClientOptionsChange(PlayerClientOptionsChangeEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerCompletesAdvancementScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerCompletesAdvancementScriptEvent; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.utilities.CoreUtilities; import net.md_5.bungee.api.ChatColor; public class PlayerCompletesAdvancementScriptEventPaperImpl extends PlayerCompletesAdvancementScriptEvent { @Override public ObjectTag getContext(String name) { switch (name) { case "message": return new ElementTag(PaperModule.stringifyComponent(event.message())); } return super.getContext(name); } @Override public boolean applyDetermination(ScriptPath path, ObjectTag determinationObj) { if (determinationObj instanceof ElementTag) { String determination = determinationObj.toString(); String lower = CoreUtilities.toLowerCase(determination); if (lower.equals("no_message")) { event.message(null); return true; } event.message(PaperModule.parseFormattedText(determination, ChatColor.WHITE)); return true; } else { return super.applyDetermination(path, determinationObj); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerDeepSleepScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerDeepSleepEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerDeepSleepScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player deep sleeps // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player has slept long enough in a bed to count as being in deep sleep and thus skip the night. Cancelling the event prevents the player from qualifying to skip the night. // // @Player Always. // // --> public PlayerDeepSleepScriptEvent() { registerCouldMatcher("player deep sleeps"); } public PlayerDeepSleepEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @EventHandler public void playerDeepSleep(PlayerDeepSleepEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerElytraBoostScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerElytraBoostEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerElytraBoostScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player boosts elytra // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Switch with: to only process the event if the firework item used matches the specified item. // @Switch elytra: to only process the event if the elytra used matches the specified item. // // @Triggers when a player boosts their elytra with a firework rocket while gliding. // // @Context // returns the firework item used to boost. // returns the firework entity that was spawned. // returns whether the firework item gets consumed. // // @Player Always. // // @Determine // "KEEP:" to set whether the firework item should be kept. // // --> public PlayerElytraBoostScriptEvent() { registerCouldMatcher("player boosts elytra"); registerSwitches("with", "elytra"); this.registerOptionalDetermination("keep", ElementTag.class, (evt, context, value) -> { if (value.isBoolean()) { evt.event.setShouldConsume(!value.asBoolean()); return true; } return false; }); } public PlayerElytraBoostEvent event; public ItemTag firework; public PlayerTag player; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, player.getLocation())) { return false; } if (!runWithCheck(path, firework)) { return false; } if (!path.tryObjectSwitch("elytra", new ItemTag(player.getPlayerEntity().getEquipment().getChestplate()))) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(player, null); } @Override public ObjectTag getContext(String name) { return switch (name) { case "item" -> firework; case "entity" -> new EntityTag(event.getFirework()); case "should_keep" -> new ElementTag(!event.shouldConsume()); default -> super.getContext(name); }; } @EventHandler public void onPlayerElytraBoost(PlayerElytraBoostEvent event) { firework = new ItemTag(event.getItemStack()); player = new PlayerTag(event.getPlayer()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerEquipsArmorScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; import org.bukkit.Material; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import java.util.HashMap; public class PlayerEquipsArmorScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player equips|unequips armor|helmet|chestplate|leggings|boots // player equips|unequips // // @Plugin Paper // // @Group Paper // // @Triggers when a player (un)equips armor. // // @Warning This event is not reliable, and may miss some types of equipment changes or fire when equipment hasn't actually changed. // // @Context // returns the ItemTag that is now in the slot. // returns the ItemTag that used to be in the slot. // returns the name of the slot. // // @Player Always. // // --> public static HashMap slotsByName = new HashMap<>(); public static HashMap namesBySlot = new HashMap<>(); public static void registerSlot(String name, PlayerArmorChangeEvent.SlotType slot) { slotsByName.put(name, slot); namesBySlot.put(slot, name); } public PlayerEquipsArmorScriptEvent() { registerSlot("helmet", PlayerArmorChangeEvent.SlotType.HEAD); registerSlot("chestplate", PlayerArmorChangeEvent.SlotType.CHEST); registerSlot("leggings", PlayerArmorChangeEvent.SlotType.LEGS); registerSlot("boots", PlayerArmorChangeEvent.SlotType.FEET); registerCouldMatcher("player (equips|unequips) armor|helmet|chestplate|leggings|boots"); registerCouldMatcher("player (equips|unequips) "); } public ItemTag oldItem; public ItemTag newItem; public PlayerArmorChangeEvent.SlotType slot; public PlayerTag player; @Override public boolean matches(ScriptPath path) { String type = path.eventArgLowerAt(1); String itemCompare = path.eventArgLowerAt(2); PlayerArmorChangeEvent.SlotType slotType = slotsByName.get(itemCompare); if (slotType != null && slot != slotType) { return false; } if (type.equals("equips")) { if (slotType != null) { if (newItem.getMaterial().getMaterial() == Material.AIR) { return false; } } else if (!itemCompare.equals("armor") && !newItem.tryAdvancedMatcher(itemCompare, path.context)) { return false; } } else { // unequips if (slotType != null) { if (oldItem.getMaterial().getMaterial() == Material.AIR) { return false; } } else if (!itemCompare.equals("armor") && !oldItem.tryAdvancedMatcher(itemCompare, path.context)) { return false; } } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(player, null); } @Override public ObjectTag getContext(String name) { switch (name) { case "new_item": return newItem; case "old_item": return oldItem; case "slot": return new ElementTag(namesBySlot.get(slot)); } return super.getContext(name); } public String simpleComparisonString(ItemStack stack) { if (stack == null) { return "null"; } stack = stack.clone(); stack.setAmount(1); stack.setDurability((short) 0); return CoreUtilities.toLowerCase(new ItemTag(stack).identify()); } @EventHandler public void armorChangeEvent(PlayerArmorChangeEvent event) { if (EntityTag.isCitizensNPC(event.getPlayer())) { return; } if (simpleComparisonString(event.getOldItem()).equals(simpleComparisonString(event.getNewItem()))) { return; } newItem = new ItemTag(event.getNewItem()); oldItem = new ItemTag(event.getOldItem()); slot = event.getSlotType(); player = new PlayerTag(event.getPlayer()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerGrantedAdvancementCriterionScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerAdvancementCriterionGrantEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerGrantedAdvancementCriterionScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player granted advancement criterion // // @Group Paper // // @Plugin Paper // // @Cancellable true // // @Switch advancement: to only fire if the advancement for the criterion has the specified name. // @Switch criterion: to only fire if the criterion being granted has the specified name. // // @Triggers when a player is granted a single criterion for an advancement. // To fire when ALL the criteria for an advancement is met, use <@link event player completes advancement> // // @Context // returns the advancement's minecraft ID key. // returns the criterion minecraft ID key. // // @Player Always. // // @Example // # Prevent a player from being granted an advancement criterion. // on player granted advancement criterion: // - determine cancelled // // @Example // # This will only narrate when the player is granted the criterion for taming a Calico cat // # for the "A Complete Catalogue" advancement. // on player granted advancement criterion advancement:husbandry/complete_catalogue criterion:calico: // - narrate "That is a pretty cute Calico cat you have there!" // // @Example // # This will fire for a custom Denizen advancement called "my_advancement". // on player granted advancement criterion advancement:denizen:my_advancement: // - narrate "You got the advancement!" // --> public PlayerGrantedAdvancementCriterionScriptEvent() { registerCouldMatcher("player granted advancement criterion"); registerSwitches("advancement", "criterion"); } public ElementTag criterion; public ElementTag advancement; public PlayerAdvancementCriterionGrantEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryObjectSwitch("advancement", advancement)) { return false; } if (!path.tryObjectSwitch("criterion", criterion)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "criterion" -> criterion; case "advancement" -> advancement; default -> super.getContext(name); }; } @EventHandler public void playerGrantedAdvancementCriterionEvent(PlayerAdvancementCriterionGrantEvent event) { this.event = event; criterion = new ElementTag(Utilities.namespacedKeyToString(Utilities.parseNamespacedKey(event.getCriterion()))); advancement = new ElementTag(Utilities.namespacedKeyToString(event.getAdvancement().getKey())); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerInventorySlotChangeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerInventorySlotChangeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerInventorySlotChangeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player inventory slot changes // // @Group Paper // // @Location true // // @Plugin Paper // // @Switch from: to only process the event if the previous item in the slot matches the specified item. // @Switch to: to only process the event if the new item in the slot matches the specified item. // @Switch slot: to only process the event if a specific slot was clicked. For slot input options, see <@link language Slot Inputs>. // // @Triggers when the item in a slot of a player's inventory changes. // Note that this fires for every item in the player's inventory when they join. // // @Context // returns an ItemTag of the new item in the slot. // returns an ItemTag of the previous item in the slot. // returns an ElementTag(Number) of the slot that was changed. // returns an ElementTag(Number) of the raw number of the slot that was changed. // // @Player Always. // // --> public PlayerInventorySlotChangeScriptEvent() { registerCouldMatcher("player inventory slot changes"); registerSwitches("from", "to", "slot"); } public PlayerInventorySlotChangeEvent event; public ItemTag oldItem; public ItemTag newItem; @Override public boolean matches(ScriptPath path) { if (!trySlot(path, "slot", event.getPlayer(), event.getSlot())) { return false; } if (!runWithCheck(path, oldItem, "from")) { return false; } if (!runWithCheck(path, newItem, "to")) { return false; } if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { switch (name) { case "new_item": return newItem; case "old_item": return oldItem; case "slot": return new ElementTag(event.getSlot() + 1); case "raw_slot": return new ElementTag(event.getRawSlot()); } return super.getContext(name); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @EventHandler public void onPlayerInventorySlotChange(PlayerInventorySlotChangeEvent event) { if (EntityTag.isNPC(event.getPlayer())) { return; } oldItem = new ItemTag(event.getOldItemStack()); newItem = new ItemTag(event.getNewItemStack()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerItemTakesDamageScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerItemTakesDamageScriptEvent; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; public class PlayerItemTakesDamageScriptEventPaperImpl extends PlayerItemTakesDamageScriptEvent { @Override public ObjectTag getContext(String name) { switch (name) { case "original_damage": return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18) ? new ElementTag(event.getOriginalDamage()) : null; } return super.getContext(name); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerJumpsScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerJumpScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; import com.destroystokyo.paper.event.player.PlayerJumpEvent; import org.bukkit.event.EventHandler; public class PlayerJumpsScriptEventPaperImpl extends PlayerJumpScriptEvent { @EventHandler public void onPlayerJumps(PlayerJumpEvent event) { if (EntityTag.isNPC(event.getPlayer())) { return; } location = new LocationTag(event.getFrom()); player = new PlayerTag(event.getPlayer()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerLecternPageChangeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerLecternPageChangeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerLecternPageChangeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player flips lectern page // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Player Always. // // @Triggers when the player flips to a page in a lectern. // // @Switch book: to only process the event if the book on the lectern matches the given item. // // @Context // returns an ItemTag of the book in the lectern. // returns a LocationTag of the lectern. // returns an ElementTag(Number) of the last page the player was on. // returns an ElementTag(Number) of the new page that the player flipped to. // returns the direction in which the player flips the lectern book page, can be either LEFT or RIGHT. // // @Determine // "PAGE:" to set the page that the player will flip to. // // @Example // # Announce the page the player flipped to. // on player flips lectern page: // - announce " flipped to page #!" // // @Example // # Flips the player to page 5 if they are flagged with "pancakes". // on player flips lectern page flagged:pancakes: // - determine page:5 // // --> public PlayerLecternPageChangeScriptEvent() { registerCouldMatcher("player flips lectern page"); registerSwitches("book"); this.registerOptionalDetermination("page", ElementTag.class, (evt, context, page) -> { if (page.isInt()) { evt.event.setNewPage(page.asInt() - 1); return true; } return false; }); } public PlayerLecternPageChangeEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getLectern().getLocation())) { return false; } if (!path.tryObjectSwitch("book", new ItemTag(event.getBook()))) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "book" -> new ItemTag(event.getBook()); case "lectern" -> new LocationTag(event.getLectern().getLocation()); case "old_page" -> new ElementTag(event.getOldPage() + 1); case "new_page" -> new ElementTag(event.getNewPage() + 1); case "flip_direction" -> new ElementTag(event.getPageChangeDirection()); default -> super.getContext(name); }; } @EventHandler public void onPlayerFlipsLecternPage(PlayerLecternPageChangeEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerLoomPatternSelectScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.InventoryTag; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerLoomPatternSelectEvent; import org.bukkit.block.banner.PatternType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerLoomPatternSelectScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player selects loom pattern // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Player Always. // // @Triggers when a player selects a loom pattern. // // @Switch type: to only process the event if the specified pattern is selected. // // @Context // returns an InventoryTag of the loom. // returns an ElementTag of the selected pattern. Valid pattern types can be found at: <@link url https://jd.papermc.io/paper/1.19/org/bukkit/block/banner/PatternType.html> // // @Determine // "PATTERN:" to set the pattern type of the loom. // // @Example // # Announce the player's selected loom pattern. // on player selects loom pattern: // - announce " selected the pattern!" // // @Example // # If the player selects the "CREEPER" pattern type, publicly shames them before setting the pattern to "SKULL". // on player selects loom pattern type:CREEPER: // - announce "Shame on for selecting the creeper pattern!" // - determine pattern:SKULL // // --> public PlayerLoomPatternSelectScriptEvent() { registerCouldMatcher("player selects loom pattern"); registerSwitches("type"); this.registerOptionalDetermination("pattern", ElementTag.class, (evt, context, pattern) -> { if (Utilities.matchesEnumlike(pattern, PatternType.class)) { evt.event.setPatternType(Utilities.elementToEnumlike(pattern, PatternType.class)); return true; } return false; }); } public PlayerLoomPatternSelectEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getLoomInventory().getLocation())) { return false; } if (!path.tryObjectSwitch("type", Utilities.enumlikeToElement(event.getPatternType()))) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "loom" -> InventoryTag.mirrorBukkitInventory(event.getLoomInventory()); case "pattern" -> Utilities.enumlikeToElement(event.getPatternType()); default -> super.getContext(name); }; } @EventHandler public void onPlayerSelectsLoomPattern(PlayerLoomPatternSelectEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerNamesEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerNameEntityEvent; import net.md_5.bungee.api.ChatColor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerNamesEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player names // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player attempts to rename an entity with a name tag. // // @Context // returns an EntityTag of the renamed entity. // returns the old name of the entity, if any. // returns the new name of the entity. // returns whether this will cause the entity to persist through server restarts. // // @Determine // "NAME:" to set a different name for the entity. // "PERSISTENT:" to set whether the event will cause the entity to persist through restarts. NOTE: Entities may still persist for other reasons. To ensure they do not, use <@link mechanism EntityTag.force_no_persist>. // // @Player Always. // // --> public PlayerNamesEntityScriptEvent() { registerCouldMatcher("player names "); this.registerOptionalDetermination("persistent", ElementTag.class, (evt, context, determination) -> { if (determination.isBoolean()) { evt.event.setPersistent(determination.asBoolean()); return true; } return false; }); this.registerDetermination("name", ElementTag.class, (evt, context, determination) -> { evt.event.setName(PaperModule.parseFormattedText(determination.toString(), ChatColor.WHITE)); }); } public PlayerNameEntityEvent event; public EntityTag entity; public ElementTag oldName; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, entity.getLocation())) { return false; } if (!path.tryArgObject(2, entity)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity.getDenizenObject(); case "name" -> new ElementTag(PaperModule.stringifyComponent(event.getName()), true); case "old_name" -> oldName; case "persistent" -> new ElementTag(event.isPersistent()); default -> super.getContext(name); }; } @EventHandler public void playerNamesEntity(PlayerNameEntityEvent event) { this.event = event; entity = new EntityTag(event.getEntity()); String name = PaperAPITools.instance.getCustomName(entity.getBukkitEntity()); oldName = name == null ? null : new ElementTag(name, true); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerOpenSignScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerOpenSignEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerOpenSignScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player opens sign // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Triggers When a player opens a sign (eg after placing a sign, or by clicking on it to edit it). // // @Context // returns an ElementTag of the side of the sign that was clicked (FRONT or BACK). // returns an ElementTag of reason the sign was opened - see <@link url https://jd.papermc.io/paper/1.20/io/papermc/paper/event/player/PlayerOpenSignEvent.Cause.html>. // returns a LocationTag of the sign's location. // // @Player Always. // // --> public PlayerOpenSignScriptEvent() { registerCouldMatcher("player opens sign"); } public PlayerOpenSignEvent event; public LocationTag location; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "side" -> new ElementTag(event.getSide()); case "cause" -> new ElementTag(event.getCause()); case "location" -> location; default -> super.getContext(name); }; } @EventHandler public void playerOpenSignEvent(PlayerOpenSignEvent event) { location = new LocationTag(event.getSign().getLocation()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerPreparesGrindstoneCraftScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.*; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.inventory.PrepareResultEvent; import org.bukkit.entity.HumanEntity; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.inventory.GrindstoneInventory; public class PlayerPreparesGrindstoneCraftScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player prepares grindstone craft // // @Group Player // // @Location true // // @Plugin Paper // // @Triggers when a player prepares to grind an item. // // @Context // returns the InventoryTag of the grindstone inventory. // returns the ItemTag to be crafted. // // @Determine // "RESULT:" to change the item that is crafted. // // @Player Always. // // @Warning The player doing the grinding is estimated and may be inaccurate. // // @Example // # This example removes the usually not removable curse of binding enchantment. // on player prepares grindstone craft item: // - determine result: // // --> public PlayerPreparesGrindstoneCraftScriptEvent() { registerCouldMatcher("player prepares grindstone craft "); this.registerDetermination("result", ItemTag.class, (evt, context, item) -> { evt.event.setResult(item.getItemStack()); }); } public PrepareResultEvent event; public PlayerTag player; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(4, new ItemTag(event.getResult()))) { return false; } if (!runInCheck(path, event.getInventory().getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "inventory" -> InventoryTag.mirrorBukkitInventory(event.getInventory()); case "result" -> new ItemTag(event.getResult()); default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(player, null); } @EventHandler public void onPlayerPreparesGrindstoneCraft(PrepareResultEvent event) { if (!(event.getInventory() instanceof GrindstoneInventory)) { return; } if (event.getViewers().isEmpty()) { return; } HumanEntity humanEntity = event.getViewers().get(0); if (EntityTag.isNPC(humanEntity)) { return; } player = EntityTag.getPlayerFrom(humanEntity); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerQuitsScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerQuitsScriptEvent; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import net.md_5.bungee.api.ChatColor; public class PlayerQuitsScriptEventPaperImpl extends PlayerQuitsScriptEvent { public PlayerQuitsScriptEventPaperImpl() { registerSwitches("cause"); this.registerTextDetermination("none", (evt) -> { event.quitMessage(null); }); this.registerDetermination(null, ElementTag.class, (evt, context, determination) -> { event.quitMessage(PaperModule.parseFormattedText(determination.toString(), ChatColor.WHITE)); }); } @Override public boolean matches(ScriptPath path) { if (!runGenericSwitchCheck(path, "cause", event.getReason().name())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "message" -> new ElementTag(PaperModule.stringifyComponent(event.quitMessage())); case "cause" -> new ElementTag(event.getReason()); default -> super.getContext(name); }; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerRaiseLowerItemScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.player.PlayerRaiseLowerItemScriptEvent; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.core.ElementTag; import io.papermc.paper.event.player.PlayerStopUsingItemEvent; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; public class PlayerRaiseLowerItemScriptEventPaperImpl extends PlayerRaiseLowerItemScriptEvent { public DurationTag heldFor; public ElementTag hand; @Override public ObjectTag getContext(String name) { return switch (name) { case "held_for" -> heldFor; case "hand" -> hand; case "item" -> item; default -> super.getContext(name); }; } @Override public void run(Player pl, String reason) { this.reason = new ElementTag(reason); player = new PlayerTag(pl); item = new ItemTag(pl.getActiveItem()); hand = new ElementTag(pl.getHandRaised()); if (item.getBukkitMaterial() == Material.AIR) { item = new ItemTag(pl.getEquipment().getItemInMainHand()); hand = new ElementTag("HAND"); } if (item.getBukkitMaterial() == Material.AIR) { item = new ItemTag(pl.getEquipment().getItemInOffHand()); hand = new ElementTag("OFF_HAND"); } if (item.getBukkitMaterial() == Material.AIR) { return; } heldFor = state ? null : new DurationTag((long) pl.getHandRaisedTime()); fire(); } @EventHandler public void onStopUsingItem(PlayerStopUsingItemEvent event) { signalDidLower(event.getPlayer(), "lower"); } public boolean isHandRaised(Player player, EquipmentSlot slot) { if (player.isHandRaised()) { return slot == player.getHandRaised(); } return raisedItems.contains(player.getUniqueId()); } @EventHandler public void onPlayerDropItem(PlayerDropItemEvent event) { // You can only drop items from your main hand, so if the player's main hand isn't raised, ignore if (isHandRaised(event.getPlayer(), EquipmentSlot.HAND) && raisedItems.remove(event.getPlayer().getUniqueId())) { cancelled = false; state = false; Player pl = event.getPlayer(); player = new PlayerTag(pl); // Work around Player#getActiveItem being air in the drop item event ItemStack loweredItem = event.getItemDrop().getItemStack(); item = new ItemTag(loweredItem); heldFor = new DurationTag((long) loweredItem.getMaxItemUseDuration() - pl.getItemUseRemainingTime()); hand = new ElementTag(pl.getHandRaised()); reason = new ElementTag("drop"); fire(); } } @EventHandler public void onPlayerChangeHeldItem(PlayerItemHeldEvent event) { if (isHandRaised(event.getPlayer(), EquipmentSlot.HAND)) { signalDidLower(event.getPlayer(), "hold"); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerReceivesLinksScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.connection.PlayerConfigurationConnection; import io.papermc.paper.connection.PlayerGameConnection; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerLinksSendEvent; public class PlayerReceivesLinksScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player receives links // // @Group Paper // // @Plugin Paper // // @Triggers when a player receives a list of server links. // // @Determine // "LINKS:" to set the links sent to the player. Each item in the list must be a MapTag in <@link language Server Links Format>. // "ADD_LINKS:" to send additional links to the player. Each item in the list must be a MapTag in <@link language Server Links Format>. // // @Player Always. // // @Warning this may fire early in the player login process, during which the linked player is essentially an offline player. // // --> public PlayerLinksSendEvent event; public PlayerTag player; public PlayerReceivesLinksScriptEvent() { registerCouldMatcher("player receives links"); this.registerDetermination("links", ListTag.class, (evt, context, value) -> { Utilities.replaceServerLinks(evt.event.getLinks(), value, context); }); this.registerDetermination("add_links", ListTag.class, (evt, context, value) -> { Utilities.fillServerLinks(evt.event.getLinks(), value, context); }); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(player, null); } @EventHandler public void onPlayerLinksSend(PlayerLinksSendEvent event) { if (event.getConnection() instanceof PlayerGameConnection gameConnection) { player = new PlayerTag(gameConnection.getPlayer()); } else if (event.getConnection() instanceof PlayerConfigurationConnection configConnection) { player = new PlayerTag(configConnection.getProfile().getId()); } else { throw new IllegalStateException("Links send event fired with unknown connection type! " + event.getConnection() + " / " + event.getConnection().getClass().getName()); } this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSelectsStonecutterRecipeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.InventoryTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerStonecutterRecipeSelectEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerSelectsStonecutterRecipeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player selects stonecutter recipe // // @Group Player // // @Cancellable true // // @Location true // // @Triggers when a player selects a recipe in a stonecutter. // // @Switch recipe_id: to only process the event if the recipe matches the recipe ID. // // @Context // returns the InventoryTag of the stonecutter inventory. // returns an ItemTag of the item in the input slot. // returns an ItemTag of the item in the result slot. // returns the ID of the recipe that was selected. // // @Player Always. // // --> public PlayerSelectsStonecutterRecipeScriptEvent() { registerCouldMatcher("player selects stonecutter recipe"); registerSwitches("recipe_id"); } public PlayerStonecutterRecipeSelectEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getStonecutterInventory().getLocation())) { return false; } if (!runGenericSwitchCheck(path, "recipe_id", event.getStonecuttingRecipe().getKey().toString())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { switch (name) { case "inventory": return InventoryTag.mirrorBukkitInventory(event.getStonecutterInventory()); case "input": return new ItemTag(event.getStonecutterInventory().getInputItem()); case "result": return new ItemTag(event.getStonecuttingRecipe().getResult()); case "recipe_id": return new ElementTag(String.valueOf(event.getStonecuttingRecipe().getKey())); } return super.getContext(name); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @EventHandler public void onPlayerSelectsStonecutterRecipe(PlayerStonecutterRecipeSelectEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSetSpawnScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerSetSpawnEvent; import net.md_5.bungee.api.ChatColor; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerSetSpawnScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player sets spawn // // @Cancellable true // // @Location true // // @Plugin Paper // // @Group Paper // // @Triggers when a player's spawn point changes. // // @Switch cause: to only process when the cause for the event matches the input. // // @Context // returns the reason the player's spawn point changed. A list of causes can be found at <@link url https://jd.papermc.io/paper/1.21.5/com/destroystokyo/paper/event/player/PlayerSetSpawnEvent.Cause.html>. // returns whether this event will persist through source block (bed or respawn anchor) removal. // returns a LocationTag of the new respawn location, if any. // returns the notification message that is sent to the player. // returns whether the player will be notified their spawn point changed. // // @Determine // "FORCED:" to set whether the player's new spawnpoint will persist even if the bed or respawn anchor that triggered the event is removed. // "MESSAGE:" to set the notification message that is sent to the player. // "NOTIFY:" to set whether the player will be notified their spawnpoint changed. // LocationTag to change the respawn location. // // @Player Always. // // --> public PlayerSetSpawnScriptEvent() { registerCouldMatcher("player sets spawn"); registerSwitches("cause"); this.registerOptionalDetermination("forced", ElementTag.class, (evt, context, value) -> { if (value.isBoolean()) { evt.event.setForced(value.asBoolean()); return true; } return false; }); this.registerDetermination("message", ElementTag.class, (evt, context, message) -> { evt.event.setNotification(PaperModule.parseFormattedText(message.toString(), ChatColor.WHITE)); }); this.registerOptionalDetermination("notify", ElementTag.class, (evt, context, value) -> { if (value.isBoolean()) { evt.event.setNotifyPlayer(value.asBoolean()); return true; } return false; }); this.registerDetermination(null, LocationTag.class, (evt, context, location) -> { evt.event.setLocation(location); evt.event.setForced(true); // required if the cause is a bed or respawn anchor }); } public PlayerSetSpawnEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getLocation())) { return false; } if (!runGenericSwitchCheck(path, "cause", event.getCause().toString())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "cause" -> new ElementTag(event.getCause()); case "forced" -> new ElementTag(event.isForced()); case "location" -> event.getLocation() != null ? new LocationTag(event.getLocation()) : null; case "message" -> event.getNotification() != null ? new ElementTag(PaperModule.stringifyComponent(event.getNotification()), true) : null; case "notify" -> new ElementTag(event.willNotifyPlayer()); default -> super.getContext(name); }; } @EventHandler public void onPlayerSetsSpawn(PlayerSetSpawnEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerShieldDisableScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerShieldDisableEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerShieldDisableScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player shield disables // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Triggers When a players shield is disabled. // // @Context // returns an EntityTag of the attacker who disabled the shield. // returns a DurationTag of the cooldown the shield is disabled for. // // @Determine // "COOLDOWN:" to change the cooldown. // // @Player Always. // // --> public PlayerShieldDisableScriptEvent() { registerCouldMatcher("player shield disables"); this.registerDetermination("cooldown", DurationTag.class, (evt, context, duration) -> { evt.event.setCooldown(duration.getTicksAsInt()); }); } public PlayerShieldDisableEvent event; public LocationTag location; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "damager" -> new EntityTag(event.getDamager()).getDenizenObject(); case "cooldown" -> new DurationTag((long) event.getCooldown()); default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @EventHandler public void playerShieldDisableEvent(PlayerShieldDisableEvent event) { location = new LocationTag(event.getPlayer().getLocation()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerSpectatesEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerSpectatesEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player spectates // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player starts spectating an entity. // // @Context // returns the entity that is being spectated. // returns the entity that was previously being spectated (or the player themself if they weren't spectating anything). // // @Player Always. // // --> public PlayerSpectatesEntityScriptEvent() { registerCouldMatcher("player spectates "); } public PlayerStartSpectatingEntityEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(2, new EntityTag(event.getNewSpectatorTarget()))) { return false; } if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { if (name.equals("entity")) { return new EntityTag(event.getNewSpectatorTarget()).getDenizenObject(); } else if (name.equals("old_entity")) { return new EntityTag(event.getCurrentSpectatorTarget()).getDenizenObject(); } return super.getContext(name); } @EventHandler public void playerSpectateEvent(PlayerStartSpectatingEntityEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerStopsSpectatingScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerStopsSpectatingScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player stops spectating () // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player stops spectating an entity. // // @Context // returns the entity that was being spectated. // // @Player Always. // // --> public PlayerStopsSpectatingScriptEvent() { registerCouldMatcher("player stops spectating ()"); } public PlayerStopSpectatingEntityEvent event; @Override public boolean matches(ScriptPath path) { if (path.eventArgLowerAt(3).length() > 0 && !path.tryArgObject(3, new EntityTag(event.getSpectatorTarget()))) { return false; } if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { if (name.equals("entity")) { return new EntityTag(event.getSpectatorTarget()).getDenizenObject(); } return super.getContext(name); } @EventHandler public void playerSpectateEvent(PlayerStopSpectatingEntityEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTracksEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerTrackEntityEvent; import io.papermc.paper.event.player.PlayerUntrackEntityEvent; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerTracksEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player tracks|untracks // // @Location true // // @Group Paper // // @Plugin Paper // // @Warning This event may fire very rapidly. // // @Triggers when a player starts or stops tracking an entity. An entity is tracked/untracked by a player's client when the player moves in/out of its <@link mechanism EntityTag.tracking_range>. // // @Context // returns an EntityTag of the entity being tracked or untracked. // // @Player Always. // // @Example // # Narrate when the player tracks any entities except for item frames. // on player tracks !item_frame: // - narrate "You are now tracking at " // // @Example // on player untracks chicken: // - narrate "CHICKEN: No! Come back! :(" // --> public PlayerTracksEntityScriptEvent() { registerCouldMatcher("player tracks|untracks "); } public String type; public Player player; public EntityTag entity; @Override public boolean matches(ScriptPath path) { if (!path.eventArgLowerAt(1).equals(type)) { return false; } if (!path.tryArgObject(2, entity)) { return false; } if (!runInCheck(path, entity.getLocation())) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(player); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; default -> super.getContext(name); }; } @EventHandler public void onPlayerTracksEntityEvent(PlayerTrackEntityEvent event) { entity = new EntityTag(event.getEntity()); player = event.getPlayer(); type = "tracks"; fire(event); } @EventHandler public void onPlayerUntracksEntityEvent(PlayerUntrackEntityEvent event) { entity = new EntityTag(event.getEntity()); player = event.getPlayer(); type = "untracks"; EntityTag.rememberEntity(event.getEntity()); fire(event); EntityTag.forgetEntity(event.getEntity()); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PlayerTradesWithMerchantScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.TradeTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PlayerPurchaseEvent; import io.papermc.paper.event.player.PlayerTradeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PlayerTradesWithMerchantScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player trades with merchant // // @Switch result: to only process the event if the player received a specific result item. // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when a player trades with a merchant (villager). // // @Context // returns the villager that was traded with, if any (may be null for example with 'opentrades' command usage). // returns a TradeTag of the trade that was done. // // @Determine // TradeTag to change the trade that should be processed. // // // @Player Always. // // --> public PlayerTradesWithMerchantScriptEvent() { registerCouldMatcher("player trades with merchant"); registerSwitches("result"); this.registerDetermination(null, TradeTag.class, (evt, context, trade) -> { evt.event.setTrade(trade.getRecipe()); }); } public PlayerPurchaseEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getPlayer().getLocation())) { return false; } if (!path.tryObjectSwitch("result", new ItemTag(event.getTrade().getResult()))) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "merchant" -> event instanceof PlayerTradeEvent tradeEvent ? new EntityTag(tradeEvent.getVillager()) : null; case "trade" -> new TradeTag(event.getTrade()).duplicate(); default -> super.getContext(name); }; } @EventHandler public void playerTradeEvent(PlayerPurchaseEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PreEntitySpawnScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent; import com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PreEntitySpawnScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // prespawns (because <'cause'>) // // @Plugin Paper // // @Group Paper // // @Location true // // @Cancellable true // // @Warning This event may fire very rapidly, and only fires for NATURAL and SPAWNER reasons. // // @Triggers before a mob spawns and before the mob is created for spawning. Note that this has a limited number of use cases. // The intent of this event is to save server resources for blanket mob banning/limiting scripts. Use the entity spawn event as a backup. // // @Context // returns the EntityTag that will be spawned. Note that this entity will not be spawned yet, so usage will be limited. // returns the LocationTag the entity will spawn at. // returns an ElementTag of the reason for spawning. Currently, this event only fires for NATURAL and SPAWNER reasons. // returns the LocationTag of the spawner's location if this mob is spawning from a spawner. // // --> public PreEntitySpawnScriptEvent() { registerCouldMatcher(" prespawns (because <'cause'>)"); } public EntityTag entity; public LocationTag location; public PreCreatureSpawnEvent event; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(0, entity)) { return false; } if (path.eventArgLowerAt(2).equals("because") && !path.eventArgLowerAt(3).equalsIgnoreCase(event.getReason().name())) { return false; } if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public void cancellationChanged() { event.setShouldAbortSpawn(cancelled); super.cancellationChanged(); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(null, null); } @Override public ObjectTag getContext(String name) { if (name.equals("entity")) { return entity; } else if (name.equals("location")) { return location; } else if (name.equals("reason")) { return new ElementTag(event.getReason()); } else if (name.equals("spawner_location") && event instanceof PreSpawnerSpawnEvent) { return new LocationTag(((PreSpawnerSpawnEvent) event).getSpawnerLocation()); } return super.getContext(name); } @EventHandler public void onPreCreatureSpawn(PreCreatureSpawnEvent event) { this.entity = new EntityTag(event.getType()); this.location = new LocationTag(event.getSpawnLocation()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/PrePlayerAttackEntityScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.player.PrePlayerAttackEntityEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class PrePlayerAttackEntityScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // player tries to attack // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Switch with: to only process the event if the player attacks the entity with the specified item. // // @Triggers when the player tries to attack an entity. This occurs before any of the damage logic, so cancelling this event will prevent any sort of sounds from being played when attacking. // // @Context // returns the entity that was attacked in this event. // returns whether this entity would be attacked normally. // Entities like falling sand will return false because their entity type does not allow them to be attacked. // Note: there may be other factors (invulnerability, etc.) that will prevent this entity from being attacked that this event does not cover. // // @Player Always. // // --> public PrePlayerAttackEntityScriptEvent() { registerCouldMatcher("player tries to attack "); registerSwitches("with"); } public PrePlayerAttackEntityEvent event; public EntityTag entity; public ItemTag item; @Override public boolean matches(ScriptPath path) { if (!path.tryArgObject(4, entity)) { return false; } if (!path.tryObjectSwitch("with", new ItemTag(event.getPlayer().getEquipment().getItemInMainHand()))) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; case "will_attack" -> new ElementTag(event.willAttack()); default -> super.getContext(name); }; } @EventHandler public void onPrePlayerAttackEntity(PrePlayerAttackEntityEvent event) { this.event = event; entity = new EntityTag(event.getAttacked()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/ProjectileCollideScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.entity.ProjectileCollideEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class ProjectileCollideScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // collides with // // @Location true // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers N/A - use <@link event projectile hits> with the 'entity' switch on versions above 1.19. // // @Context // returns the projectile that is colliding. // returns the entity that was collided with. // // @Player When the entity collided with is a player. // @NPC When the entity collided with is a NPC. // // @deprecated Use 'projectile hits' with the 'entity' switch on versions above 1.19. // // --> public ProjectileCollideScriptEvent() { registerCouldMatcher(" collides with "); } @Override public boolean couldMatch(ScriptPath path) { if (!super.couldMatch(path)) { return false; } if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { BukkitImplDeprecations.projectileCollideEvent.warn(path.container); } return true; } public ProjectileCollideEvent event; public EntityTag projectile; public EntityTag collidedWith; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getEntity().getLocation())) { return false; } if (!path.tryArgObject(0, projectile)) { return false; } if (!path.tryArgObject(3, collidedWith)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(collidedWith); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> collidedWith.getDenizenObject(); case "projectile" -> projectile; default -> super.getContext(name); }; } @EventHandler public void projectileCollideEvent(ProjectileCollideEvent event) { this.event = event; collidedWith = new EntityTag(event.getCollidedWith()); projectile = new EntityTag(event.getEntity()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/ServerListPingScriptEventPaperImpl.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.server.ListPingScriptEvent; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.nms.abstracts.ProfileEditor; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.destroystokyo.paper.event.server.PaperServerListPingEvent; import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; import net.md_5.bungee.api.ChatColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.profile.PlayerTextures; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.CompletableFuture; public class ServerListPingScriptEventPaperImpl extends ListPingScriptEvent { public ServerListPingScriptEventPaperImpl() { this.registerOptionalDetermination("protocol_version", ElementTag.class, (evt, context, version) -> { if (version.isInt()) { evt.getEvent().setProtocolVersion(version.asInt()); return true; } return false; }); this.registerDetermination("version_name", ElementTag.class, (evt, context, name) -> { evt.getEvent().setVersion(name.asString()); }); this.registerDetermination("exclude_players", ListTag.class, (evt, context, list) -> { HashSet exclusions = new HashSet<>(); for (PlayerTag player : list.filter(PlayerTag.class, context)) { exclusions.add(player.getUUID()); } if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { Iterator players = evt.getEvent().iterator(); while (players.hasNext()) { if (exclusions.contains(players.next().getUniqueId())) { players.remove(); } } return; } ListedPlayersEditor.excludeListedPlayers(evt.getEvent(), exclusions); }); this.registerOptionalDetermination("alternate_player_text", ListTag.class, (evt, context, text) -> { if (!CoreConfiguration.allowRestrictedActions) { Debug.echoError("Cannot use 'alternate_player_text' in list ping event: 'Allow restricted actions' is disabled in Denizen config.yml."); return false; } if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { evt.getEvent().getPlayerSample().clear(); for (String line : text) { FakeProfile lineProf = new FakeProfile(); lineProf.setName(line); evt.getEvent().getPlayerSample().add(lineProf); } return true; } ListedPlayersEditor.setListedPlayerInfo(evt.getEvent(), text); return true; }); } public PaperServerListPingEvent getEvent() { return (PaperServerListPingEvent) event; } // TODO: workaround for Java trying to load ListedPlayerInfo on old versions, remove once 1.20 is the minimum supported version public static class ListedPlayersEditor { public static void setListedPlayerInfo(PaperServerListPingEvent event, List lines) { event.getListedPlayers().clear(); for (String line : lines) { event.getListedPlayers().add(new PaperServerListPingEvent.ListedPlayerInfo(line, ProfileEditor.NIL_UUID)); } } public static void excludeListedPlayers(PaperServerListPingEvent event, Set exclude) { event.getListedPlayers().removeIf(listedPlayerInfo -> exclude.contains(listedPlayerInfo.id())); } } public static class FakeProfile implements PlayerProfile { public String name; @Override public @Nullable String getName() { return name; } @Override public @NotNull String setName(@Nullable String s) { String old = name; name = s; return old; } @Override public @Nullable UUID getUniqueId() { return null; } @Override public @Nullable UUID getId() { return null; } @Override public @Nullable UUID setId(@Nullable UUID uuid) { return null; } @Override public @NotNull PlayerTextures getTextures() { return null; } @Override public void setTextures(@Nullable PlayerTextures playerTextures) { } @Override public @NotNull Set getProperties() { return null; } @Override public boolean hasProperty(@Nullable String s) { return false; } @Override public void setProperty(@NotNull ProfileProperty profileProperty) { } @Override public void setProperties(@NotNull Collection collection) { } @Override public boolean removeProperty(@Nullable String s) { return false; } @Override public void clearProperties() { } @Override public boolean isComplete() { return false; } @Override public @NotNull CompletableFuture update() { return null; } @Override public com.destroystokyo.paper.profile.@NotNull PlayerProfile clone() { return null; } @Override public boolean completeFromCache() { return false; } @Override public boolean completeFromCache(boolean b) { return false; } @Override public boolean completeFromCache(boolean b, boolean b1) { return false; } @Override public boolean complete(boolean b) { return false; } @Override public boolean complete(boolean b, boolean b1) { return false; } @Override public @NotNull Map serialize() { return null; } } @Override public void setMotd(String text) { event.motd(PaperModule.parseFormattedText(text, ChatColor.WHITE)); } @Override public ObjectTag getContext(String name) { return switch (name) { case "motd" -> new ElementTag(PaperModule.stringifyComponent(event.motd()), true); case "protocol_version" -> new ElementTag(getEvent().getProtocolVersion()); case "version_name" -> new ElementTag(getEvent().getVersion(), true); case "client_protocol_version" -> new ElementTag(getEvent().getClient().getProtocolVersion()); default -> super.getContext(name); }; } @EventHandler public void onListPing(PaperServerListPingEvent event) { syncFire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/ServerResourcesReloadedScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import io.papermc.paper.event.server.ServerResourcesReloadedEvent; public class ServerResourcesReloadedScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // server resources reloaded // // @Plugin Paper // // @Group Paper // // @Switch cause: to only process the event if the cause of the resource reload matches the specified cause. // // @Triggers when vanilla resources (such as datapacks) are reloaded (by vanilla commands or by plugins). If you mess with datapacks often, it may be helpful to run <@link command reload> in this event. // // @Context // Returns the cause of the resource reload. Refer to <@link url https://jd.papermc.io/paper/1.19/io/papermc/paper/event/server/ServerResourcesReloadedEvent.Cause.html> // // --> public ServerResourcesReloadedScriptEvent() { registerCouldMatcher("server resources reloaded"); registerSwitches("cause"); } public ElementTag cause; @Override public boolean matches(ScriptPath path) { if (!runGenericSwitchCheck(path, "cause", cause.asString())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { switch (name) { case "cause": return cause; } return super.getContext(name); } @EventHandler public void onServerResourcesReloaded(ServerResourcesReloadedEvent event) { cause = new ElementTag(event.getCause()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/SkeletonHorseTrapScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.destroystokyo.paper.event.entity.SkeletonHorseTrapEvent; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class SkeletonHorseTrapScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // skeleton horse trap // // @Location true // // @Group Paper // // @Plugin Paper // // @Triggers when a player gets too close to a trapped skeleton horse and triggers the trap. // // @Context // returns an EntityTag of the skeleton horse. // returns a ListTag(PlayerTag) of the players involved in the trap. // --> public SkeletonHorseTrapScriptEvent() { registerCouldMatcher("skeleton horse trap"); } public EntityTag entity; public SkeletonHorseTrapEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, entity.getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> entity; case "players" -> { ListTag players = new ListTag(); for (HumanEntity human : event.getEligibleHumans()) { if (!EntityTag.isNPC(human) && human instanceof Player player) { players.addObject(new PlayerTag(player)); } } yield players; } default -> super.getContext(name); }; } @EventHandler public void onSkeletonHorseTrap(SkeletonHorseTrapEvent event) { this.event = event; entity = new EntityTag(event.getEntity()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/TNTPrimesScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import com.destroystokyo.paper.event.block.TNTPrimeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class TNTPrimesScriptEvent extends BukkitScriptEvent implements Listener { public TNTPrimesScriptEvent() { registerCouldMatcher("tnt primes"); } public TNTPrimeEvent event; public LocationTag location; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPrimerEntity()); } @Override public ObjectTag getContext(String name) { if (name.equals("entity") && event.getPrimerEntity() != null) { return new EntityTag(event.getPrimerEntity()).getDenizenObject(); } else if (name.equals("location")) { return location; } else if (name.equals("reason")) { return new ElementTag(event.getReason()); } return super.getContext(name); } @EventHandler public void tntPrimeEvent(TNTPrimeEvent event) { this.event = event; location = new LocationTag(event.getBlock().getLocation()); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/TargetBlockHitScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.block.TargetHitEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class TargetBlockHitScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // target block hit // // @Location true // // @Group Paper // // @Plugin Paper // // @Triggers when a target block is hit by a projectile such as an arrow. // // @Context // returns an EntityTag of the projectile. // returns a LocationTag of the block that was hit. // returns a LocationTag vector of the hit normal (like '0,1,0' if the projectile hit the top of a block). // returns an EntityTag of the entity that shot the projectile, if any. // returns a ElementTag of the emitted redstone strength. // // @Player when the shooter is a player. // // @NPC when the shooter is a npc. // --> public TargetBlockHitScriptEvent() { registerCouldMatcher("target block hit"); } public TargetHitEvent event; public LocationTag hitBlock; public EntityTag projectile; public EntityTag shooter; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, hitBlock)) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "projectile" -> projectile.getDenizenObject(); case "hit_block" -> hitBlock; case "hit_face" -> event.getHitBlockFace() != null ? new LocationTag(event.getHitBlockFace().getDirection()) : null; case "shooter" -> shooter != null ? shooter.getDenizenObject() : null; case "strength" -> new ElementTag(event.getSignalStrength()); default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(shooter); } @EventHandler public void onProjectileHit(TargetHitEvent event) { this.event = event; projectile = new EntityTag(event.getEntity()); hitBlock = new LocationTag(event.getHitBlock().getLocation()); shooter = projectile.getShooter(); fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/UnknownCommandScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ArgumentHelper; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import net.md_5.bungee.api.ChatColor; import org.bukkit.command.BlockCommandSender; import org.bukkit.entity.Player; import org.bukkit.entity.minecart.CommandMinecart; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.command.UnknownCommandEvent; import java.util.Arrays; public class UnknownCommandScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // command unknown // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Triggers when an unknown command is processed by the server. // // @Context // returns an ElementTag of the message to be shown to the command sender. // returns the command name as an Element. // returns any args used as an Element. // returns a ListTag of the arguments. // returns the source of the command. Can be: PLAYER, SERVER, COMMAND_BLOCK, or COMMAND_MINECART. // returns the command block's location (if the command was run from one). // returns the EntityTag of the command minecart (if the command was run from one). // // @Determine // ElementTag to change the message returned to the command sender. // "NONE" to cancel the message. // // @Player when source_type is player. // // --> public UnknownCommandScriptEvent() { registerCouldMatcher("command unknown"); this.registerDetermination(null, ElementTag.class, (evt, context, text) -> { evt.event.message(PaperModule.parseFormattedText(text.toString(), ChatColor.WHITE)); }); this.registerTextDetermination("none", (evt) -> { evt.event.message(null); }); } public UnknownCommandEvent event; public String command; public String rawArgs; public String sourceType; @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getSender() instanceof Player player ? new PlayerTag(player) : null, null); } @Override public ObjectTag getContext(String name) { return switch (name) { case "command" -> new ElementTag(command, true); case "raw_args" -> new ElementTag(rawArgs, true); case "args" -> new ListTag(Arrays.asList(ArgumentHelper.buildArgs(rawArgs, false)), true); case "server" -> new ElementTag(sourceType.equals("server")); case "source_type" -> new ElementTag(sourceType, true); case "command_block_location" -> sourceType.equals("command_block") ? new LocationTag(((BlockCommandSender) event.getSender()).getBlock().getLocation()) : null; case "command_minecart" -> sourceType.equals("command_minecart") ? new EntityTag((CommandMinecart) event.getSender()) : null; case "message" -> new ElementTag(PaperModule.stringifyComponent(event.message()), true); default -> super.getContext(name); }; } @EventHandler public void unknownCommandEvent(UnknownCommandEvent event) { this.event = event; String[] splitCommand = event.getCommandLine().split(" ", 2); this.command = splitCommand[0]; this.rawArgs = splitCommand.length > 1 ? splitCommand[1] : ""; if (event.getSender() instanceof Player) { this.sourceType = "player"; } else if (event.getSender() instanceof BlockCommandSender) { this.sourceType = "command_block"; } else if (event.getSender() instanceof CommandMinecart) { this.sourceType = "command_minecart"; } else { this.sourceType = "server"; } fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/VaultChangesStateScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.block.VaultChangeStateEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class VaultChangesStateScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // vault changes state // // @Plugin Paper // // @Group Block // // @Cancellable true // // @Location true // // @Triggers when a vault block's state changes. A list of states can be found at <@link url https://jd.papermc.io/paper/org/bukkit/block/data/type/Vault.State.html>. // // @Context // returns the LocationTag of the vault block. // returns the vault state before the change. // returns the vault state after the change. // // @Player when the change is triggered by a player. // // --> public VaultChangesStateScriptEvent() { registerCouldMatcher("vault changes state"); } public LocationTag location; public VaultChangeStateEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, location)) { return false; } return super.matches(path); } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getPlayer()); } @Override public ObjectTag getContext(String name) { return switch (name) { case "old_state" -> new ElementTag(event.getCurrentState()); case "new_state" -> new ElementTag(event.getNewState()); case "location" -> location; default -> super.getContext(name); }; } @EventHandler public void onVaultChangesStateEvent(VaultChangeStateEvent event) { location = new LocationTag(event.getBlock().getLocation()); this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/WardenChangesAngerLevelScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.entity.WardenAngerChangeEvent; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class WardenChangesAngerLevelScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // warden changes anger level // // @Plugin Paper // // @Group Paper // // @Cancellable true // // @Location true // // @Triggers when a warden changes its anger level. (In practice, only fires when increasing). // // @Player when the entity who triggered the change is a player. // // @NPC when the entity who triggered the change is an NPC. // // @Context // returns the EntityTag of the warden which changed its anger level. // returns an ElementTag(Number) of the new anger level. // returns an ElementTag(Number) of the old anger level. // returns the EntityTag who triggered the change (if any). (In practice, always present). // // @Determine // "ANGER:" to set the value of the anger level. Value must be between 0 and 150. // // @Example // on warden changes anger level: // - if >= 40 && < 80: // - announce "Careful, the warden is agitated!" // // --> public WardenChangesAngerLevelScriptEvent() { registerCouldMatcher("warden changes anger level"); this.registerOptionalDetermination("anger", ElementTag.class, (evt, context, anger) -> { if (anger.isInt()) { evt.event.setNewAnger(anger.asInt()); return true; } return false; }); } public WardenAngerChangeEvent event; @Override public boolean matches(ScriptPath path) { if (!runInCheck(path, event.getEntity().getLocation())) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "entity" -> new EntityTag(event.getEntity()); case "new_anger" -> new ElementTag(event.getNewAnger()); case "old_anger" -> new ElementTag(event.getOldAnger()); case "target" -> event.getTarget() != null ? new EntityTag(event.getTarget()).getDenizenObject() : null; default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { return new BukkitScriptEntryData(event.getTarget()); } @EventHandler public void onWardenAngerChange(WardenAngerChangeEvent event) { this.event = event; fire(event); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/events/WorldGameRuleChangeScriptEvent.java ================================================ package com.denizenscript.denizen.paper.events; import com.denizenscript.denizen.events.BukkitScriptEvent; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.objects.WorldTag; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizen.utilities.world.GameRuleReflect; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.scripts.ScriptEntryData; import io.papermc.paper.event.world.WorldGameRuleChangeEvent; import org.bukkit.command.BlockCommandSender; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.entity.minecart.CommandMinecart; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; public class WorldGameRuleChangeScriptEvent extends BukkitScriptEvent implements Listener { // <--[event] // @Events // gamerule changes (in ) // // @Plugin Paper // // @Group Paper // // @Triggers when a gamerule changes. // // @Switch gamerule: to only process the event if the gamerule matches a specific gamerule. // // @Context // returns the name of the GameRule which was changed. Refer to <@link url https://jd.papermc.io/paper/1.19/org/bukkit/GameRule.html>. // returns the new value of the GameRule. // returns the world where the GameRule is applied. // returns type of source. Can be: PLAYER, COMMAND_BLOCK, COMMAND_MINECART, SERVER. // returns the command block's location (if the command was run from one). // returns the EntityTag of the command minecart (if the command was run from one). // // @Determine // "VALUE:" or ElementTag(Boolean) to set the value of the GameRule. // // @Player when the sender of the command is a player. // // --> public WorldGameRuleChangeScriptEvent() { registerCouldMatcher("gamerule changes (in )"); registerSwitches("gamerule"); this.registerOptionalDetermination("value", ElementTag.class, (evt, context, value) -> { if (value.isBoolean() || value.isInt()) { evt.event.setValue(value.toString()); return true; } return false; }); } public WorldGameRuleChangeEvent event; public WorldTag world; public CommandSender source; @Override public boolean matches(ScriptPath path) { if (path.eventArgLowerAt(2).equals("in") && !path.tryArgObject(3, world)) { return false; } if (!runGenericSwitchCheck(path, "gamerule", GameRuleReflect.getName(event.getGameRule()))) { return false; } return super.matches(path); } @Override public ObjectTag getContext(String name) { return switch (name) { case "gamerule" -> new ElementTag(GameRuleReflect.getName(event.getGameRule()), true); case "value" -> new ElementTag(event.getValue(), true); case "source_type" -> getSourceType(); case "command_block_location" -> getCommandBlock(); case "command_minecart" -> getCommandMinecart(); case "world" -> world; default -> super.getContext(name); }; } @Override public ScriptEntryData getScriptEntryData() { PlayerTag player = null; if (source instanceof Player) { player = new PlayerTag((Player) source); } return new BukkitScriptEntryData(player, null); } @EventHandler public void onGameRuleChanged(WorldGameRuleChangeEvent event) { this.source = event.getCommandSender(); this.world = new WorldTag(event.getWorld()); this.event = event; fire(event); } public LocationTag getCommandBlock() { if (source instanceof BlockCommandSender) return new LocationTag(((BlockCommandSender) source).getBlock().getLocation()); return null; } public EntityTag getCommandMinecart() { if (source instanceof CommandMinecart) return new EntityTag(((CommandMinecart) source)); return null; } public ElementTag getSourceType() { if (source instanceof Player) { return new ElementTag("player"); } else if (source instanceof BlockCommandSender) { return new ElementTag("command_block"); } else if (source instanceof CommandMinecart) { return new ElementTag("command_minecart"); } else { return new ElementTag("server"); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityArmsRaised.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.destroystokyo.paper.entity.RangedEntity; @Deprecated public class EntityArmsRaised implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof RangedEntity; } public static EntityArmsRaised getFrom(ObjectTag _entity) { if (!describes(_entity)) { return null; } else { return new EntityArmsRaised((EntityTag) _entity); } } public EntityArmsRaised(EntityTag _entity) { entity = _entity; } EntityTag entity; @Override public String getPropertyString() { return null; } @Override public String getPropertyId() { return "arms_raised"; } public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism EntityTag.arms_raised // @group properties // @Plugin Paper // @deprecated use 'aggressive' // @description // Deprecated in favor of <@link tag EntityTag.aggressive>. // --> PropertyParser.registerTag(EntityArmsRaised.class, ElementTag.class, "arms_raised", (attribute, object) -> { BukkitImplDeprecations.entityArmsRaised.warn(attribute.context); return new ElementTag(object.getRanged().isChargingAttack()); }); // <--[mechanism] // @object EntityTag // @name arms_raised // @input ElementTag(Boolean) // @Plugin Paper // @group properties // @deprecated use 'aggressive' // @description // Deprecated in favor of <@link mechanism EntityTag.aggressive>. // @tags // // --> PropertyParser.registerMechanism(EntityArmsRaised.class, ElementTag.class, "arms_raised", (object, mechanism, input) -> { BukkitImplDeprecations.entityArmsRaised.warn(mechanism.context); if (mechanism.requireBoolean()) { object.getRanged().setChargingAttack(input.asBoolean()); } }); } public RangedEntity getRanged() { return (RangedEntity) entity.getBukkitEntity(); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityAutoExpire.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import org.bukkit.entity.FallingBlock; public class EntityAutoExpire implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof FallingBlock; } public static EntityAutoExpire getFrom(ObjectTag _entity) { if (!describes(_entity)) { return null; } else { return new EntityAutoExpire((EntityTag) _entity); } } public static final String[] handledMechs = new String[] { "auto_expire" }; public EntityAutoExpire(EntityTag _entity) { entity = _entity; } EntityTag entity; public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism EntityTag.auto_expire // @group properties // @Plugin Paper // @description // Returns whether a falling_block will auto-expire (after 30 seconds, or 5 when outside the world). // See also <@link tag EntityTag.time_lived> // --> PropertyParser.registerTag(EntityAutoExpire.class, ElementTag.class, "auto_expire", (attribute, object) -> { return new ElementTag(object.doesAutoExpire()); }); } public FallingBlock getFallingBlock() { return (FallingBlock) entity.getBukkitEntity(); } public boolean doesAutoExpire() { return getFallingBlock().doesAutoExpire(); } @Override public String getPropertyString() { return doesAutoExpire() ? null : "false"; } @Override public String getPropertyId() { return "auto_expire"; } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object EntityTag // @name auto_expire // @input ElementTag(Boolean) // @Plugin Paper // @group properties // @description // Sets whether a falling_block will auto-expire (after 30 seconds, or 5 when outside the world). // See also <@link mechanism EntityTag.time_lived> // @tags // // --> if (mechanism.matches("auto_expire") && mechanism.requireBoolean()) { getFallingBlock().shouldAutoExpire(mechanism.getValue().asBoolean()); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityBodyStingers.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.properties.entity.EntityProperty; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; public class EntityBodyStingers extends EntityProperty { // <--[property] // @object EntityTag // @name body_stingers // @input ElementTag(Number) // @plugin Paper // @description // Controls the number of bee stingers stuck in an entity's body. // Note: Bee stingers will only be visible for players or player-type npcs. // --> public static boolean describes(EntityTag entity) { return entity.isLivingEntity(); } @Override public boolean isDefaultValue(ElementTag value) { return value.asInt() == 0; } @Override public ElementTag getPropertyValue() { return new ElementTag(getLivingEntity().getBeeStingersInBody()); } @Override public String getPropertyId() { return "body_stingers"; } @Override public void setPropertyValue(ElementTag param, Mechanism mechanism) { if (mechanism.requireInteger()) { getLivingEntity().setBeeStingersInBody(param.asInt()); } } public static void register() { autoRegister("body_stingers", EntityBodyStingers.class, ElementTag.class, false); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityCanTick.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.properties.PropertyParser; import org.bukkit.entity.ArmorStand; public class EntityCanTick implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof ArmorStand; } public static EntityCanTick getFrom(ObjectTag entity) { if (!describes(entity)) { return null; } return new EntityCanTick((EntityTag) entity); } public static final String[] handledMechs = new String[] { "can_tick" }; public EntityCanTick(EntityTag entity) { this.entity = entity; } EntityTag entity; @Override public String getPropertyString() { return String.valueOf(((ArmorStand) entity.getBukkitEntity()).canTick()); } @Override public String getPropertyId() { return "can_tick"; } public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism EntityTag.can_tick // @group properties // @Plugin Paper // @description // If the entity is an armor stand, returns whether the armor stand can tick. // --> PropertyParser.registerTag(EntityCanTick.class, ElementTag.class, "can_tick", (attribute, entity) -> { return new ElementTag(((ArmorStand) entity.entity.getBukkitEntity()).canTick()); }); } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object EntityTag // @name can_tick // @input ElementTag(Boolean) // @Plugin Paper // @group properties // @description // Changes whether an armor stand can tick. // @tags // // --> if (mechanism.matches("can_tick") && mechanism.requireBoolean()) { ((ArmorStand) entity.getBukkitEntity()).setCanTick(mechanism.getValue().asBoolean()); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityCarryingEgg.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import org.bukkit.entity.Turtle; public class EntityCarryingEgg implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof Turtle; } public static EntityCarryingEgg getFrom(ObjectTag entity) { if (!describes(entity)) { return null; } else { return new EntityCarryingEgg((EntityTag) entity); } } public static final String[] handledMechs = new String[] { "carrying_egg" }; public EntityCarryingEgg(EntityTag _entity) { entity = _entity; } EntityTag entity; public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism EntityTag.carrying_egg // @group properties // @Plugin Paper // @description // If the entity is a turtle, returns whether it is carrying an egg. A turtle that is carrying an egg isn't visually different, but can't breed and will eventually lay the egg. // --> PropertyParser.registerTag(EntityCarryingEgg.class, ElementTag.class, "carrying_egg", (attribute, entity) -> { return new ElementTag(((Turtle) entity.entity.getBukkitEntity()).hasEgg()); }); } @Override public String getPropertyString() { return ((Turtle) entity.getBukkitEntity()).hasEgg() ? "true" : null; } @Override public String getPropertyId() { return "carrying_egg"; } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object EntityTag // @name carrying_egg // @input ElementTag(Boolean) // @Plugin Paper // @group properties // @description // If the entity is a turtle, sets whether it is carrying an egg. // @tags // // --> if (mechanism.matches("carrying_egg") && mechanism.requireBoolean()) { ((Turtle) entity.getBukkitEntity()).setHasEgg(mechanism.getValue().asBoolean()); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityDrinkingPotion.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import org.bukkit.Material; import org.bukkit.entity.Witch; public class EntityDrinkingPotion implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof Witch; } public static EntityDrinkingPotion getFrom(ObjectTag _entity) { if (!describes(_entity)) { return null; } else { return new EntityDrinkingPotion((EntityTag) _entity); } } public static final String[] handledMechs = new String[] { "drinking_potion", "potion_drink_duration" }; public EntityDrinkingPotion(EntityTag _entity) { entity = _entity; } EntityTag entity; public static void register() { // <--[tag] // @attribute // @returns ItemTag // @mechanism EntityTag.drinking_potion // @group properties // @Plugin Paper // @description // Returns the potion item a witch is drinking, or air if none. // --> PropertyParser.registerTag(EntityDrinkingPotion.class, ItemTag.class, "drinking_potion", (attribute, object) -> { return new ItemTag(object.getWitch().getDrinkingPotion()); }); // <--[tag] // @attribute // @returns DurationTag // @mechanism EntityTag.potion_drink_duration // @group properties // @Plugin Paper // @description // Returns the duration remaining until a witch is done drinking a potion. // --> PropertyParser.registerTag(EntityDrinkingPotion.class, DurationTag.class, "potion_drink_duration", (attribute, object) -> { return new DurationTag((long) object.getWitch().getPotionUseTimeLeft()); }); } public Witch getWitch() { return (Witch) entity.getBukkitEntity(); } @Override public String getPropertyString() { return null; } @Override public String getPropertyId() { return "drinking_potion"; } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object EntityTag // @name drinking_potion // @input ItemTag // @Plugin Paper // @group properties // @description // Sets the potion item a witch is drinking. // @tags // // --> if (mechanism.matches("drinking_potion") && mechanism.requireObject(ItemTag.class)) { ItemTag potion = mechanism.valueAsType(ItemTag.class); if (potion.getBukkitMaterial() != Material.POTION) { mechanism.echoError("Invalid item input '" + potion + "': item must be a potion"); return; } getWitch().setDrinkingPotion(potion.getItemStack()); } // <--[mechanism] // @object EntityTag // @name potion_drink_duration // @input DurationTag // @Plugin Paper // @group properties // @description // Sets the duration remaining until a witch is done drinking a potion. // @tags // // --> if (mechanism.matches("potion_drink_duration") && mechanism.requireObject(DurationTag.class)) { getWitch().setPotionUseTimeLeft(mechanism.valueAsType(DurationTag.class).getTicksAsInt()); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityEggLayTime.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.properties.entity.EntityProperty; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.DurationTag; import org.bukkit.entity.Chicken; public class EntityEggLayTime extends EntityProperty { // <--[property] // @object EntityTag // @name egg_lay_time // @input DurationTag // @plugin Paper // @description // If the entity is a chicken, controls the duration of time until it next lays an egg. // --> public static boolean describes(EntityTag entity) { return entity.getBukkitEntity() instanceof Chicken; } @Override public DurationTag getPropertyValue() { return new DurationTag((long) as(Chicken.class).getEggLayTime()); } @Override public String getPropertyId() { return "egg_lay_time"; } @Override public void setPropertyValue(DurationTag param, Mechanism mechanism) { as(Chicken.class).setEggLayTime(param.getTicksAsInt()); } public static void register() { autoRegister("egg_lay_time", EntityEggLayTime.class, DurationTag.class, false); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityFriction.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import io.papermc.paper.entity.Frictional; import net.kyori.adventure.util.TriState; public class EntityFriction implements Property { public static boolean describes(ObjectTag object) { return object instanceof EntityTag entityTag && entityTag.getBukkitEntity() instanceof Frictional; } public static EntityFriction getFrom(ObjectTag entity) { if (!describes(entity)) { return null; } return new EntityFriction((EntityTag) entity); } public EntityFriction(EntityTag ent) { entity = ent; } EntityTag entity; public Frictional getFrictional() { return (Frictional) entity.getBukkitEntity(); } @Override public String getPropertyString() { Boolean frictionState = getFrictional().getFrictionState().toBoolean(); if (frictionState == null) { return null; } return String.valueOf(frictionState); } @Override public String getPropertyId() { return "has_friction"; } public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism EntityTag.has_friction // @group properties // @Plugin Paper // @description // Returns an entity's friction state if one has been set. // --> PropertyParser.registerTag(EntityFriction.class, ElementTag.class, "has_friction", (attribute, object) -> { Boolean frictionState = object.getFrictional().getFrictionState().toBoolean(); if (frictionState == null) { return null; } return new ElementTag(frictionState); }); // <--[mechanism] // @object EntityTag // @name has_friction // @input ElementTag(Boolean) // @Plugin Paper // @group properties // @description // Forces an entity into a friction state, so it either always or never experiences friction. // An entity with no friction will move in a direction forever until its velocity is changed or it impacts a block. // Does not work with players. Provide empty input to reset an entity back to its vanilla friction behavior. // @tags // // --> PropertyParser.registerMechanism(EntityFriction.class, ElementTag.class, "has_friction", (object, mechanism, input) -> { if (!mechanism.hasValue()) { object.getFrictional().setFrictionState(TriState.NOT_SET); } else if (mechanism.requireBoolean()) { object.getFrictional().setFrictionState(TriState.byBoolean(input.asBoolean())); } }); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityLeftHanded.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.properties.entity.EntityProperty; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import org.bukkit.entity.Mob; public class EntityLeftHanded extends EntityProperty { // <--[property] // @object EntityTag // @name left_handed // @input ElementTag(Boolean) // @plugin Paper // @description // Whether a mob is left-handed. Mobs have a rare chance of spawning left-handed. // --> public static boolean describes(EntityTag entity) { return entity.getBukkitEntity() instanceof Mob; } @Override public ElementTag getPropertyValue() { return new ElementTag(as(Mob.class).isLeftHanded()); } @Override public String getPropertyId() { return "left_handed"; } @Override public void setPropertyValue(ElementTag param, Mechanism mechanism) { if (mechanism.requireBoolean()) { as(Mob.class).setLeftHanded(param.asBoolean()); } } public static void register() { autoRegister("left_handed", EntityLeftHanded.class, ElementTag.class, false); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityReputation.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.denizenscript.denizencore.utilities.text.StringHolder; import com.destroystokyo.paper.entity.villager.Reputation; import com.destroystokyo.paper.entity.villager.ReputationType; import org.bukkit.entity.Villager; import java.util.Map; import java.util.UUID; public class EntityReputation implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof Villager; } public static EntityReputation getFrom(ObjectTag _entity) { if (!describes(_entity)) { return null; } else { return new EntityReputation((EntityTag) _entity); } } public EntityReputation(EntityTag _entity) { entity = _entity; } EntityTag entity; @Override public String getPropertyString() { return getReputationMap().identify(); } @Override public String getPropertyId() { return "reputation"; } public static void register() { // <--[tag] // @attribute // @returns MapTag // @mechanism EntityTag.reputation // @group properties // @Plugin Paper // @description // Returns a villager's reputations as a map of player UUIDs to reputation maps. // Reputation maps are maps of reputation types to integer values, a full list of all valid reputation types can be found at <@link url https://jd.papermc.io/paper/1.19/com/destroystokyo/paper/entity/villager/ReputationType.html>. // --> PropertyParser.registerTag(EntityReputation.class, MapTag.class, "reputation", (attribute, object) -> { return object.getReputationMap(); }); // <--[mechanism] // @object EntityTag // @name reputation // @input MapTag // @Plugin Paper // @group properties // @description // Sets a villager's reputations as a map of player UUIDs to reputation maps. // Reputation maps are maps of reputation types to integer values, a full list of all valid reputation types can be found at <@link url https://jd.papermc.io/paper/1.19/com/destroystokyo/paper/entity/villager/ReputationType.html>. // @tags // // --> PropertyParser.registerMechanism(EntityReputation.class, MapTag.class, "reputation", (object, mechanism, input) -> { Villager villager = object.getVillager(); villager.clearReputations(); for (Map.Entry entry : input.entrySet()) { UUID uuid; try { uuid = UUID.fromString(entry.getKey().str); } catch (IllegalArgumentException exception) { mechanism.echoError("Invalid uuid specified: " + entry.getKey().str); continue; } MapTag reputationInput = entry.getValue().asType(MapTag.class, mechanism.context); if (reputationInput == null) { mechanism.echoError("Invalid reputation map specified: " + entry.getValue()); continue; } Reputation reputation = new Reputation(); for (Map.Entry reputationEntry : reputationInput.entrySet()) { ReputationType reputationType = new ElementTag(reputationEntry.getKey().low).asEnum(ReputationType.class); if (reputationType == null) { mechanism.echoError("Invalid reputation type specified: " + reputationEntry.getKey().str); continue; } reputation.setReputation(reputationType, reputationEntry.getValue().asElement().asInt()); } villager.setReputation(uuid, reputation); } }); } public Villager getVillager() { return (Villager) entity.getBukkitEntity(); } public MapTag getReputationMap() { MapTag result = new MapTag(); for (Map.Entry entry : getVillager().getReputations().entrySet()) { MapTag reputationMap = new MapTag(); Reputation reputation = entry.getValue(); for (ReputationType reputationType : ReputationType.values()) { reputationMap.putObject(reputationType.name(), new ElementTag(reputation.getReputation(reputationType))); } result.putObject(entry.getKey().toString(), reputationMap); } return result; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityShouldBurn.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.properties.entity.EntityProperty; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import org.bukkit.entity.*; public class EntityShouldBurn extends EntityProperty { // <--[property] // @object EntityTag // @name should_burn // @input ElementTag(Boolean) // @plugin Paper // @description // If the entity is a Zombie, Skeleton, Stray, Bogged, or Phantom, controls whether it should burn in daylight. // --> public static boolean describes(EntityTag entity) { return entity.getBukkitEntity() instanceof Zombie || entity.getBukkitEntity() instanceof Phantom || entity.getBukkitEntity() instanceof Skeleton || entity.getBukkitEntity() instanceof Stray || (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && entity.getBukkitEntity() instanceof Bogged); } @Override public ElementTag getPropertyValue() { if (getEntity() instanceof Zombie zombie) { return new ElementTag(zombie.shouldBurnInDay()); } else if (getEntity() instanceof Phantom phantom) { return new ElementTag(phantom.shouldBurnInDay()); } else if (getEntity() instanceof Skeleton skeleton) { return new ElementTag(skeleton.shouldBurnInDay()); } else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getEntity() instanceof Bogged bogged) { return new ElementTag(bogged.shouldBurnInDay()); } else { // stray return new ElementTag(as(Stray.class).shouldBurnInDay()); } } @Override public String getPropertyId() { return "should_burn"; } @Override public void setPropertyValue(ElementTag param, Mechanism mechanism) { if (mechanism.requireBoolean()) { if (getEntity() instanceof Zombie zombie) { zombie.setShouldBurnInDay(param.asBoolean()); } else if (getEntity() instanceof Phantom phantom) { phantom.setShouldBurnInDay(param.asBoolean()); } else if (getEntity() instanceof Skeleton skeleton) { skeleton.setShouldBurnInDay(param.asBoolean()); } else if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && getEntity() instanceof Bogged bogged) { bogged.setShouldBurnInDay(param.asBoolean()); } else { // stray as(Stray.class).setShouldBurnInDay(param.asBoolean()); } } } public static void register() { autoRegister("should_burn", EntityShouldBurn.class, ElementTag.class, false); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntitySneaking.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.npc.traits.SneakingTrait; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.properties.entity.EntityProperty; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import net.citizensnpcs.api.npc.NPC; public class EntitySneaking extends EntityProperty { // <--[property] // @object EntityTag // @name is_sneaking // @input ElementTag(Boolean) // @plugin Paper // @description // Whether an entity is sneaking. // For most entities this just makes the name tag less visible, and doesn't actually update the pose. // Note that <@link command sneak> is also available. // --> public static boolean describes(EntityTag entity) { return true; } @Override public ElementTag getPropertyValue() { return new ElementTag(getEntity().isSneaking()); } @Override public boolean isDefaultValue(ElementTag value) { return !value.asBoolean(); } @Override public void setPropertyValue(ElementTag value, Mechanism mechanism) { if (mechanism.requireBoolean()) { boolean sneaking = value.asBoolean(); getEntity().setSneaking(sneaking); if (object.isCitizensNPC()) { NPC npc = object.getDenizenNPC().getCitizen(); if (sneaking) { npc.getOrAddTrait(SneakingTrait.class).sneak(); } else if (npc.hasTrait(SneakingTrait.class)) { npc.getTraitNullable(SneakingTrait.class).stand(); npc.removeTrait(SneakingTrait.class); } } } } @Override public String getPropertyId() { return "is_sneaking"; } public static void register() { autoRegister("is_sneaking", EntitySneaking.class, ElementTag.class, false); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/EntityWitherInvulnerable.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import org.bukkit.entity.Wither; public class EntityWitherInvulnerable implements Property { public static boolean describes(ObjectTag entity) { return entity instanceof EntityTag && ((EntityTag) entity).getBukkitEntity() instanceof Wither; } public static EntityWitherInvulnerable getFrom(ObjectTag _entity) { if (!describes(_entity)) { return null; } else { return new EntityWitherInvulnerable((EntityTag) _entity); } } public static final String[] handledMechs = new String[]{ "invulnerable_duration" }; public EntityWitherInvulnerable(EntityTag _entity) { entity = _entity; } EntityTag entity; public static void register() { // <--[tag] // @attribute // @returns DurationTag // @mechanism EntityTag.invulnerable_duration // @group properties // @Plugin Paper // @description // Returns the duration remaining until the wither becomes vulnerable. // --> PropertyParser.registerTag(EntityWitherInvulnerable.class, DurationTag.class, "invulnerable_duration", (attribute, object) -> { return new DurationTag((long) object.getWither().getInvulnerableTicks()); }); } public Wither getWither() { return (Wither) entity.getBukkitEntity(); } @Override public String getPropertyString() { int ticks = getWither().getInvulnerableTicks(); if (ticks == 0) { return null; } return new DurationTag((long) ticks).identify(); } @Override public String getPropertyId() { return "invulnerable_duration"; } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object EntityTag // @name invulnerable_duration // @input DurationTag // @Plugin Paper // @group properties // @description // Sets the duration remaining until the wither becomes vulnerable. // @tags // // --> if (mechanism.matches("invulnerable_duration") && mechanism.requireObject(DurationTag.class)) { getWither().setInvulnerableTicks(mechanism.valueAsType(DurationTag.class).getTicksAsInt()); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/ItemArmorStand.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.objects.properties.Property; import com.denizenscript.denizencore.objects.properties.PropertyParser; import com.destroystokyo.paper.inventory.meta.ArmorStandMeta; import org.bukkit.Material; public class ItemArmorStand implements Property { public static boolean describes(ObjectTag item) { return item instanceof ItemTag && ((ItemTag) item).getBukkitMaterial() == Material.ARMOR_STAND; } public static ItemArmorStand getFrom(ObjectTag item) { if (!describes(item)) { return null; } return new ItemArmorStand((ItemTag) item); } public static final String[] handledMechs = new String[] { "armor_stand_data" }; public ItemArmorStand(ItemTag item) { this.item = item; } ItemTag item; public MapTag getDataMap() { ArmorStandMeta meta = (ArmorStandMeta) item.getItemMeta(); if (meta == null) { return null; } MapTag result = new MapTag(); result.putObject("base_plate", new ElementTag(!meta.hasNoBasePlate())); result.putObject("visible", new ElementTag(!meta.isInvisible())); result.putObject("marker", new ElementTag(meta.isMarker())); result.putObject("is_small", new ElementTag(meta.isSmall())); result.putObject("arms", new ElementTag(meta.shouldShowArms())); return result; } @Override public String getPropertyString() { MapTag result = getDataMap(); if (result == null) { return null; } return result.toString(); } @Override public String getPropertyId() { return "armor_stand_data"; } public static void register() { // <--[tag] // @attribute // @returns MapTag // @mechanism ItemTag.armor_stand_data // @group properties // @Plugin Paper // @description // Returns a map of basic armor stand data, with keys matching EntityTag property names. // Keys: base_plate, visible, marker, is_small, arms // --> PropertyParser.registerTag(ItemArmorStand.class, MapTag.class, "armor_stand_data", (attribute, item) -> { return item.getDataMap(); }); } @Override public void adjust(Mechanism mechanism) { // <--[mechanism] // @object ItemTag // @name armor_stand_data // @input MapTag // @Plugin Paper // @group properties // @description // Sets a map of basic armor stand data, with keys matching EntityTag property names. // Allowed keys: base_plate, visible, marker, is_small, arms // @tags // // --> if (mechanism.matches("armor_stand_data") && mechanism.requireObject(MapTag.class)) { MapTag map = mechanism.valueAsType(MapTag.class); ArmorStandMeta meta = (ArmorStandMeta) item.getItemMeta(); ElementTag base_plate = map.getElement("base_plate"); ElementTag visible = map.getElement("visible"); ElementTag marker = map.getElement("marker"); ElementTag is_small = map.getElement("is_small"); ElementTag arms = map.getElement("arms"); if (base_plate != null) { meta.setNoBasePlate(!base_plate.asBoolean()); } if (visible != null) { meta.setInvisible(!visible.asBoolean()); } if (marker != null) { meta.setMarker(marker.asBoolean()); } if (is_small != null) { meta.setSmall(is_small.asBoolean()); } if (arms != null) { meta.setShowArms(arms.asBoolean()); } item.setItemMeta(meta); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/ItemRemovedComponents.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.properties.item.ItemProperty; import com.denizenscript.denizen.paper.datacomponents.DataComponentAdapter; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.properties.PropertyParser; import io.papermc.paper.datacomponent.DataComponentType; public class ItemRemovedComponents extends ItemProperty { // <--[property] // @object ItemTag // @name removed_components // @input ListTag // @description // Controls the item components explicitly removed from an item. // This can be used to remove item's default behavior, such as making consumable items non-consumable. // Alternatively, use <@link mechanism ItemTag.remove_component> to remove a single component. // See <@link language Item Components> for more information. // --> public static boolean describes(ItemTag item) { return !item.getItemStack().isEmpty(); } public boolean isRemoved(DataComponentType componentType) { return getItemStack().isDataOverridden(componentType) && !getItemStack().hasData(componentType); } @Override public ListTag getPropertyValue() { return new ListTag(getMaterial().getDefaultDataTypes(), this::isRemoved, componentType -> new ElementTag(componentType.key().asMinimalString(), true)); } @Override public boolean isDefaultValue(ListTag value) { return value.isEmpty(); } @Override public void setPropertyValue(ListTag value, Mechanism mechanism) { for (DataComponentType componentType : getMaterial().getDefaultDataTypes()) { if (isRemoved(componentType)) { getItemStack().resetData(componentType); } } for (String input : value) { DataComponentType componentType = DataComponentAdapter.getComponentType(input); if (componentType == null) { mechanism.echoError("Invalid type to remove '" + input + "' specified: must be a valid property or item component name."); continue; } getItemStack().unsetData(componentType); } } @Override public String getPropertyId() { return "removed_components"; } public static void register() { autoRegister("removed_components", ItemRemovedComponents.class, ListTag.class, false); // <--[mechanism] // @object ItemTag // @name remove_component // @input ElementTag // @description // Removes the specified item component from the item, see <@link language Item Components> for more information. // This can be used to remove item's default behavior, such as making consumable items non-consumable. // See also <@link property ItemTag.removed_components>. // --> PropertyParser.registerMechanism(ItemRemovedComponents.class, ElementTag.class, "remove_component", (prop, mechanism, input) -> { DataComponentType componentType = DataComponentAdapter.getComponentType(input.asString()); if (componentType == null) { mechanism.echoError("Invalid type to remove specified: must be a valid property or item component name."); return; } prop.getItemStack().unsetData(componentType); }); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperElementExtensions.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.objects.core.ElementTag; import net.kyori.adventure.text.minimessage.MiniMessage; public class PaperElementExtensions { public static void register() { if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { // <--[tag] // @attribute // @returns ElementTag // @Plugin Paper // @group paper // @description // Returns the element with all MiniMessage tags parsed, see <@link url https://docs.adventure.kyori.net/minimessage/format.html> for more information. // This may be useful for reading data from external plugins, but should not be used in normal scripts. // --> ElementTag.tagProcessor.registerTag(ElementTag.class, "parse_minimessage", (attribute, object) -> { return new ElementTag(PaperModule.stringifyComponent(MiniMessage.miniMessage().deserialize(object.asString()))); }); // <--[tag] // @attribute // @returns ElementTag // @Plugin Paper // @group paper // @description // Returns the element with all text formatting parsed into MiniMessage format. // This may be useful for sending data to external plugins, but should not be used in normal scripts. // --> ElementTag.tagProcessor.registerTag(ElementTag.class, "to_minimessage", (attribute, object) -> { return new ElementTag(PaperAPITools.instance.convertTextToMiniMessage(object.asString(), false)); }); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperEntityExtensions.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.EntityFormObject; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.MapTag; import io.papermc.paper.entity.Shearable; import net.kyori.adventure.sound.Sound; import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Goat; import org.bukkit.inventory.EquipmentSlot; import java.util.UUID; public class PaperEntityExtensions { public static void register() { // <--[tag] // @attribute // @returns ElementTag // @group paper // @Plugin Paper // @description // Returns the entity's spawn reason. // Valid spawn reasons can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/entity/CreatureSpawnEvent.SpawnReason.html> // --> EntityTag.tagProcessor.registerTag(ElementTag.class, "spawn_reason", (attribute, entity) -> { return new ElementTag(entity.getBukkitEntity().getEntitySpawnReason()); }); // <--[tag] // @attribute // @returns ElementTag // @group paper // @Plugin Paper // @description // If the entity is an experience orb, returns its spawn reason. // Valid spawn reasons can be found at <@link url https://papermc.io/javadocs/paper/1.17/org/bukkit/entity/ExperienceOrb.SpawnReason.html> // --> EntityTag.tagProcessor.registerTag(ElementTag.class, "xp_spawn_reason", (attribute, entity) -> { if (!(entity.getBukkitEntity() instanceof ExperienceOrb experienceOrb)) { attribute.echoError("Entity " + entity + " is not an experience orb."); return null; } return new ElementTag(experienceOrb.getSpawnReason()); }); // <--[tag] // @attribute // @returns EntityTag // @group paper // @Plugin Paper // @description // If the entity is an experience orb, returns the entity that triggered it spawning (if any). // For example, if a player killed an entity this would return the player. // --> EntityTag.tagProcessor.registerTag(EntityFormObject.class, "xp_trigger", (attribute, entity) -> { if (!(entity.getBukkitEntity() instanceof ExperienceOrb experienceOrb)) { attribute.echoError("Entity " + entity + " is not an experience orb."); return null; } UUID uuid = experienceOrb.getTriggerEntityId(); if (uuid == null) { return null; } Entity e = EntityTag.getEntityForID(uuid); if (e == null) { return null; } return new EntityTag(e).getDenizenObject(); }); // <--[tag] // @attribute // @returns EntityTag // @group paper // @Plugin Paper // @description // If the entity is an experience orb, returns the entity that it was created from (if any). // For example, if the xp orb was spawned from breeding this would return the baby. // --> EntityTag.registerSpawnedOnlyTag(EntityFormObject.class, "xp_source", (attribute, entity) -> { if (!(entity.getBukkitEntity() instanceof ExperienceOrb experienceOrb)) { attribute.echoError("Entity " + entity + " is not an experience orb."); return null; } UUID uuid = experienceOrb.getSourceEntityId(); if (uuid == null) { return null; } Entity e = EntityTag.getEntityForID(uuid); if (e == null) { return null; } return new EntityTag(e).getDenizenObject(); }); // <--[tag] // @attribute // @returns LocationTag // @group paper // @Plugin Paper // @description // Returns the initial spawn location of this entity. // --> EntityTag.tagProcessor.registerTag(LocationTag.class, "spawn_location", (attribute, entity) -> { Location loc = entity.getBukkitEntity().getOrigin(); return loc != null ? new LocationTag(loc) : null; }); // <--[tag] // @attribute // @returns ElementTag(Boolean) // @group paper // @Plugin Paper // @description // Returns whether the entity was spawned from a spawner. // --> EntityTag.tagProcessor.registerTag(ElementTag.class, "from_spawner", (attribute, entity) -> { return new ElementTag(entity.getBukkitEntity().fromMobSpawner()); }); // <--[mechanism] // @object EntityTag // @name goat_ram // @input EntityTag // @Plugin Paper // @group paper // @description // Causes a goat to ram the specified entity. // --> EntityTag.registerSpawnedOnlyMechanism("goat_ram", false, EntityTag.class, (object, mechanism, input) -> { if (object.getBukkitEntity() instanceof Goat goat) { goat.ram(input.getLivingEntity()); } }); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { // <--[tag] // @attribute ]> // @returns ElementTag(Boolean) // @group paper // @Plugin Paper // @description // Returns whether the entity's bounding box would collide if the entity was moved to the given location. // This checks for any colliding entities (like boats and shulkers), the world border and regular blocks. // (Note that this won't load chunks at the location.) // --> EntityTag.tagProcessor.registerTag(ElementTag.class, LocationTag.class, "collides_at", (attribute, entity, location) -> { return new ElementTag(entity.getBukkitEntity().collidesAt(location)); }); // <--[mechanism] // @object EntityTag // @name damage_item // @input MapTag // @Plugin Paper // @group paper // @description // Damages the given equipment slot for the given amount. // This runs all vanilla logic associated with damaging an item like gamemode and enchantment checks, events, stat changes, advancement triggers, and notifying clients to play break animations. // Input is a map with "slot" as a valid equipment slot, and "amount" as the damage amount to be dealt. // Valid equipment slot values can be found at <@link url https://hub.spigotmc.org/javadocs/spigot/org/bukkit/inventory/EquipmentSlot.html>. // // @example // # Damages your precious boots! :( // - adjust damage_item:[slot=feet;amount=45] // --> EntityTag.registerSpawnedOnlyMechanism("damage_item", false, MapTag.class, (object, mechanism, input) -> { ElementTag slot = input.getElement("slot"); ElementTag amount = input.getElement("amount"); if (slot == null || !slot.matchesEnum(EquipmentSlot.class)) { mechanism.echoError("Must specify a valid equipment slot to damage."); return; } if (amount == null || !amount.isInt()) { mechanism.echoError("Must specify a valid amount to damage this item for."); return; } object.getLivingEntity().damageItemStack(slot.asEnum(EquipmentSlot.class), amount.asInt()); }); // <--[mechanism] // @object EntityTag // @name shear // @input None // @Plugin paper // @group paper // @description // Shears entities in the same way as a player can do using shears, including drops. // If the entity is not ready to be sheared, there will be no drops but the sound will still play. // // This mech will: // - Shear a sheep // - harvest a bogged // - harvest a mushroom cow (note: entity data will be lost as Minecraft will remove the entity and spawn an entirely new cow instead) // - derp a snowman (i.e. remove the pumpkin) // // Optionally, specify a sound source to change the source of the sound. // Valid sound sources can be found here: <@link url https://jd.advntr.dev/api/latest/net/kyori/adventure/sound/Sound.Source.html>. // // @example // # Shears the entity you're looking at. // - adjust shear // // --> EntityTag.registerSpawnedOnlyMechanism("shear", false, (object, mechanism) -> { if (!(object.getBukkitEntity() instanceof Shearable shearable)) { return; } if (!mechanism.hasValue()) { shearable.shear(); return; } ElementTag input = mechanism.getValue(); if (!mechanism.requireEnum(Sound.Source.class)) { mechanism.echoError("Invalid sound source specified: " + input); return; } Sound.Source source = input.asEnum(Sound.Source.class); shearable.shear(source); }); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperItemExtensions.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizencore.objects.core.ElementTag; public class PaperItemExtensions { public static void register() { if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) { ItemTag.tagProcessor.registerTag(ElementTag.class, "rarity", (attribute, item) -> { return new ElementTag(item.getItemStack().getRarity()); }); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperPlayerExtensions.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.destroystokyo.paper.ClientOption; import com.destroystokyo.paper.SkinParts; import net.kyori.adventure.util.TriState; import org.bukkit.Material; import org.bukkit.entity.Player; public class PaperPlayerExtensions { public static void register() { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism PlayerTag.affects_monster_spawning // @group paper // @Plugin Paper // @description // Returns whether the player affects monster spawning. When false, no monsters will spawn naturally because of this player. // --> PlayerTag.registerOnlineOnlyTag(ElementTag.class, "affects_monster_spawning", (attribute, object) -> { return new ElementTag(object.getPlayerEntity().getAffectsSpawning()); }); // <--[tag] // @attribute // @returns MapTag // @group paper // @Plugin Paper // @description // Returns the player's client options. // The output map contains the following keys: // - 'allow_server_listings' (ElementTag(Boolean)): whether the player allows server listings. Available only on MC 1.19+. // - 'chat_colors_enabled' (ElementTag(Boolean)): whether the player has chat colors enabled. // - 'chat_visibility' (ElementTag): the player's current chat visibility option. Possible output values are: FULL, SYSTEM, HIDDEN, and UNKNOWN. // - 'locale' (ElementTag): the player's current locale. // - 'main_hand' (ElementTag): the player's main hand, either LEFT or RIGHT. // - 'skin_parts' (MapTag): which skin parts the player has enabled. The output map contains the following keys: // - 'cape' (ElementTag(Boolean)): whether the player's cape is enabled. // - 'hat' (ElementTag(Boolean)): whether the player's hat is enabled. // - 'jacket' (ElementTag(Boolean)): whether the player's jacket is enabled. // - 'left_sleeve' (ElementTag(Boolean)): whether the player's left sleeve is enabled. // - 'right_sleeve' (ElementTag(Boolean)): whether the player's right sleeve is enabled. // - 'left_pants' (ElementTag(Boolean)): whether the player's left pants is enabled. // - 'right_pants' (ElementTag(Boolean)): whether the player's right pants is enabled. // - 'text_filtering_enabled' (ElementTag(Boolean)): whether the player has text filtering enabled. Available only on MC 1.19+. // - 'view_distance' (ElementTag(Number)): the player's current view distance. // --> PlayerTag.registerOnlineOnlyTag(MapTag.class, "client_options", (attribute, object) -> { MapTag map = new MapTag(); Player player = object.getPlayerEntity(); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { map.putObject("allow_server_listings", new ElementTag(player.getClientOption(ClientOption.ALLOW_SERVER_LISTINGS))); map.putObject("text_filtering_enabled", new ElementTag(player.getClientOption(ClientOption.TEXT_FILTERING_ENABLED))); } map.putObject("chat_colors_enabled", new ElementTag(player.getClientOption(ClientOption.CHAT_COLORS_ENABLED))); map.putObject("chat_visibility", new ElementTag(player.getClientOption(ClientOption.CHAT_VISIBILITY))); map.putObject("locale", new ElementTag(player.getClientOption(ClientOption.LOCALE))); map.putObject("main_hand", new ElementTag(player.getClientOption(ClientOption.MAIN_HAND))); MapTag skinParts = new MapTag(); SkinParts parts = player.getClientOption(ClientOption.SKIN_PARTS); skinParts.putObject("cape", new ElementTag(parts.hasCapeEnabled())); skinParts.putObject("hat", new ElementTag(parts.hasHatsEnabled())); skinParts.putObject("jacket", new ElementTag(parts.hasJacketEnabled())); skinParts.putObject("left_sleeve", new ElementTag(parts.hasLeftSleeveEnabled())); skinParts.putObject("right_sleeve", new ElementTag(parts.hasRightSleeveEnabled())); skinParts.putObject("left_pants", new ElementTag(parts.hasLeftPantsEnabled())); skinParts.putObject("right_pants", new ElementTag(parts.hasRightPantsEnabled())); map.putObject("skin_parts", skinParts); map.putObject("view_distance", new ElementTag(player.getClientOption(ClientOption.VIEW_DISTANCE))); return map; }); // <--[tag] // @attribute // @returns ElementTag(Number) // @mechanism PlayerTag.view_distance // @group paper // @Plugin Paper // @description // Returns this player's view distance, or the view distance of the world they're in if unset. // --> PlayerTag.registerOnlineOnlyTag(ElementTag.class, "view_distance", (attribute, object) -> { return new ElementTag(object.getPlayerEntity().getViewDistance()); }); // <--[mechanism] // @object PlayerTag // @name affects_monster_spawning // @input ElementTag(Boolean) // @Plugin Paper // @group paper // @description // Sets whether this player affects monster spawning. When false, no monsters will spawn naturally because of this player. // @tags // // --> PlayerTag.registerOnlineOnlyMechanism("affects_monster_spawning", ElementTag.class, (object, mechanism, input) -> { if (mechanism.requireBoolean()) { object.getPlayerEntity().setAffectsSpawning(input.asBoolean()); } }); // <--[mechanism] // @object PlayerTag // @name firework_boost // @input ItemTag // @Plugin Paper // @group paper // @description // Firework boosts the player with the specified firework rocket. // The player must be gliding. // --> PlayerTag.registerOnlineOnlyMechanism("firework_boost", ItemTag.class, (object, mechanism, input) -> { if (!object.getPlayerEntity().isGliding()) { mechanism.echoError("Cannot adjust 'firework_boost': player must be gliding."); return; } if (input.getBukkitMaterial() != Material.FIREWORK_ROCKET) { mechanism.echoError("Invalid input item '" + input + "': must be a firework rocket."); return; } object.getPlayerEntity().boostElytra(input.getItemStack()); }); // <--[mechanism] // @object PlayerTag // @name fake_op_level // @input ElementTag(Number) // @Plugin Paper // @group paper // @description // Sends a fake operator level to the client, enabling clientside op-required features like the debug gamemode hotkey (F3+F4). // Input should be a number from 0 to 4, 0 indicating not op and 4 indicating maximum level op. // The input number value corresponds to "op-permission-level" in the server.properties. See also <@link url https://minecraft.wiki/w/Permission_level> // This will be reset when a player rejoins, changes world, has their real op status changed, ... // --> PlayerTag.registerOnlineOnlyMechanism("fake_op_level", ElementTag.class, (object, mechanism, input) -> { if (mechanism.requireInteger()) { object.getPlayerEntity().sendOpLevel((byte) input.asInt()); } }); // <--[mechanism] // @object PlayerTag // @name view_distance // @input ElementTag(Number) // @Plugin Paper // @group paper // @description // Sets this player's view distance. Input must be a number between 2 and 32. // This will be reset when a player rejoins. Provide no input to unset. // @tags // // --> PlayerTag.registerOnlineOnlyMechanism("view_distance", (object, mechanism) -> { if (!mechanism.hasValue()) { object.getPlayerEntity().setViewDistance(-1); } else if (mechanism.requireInteger()) { int distance = mechanism.getValue().asInt(); if (distance < 2 || distance > 32) { mechanism.echoError("Invalid view distance '" + distance + "': must be between 2 and 32."); return; } object.getPlayerEntity().setViewDistance(distance); } }); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { // <--[tag] // @attribute // @returns ElementTag(Boolean) // @mechanism PlayerTag.flying_fall_damage // @group paper // @Plugin Paper // @description // Returns whether the player will take fall damage while <@link tag PlayerTag.can_fly> is true. // --> PlayerTag.registerOnlineOnlyTag(ElementTag.class, "flying_fall_damage", (attribute, object) -> { return new ElementTag(object.getPlayerEntity().hasFlyingFallDamage().toBooleanOrElse(false)); }); // <--[mechanism] // @object PlayerTag // @name add_tab_completions // @input ListTag // @Plugin Paper // @group paper // @description // Adds custom tab completions that will be suggested to the player when typing in chat. // Tab completions added by this mechanism can be removed using <@link mechanism PlayerTag.remove_tab_completions>. // --> PlayerTag.registerOnlineOnlyMechanism("add_tab_completions", ListTag.class, (object, mechanism, input) -> { object.getPlayerEntity().addAdditionalChatCompletions(input); }); // <--[mechanism] // @object PlayerTag // @name remove_tab_completions // @input ListTag // @Plugin Paper // @group paper // @description // Removes custom tab completions added by <@link mechanism PlayerTag.add_tab_completions>. // --> PlayerTag.registerOnlineOnlyMechanism("remove_tab_completions", ListTag.class, (object, mechanism, input) -> { object.getPlayerEntity().removeAdditionalChatCompletions(input); }); // <--[mechanism] // @object PlayerTag // @name flying_fall_damage // @input ElementTag(Boolean) // @Plugin Paper // @group paper // @description // Sets whether the player will take fall damage while <@link mechanism PlayerTag.can_fly> is true. // @tags // // // --> PlayerTag.registerOnlineOnlyMechanism("flying_fall_damage", ElementTag.class, (object, mechanism, input) -> { if (mechanism.requireBoolean()) { object.getPlayerEntity().setFlyingFallDamage(TriState.byBoolean(input.asBoolean())); } }); } } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/properties/PaperWorldExtensions.java ================================================ package com.denizenscript.denizen.paper.properties; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.EntityTag; import com.denizenscript.denizen.objects.LocationTag; import com.denizenscript.denizen.objects.WorldTag; import com.denizenscript.denizen.utilities.BukkitImplDeprecations; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.objects.core.ListTag; import org.bukkit.boss.DragonBattle; public class PaperWorldExtensions { public static void register() { // <--[tag] // @attribute // @returns ElementTag(Number) // @mechanism WorldTag.no_tick_view_distance // @group paper // @deprecated replaced by Minecraft's simulation_distance and view_distance config pairing // @Plugin Paper // @description // Deprecated: replaced by Minecraft's simulation_distance and view_distance config pairing // --> WorldTag.tagProcessor.registerTag(ElementTag.class, "no_tick_view_distance", (attribute, world) -> { BukkitImplDeprecations.paperNoTickViewDistance.warn(attribute.context); return new ElementTag(world.getWorld().getNoTickViewDistance()); }); if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) { // <--[tag] // @attribute // @returns ElementTag(Number) // @group paper // @Plugin Paper // @description // Returns the number of end gateway portals. // Only works if the world is an end world. // --> WorldTag.tagProcessor.registerTag(ElementTag.class, "gateway_count", (attribute, object) -> { DragonBattle battle = object.getWorld().getEnderDragonBattle(); if (battle == null) { attribute.echoError("Provided world is not an end world!"); return null; } return new ElementTag(battle.getGatewayCount()); }); // <--[tag] // @attribute // @returns ListTag(EntityTag) // @group paper // @Plugin Paper // @description // Returns a ListTag of the healing end crystals located on top of the obsidian towers. // Only works if the world is an end world. // --> WorldTag.tagProcessor.registerTag(ListTag.class, "healing_crystals", (attribute, object) -> { DragonBattle battle = object.getWorld().getEnderDragonBattle(); if (battle == null) { attribute.echoError("Provided world is not an end world!"); return null; } return new ListTag(battle.getHealingCrystals(), EntityTag::new); }); // <--[tag] // @attribute // @returns ListTag(EntityTag) // @group paper // @Plugin Paper // @description // Returns a ListTag of the respawn end crystals located at the end exit portal. // Only works if the world is an end world. // --> WorldTag.tagProcessor.registerTag(ListTag.class, "respawn_crystals", (attribute, object) -> { DragonBattle battle = object.getWorld().getEnderDragonBattle(); if (battle == null) { attribute.echoError("Provided world is not an end world!"); return null; } return new ListTag(battle.getRespawnCrystals(), EntityTag::new); }); // <--[mechanism] // @object WorldTag // @name spawn_gateway // @input LocationTag // @group paper // @Plugin Paper // @description // Spawns a new end gateway portal at the specified location. // If no location is specified, tries to spawn a new end gateway using default game mechanics. // Only works if the world is an end world. // --> WorldTag.tagProcessor.registerMechanism("spawn_gateway", false, (object, mechanism) -> { DragonBattle battle = object.getWorld().getEnderDragonBattle(); if (battle == null) { mechanism.echoError("Cannot spawn gateway in non-end world!"); return; } if (!mechanism.hasValue()) { battle.spawnNewGateway(); } else if (mechanism.requireObject(LocationTag.class)) { battle.spawnNewGateway(mechanism.valueAsType(LocationTag.class)); } }); } // <--[mechanism] // @object WorldTag // @name view_distance // @input ElementTag(Number) // @Plugin Paper // @group paper // @description // Sets this world's view distance. All chunks within this radius of a player will be visible to that player. // Input should be a number from 2 to 32. // See also <@link mechanism WorldTag.simulation_distance> // @tags // // // --> WorldTag.tagProcessor.registerMechanism("view_distance", false, ElementTag.class, (object, mechanism, input) -> { if (mechanism.requireInteger()) { int distance = input.asInt(); if (distance < 2 || distance > 32) { mechanism.echoError("View distance must be a number from 2 to 32!"); } else { object.getWorld().setViewDistance(distance); } } }); // <--[mechanism] // @object WorldTag // @name simulation_distance // @input ElementTag(Number) // @Plugin Paper // @group paper // @description // Sets this world's view distance. All chunks within this radius will be tracked by the server. // Input should be a number from 2 to 32. // See also <@link mechanism WorldTag.view_distance> // @tags // // // --> WorldTag.tagProcessor.registerMechanism("simulation_distance", false, ElementTag.class, (object, mechanism, input) -> { if (mechanism.requireInteger()) { int distance = input.asInt(); if (distance < 2 || distance > 32) { mechanism.echoError("View distance must be a number from 2 to 32!"); } else { object.getWorld().setSimulationDistance(distance); } } }); // <--[mechanism] // @object WorldTag // @name no_tick_view_distance // @input ElementTag(Number) // @Plugin Paper // @group paper // @deprecated replaced by Minecraft's simulation_distance and view_distance config pairing // @description // Deprecated: replaced by Minecraft's simulation_distance and view_distance config pairing // @tags // // --> WorldTag.tagProcessor.registerMechanism("no_tick_view_distance", false, (object, mechanism) -> { BukkitImplDeprecations.paperNoTickViewDistance.warn(mechanism.context); if (!mechanism.hasValue()) { object.getWorld().setNoTickViewDistance(-1); } else if (mechanism.requireInteger()) { int distance = mechanism.getValue().asInt(); if (distance < 2 || distance > 32) { mechanism.echoError("View distance must be a number from 2 to 32!"); } else { object.getWorld().setNoTickViewDistance(distance); } } }); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/tags/PaperTagBase.java ================================================ package com.denizenscript.denizen.paper.tags; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.objects.core.ListTag; import com.denizenscript.denizencore.tags.*; import org.bukkit.Bukkit; public class PaperTagBase extends PseudoObjectTagBase { public static PaperTagBase instance; public PaperTagBase() { instance = this; TagManager.registerStaticTagBaseHandler(PaperTagBase.class, "paper", (t) -> instance); } @Override public void register() { // <--[tag] // @attribute // @returns ListTag(DurationTag) // @Plugin Paper // @description // Returns a sample of the server's last 5s of tick times as a list of durations. // On average, a tick should take 50ms or less for a stable 20tps. // --> tagProcessor.registerTag(ListTag.class, "tick_times", (attribute, object) -> { ListTag list = new ListTag(); for (long time : Bukkit.getServer().getTickTimes()) { list.addObject(new DurationTag(time / 1000000000D)); } return list; }); } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/utilities/BlockTagsSetter.java ================================================ package com.denizenscript.denizen.paper.utilities; import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.VanillaTagHelper; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.destroystokyo.paper.event.server.ServerTickEndEvent; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.configuration.PluginMeta; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.TypedKey; import io.papermc.paper.registry.tag.TagKey; import net.kyori.adventure.text.logger.slf4j.ComponentLogger; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.BlockType; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import java.lang.invoke.MethodHandle; import java.nio.file.Path; import java.util.*; import java.util.stream.Collectors; public class BlockTagsSetter implements Listener { public static final MethodHandle BOOTSTRAP_CONTEXT_CONSTRUCTOR; static { try { Class bootstrapContextImplClass = Class.forName("io.papermc.paper.plugin.bootstrap.PluginBootstrapContextImpl"); BOOTSTRAP_CONTEXT_CONSTRUCTOR = ReflectionHelper.getConstructor(bootstrapContextImplClass, PluginMeta.class, Path.class, ComponentLogger.class, Path.class); } catch (Throwable e) { throw new RuntimeException("Failed to initialize BlockTagsSetter", e); } } public static final BlockTagsSetter INSTANCE = new BlockTagsSetter(Denizen.getInstance()); public Map, Set>> modifiedTags = new HashMap<>(); public boolean batchReloadNeeded; public BlockTagsSetter(Denizen plugin) { Bukkit.getPluginManager().registerEvents(this, plugin); try { BootstrapContext fakeContext = (BootstrapContext) BOOTSTRAP_CONTEXT_CONSTRUCTOR.invoke(plugin.getPluginMeta(), plugin.getDataPath(), plugin.getComponentLogger(), plugin.getFile().toPath()); fakeContext.getLifecycleManager().registerEventHandler(LifecycleEvents.TAGS.postFlatten(RegistryKey.BLOCK), event -> { Map, Collection>> allTags = event.registrar().getAllTags(); for (Map.Entry, Set>> entry : modifiedTags.entrySet()) { TypedKey blockType = entry.getKey(); Set> tags = entry.getValue(); for (Map.Entry, Collection>> tagEntry : allTags.entrySet()) { TagKey tagKey = tagEntry.getKey(); Collection> values = tagEntry.getValue(); if (values.contains(blockType) && !tags.contains(tagKey)) { List> modifiedValues = new ArrayList<>(values); modifiedValues.remove(blockType); event.registrar().setTag(tagKey, modifiedValues); } } for (TagKey tag : tags) { event.registrar().addToTag(tag, List.of(blockType)); } } }); } catch (Throwable e) { Debug.echoError(e); } } @EventHandler public void onServerTickEnd(ServerTickEndEvent event) { if (batchReloadNeeded) { batchReloadNeeded = false; Bukkit.reloadData(); } } public void setTags(Material material, Set tags) { TypedKey blockKey = TypedKey.create(RegistryKey.BLOCK, material.getKey()); Set> tagKeys = tags.stream().map(tag -> TagKey.create(RegistryKey.BLOCK, tag)).collect(Collectors.toCollection(HashSet::new)); Set> oldTagKeys = modifiedTags.put(blockKey, tagKeys); if (tagKeys.equals(oldTagKeys)) { return; } VanillaTagHelper.tagsByMaterial.put(material, tags.stream().map(Utilities::namespacedKeyToString).collect(Collectors.toCollection(HashSet::new))); batchReloadNeeded = true; } } ================================================ FILE: paper/src/main/java/com/denizenscript/denizen/paper/utilities/PaperAPIToolsImpl.java ================================================ package com.denizenscript.denizen.paper.utilities; import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.objects.ItemTag; import com.denizenscript.denizen.paper.PaperModule; import com.denizenscript.denizen.scripts.commands.entity.TeleportCommand; import com.denizenscript.denizen.scripts.containers.core.ItemScriptContainer; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; import com.denizenscript.denizen.utilities.FormattedTextHelper; import com.denizenscript.denizen.utilities.PaperAPITools; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.Mechanism; import com.denizenscript.denizencore.objects.core.ElementTag; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.ReflectionHelper; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; import io.papermc.paper.entity.TeleportFlag; import io.papermc.paper.potion.PotionMix; import io.papermc.paper.world.WeatheringCopperState; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.*; import org.bukkit.block.Sign; import org.bukkit.command.CommandSender; import org.bukkit.entity.*; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.*; import org.bukkit.inventory.meta.PotionMeta; import org.bukkit.potion.PotionBrewer; import org.bukkit.scoreboard.Team; import org.bukkit.util.Consumer; import java.net.URI; import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; public class PaperAPIToolsImpl extends PaperAPITools { @Override public Inventory createInventory(InventoryHolder holder, int slots, String title) { return Bukkit.getServer().createInventory(holder, slots, PaperModule.parseFormattedText(title, ChatColor.BLACK)); } @Override public Inventory createInventory(InventoryHolder holder, InventoryType type, String title) { return Bukkit.getServer().createInventory(holder, type, PaperModule.parseFormattedText(title, ChatColor.BLACK)); } @Override public String parseComponent(Object input) { if (input == null) { return null; } if (input instanceof Component) { return PaperModule.stringifyComponent((Component) input); } return super.parseComponent(input); } @Override public String getTitle(Inventory inventory) { // TODO: Paper lacks an inventory.getTitle? 0.o return NMSHandler.instance.getTitle(inventory); } @Override public void setCustomName(Entity entity, String name) { entity.customName(PaperModule.parseFormattedText(name, ChatColor.WHITE)); } @Override public String getCustomName(Entity entity) { return PaperModule.stringifyComponent(entity.customName()); } @Override public BaseComponent[] getCustomNameComponent(Entity entity) { Component customName = entity.customName(); return customName != null ? FormattedTextHelper.parseJson(PaperModule.componentToJson(customName)) : null; } @Override public void setPlayerListName(Player player, String name) { player.playerListName(PaperModule.parseFormattedText(name, ChatColor.WHITE)); } @Override public String getPlayerListName(Player player) { return PaperModule.stringifyComponent(player.playerListName()); } @Override public String[] getSignLines(Sign sign) { String[] output = new String[4]; int i = 0; for (Component component : sign.lines()) { output[i++] = PaperModule.stringifyComponent(component); } return output; } @Override public void setSignLine(Sign sign, int line, String text) { sign.line(line, PaperModule.parseFormattedText(text == null ? "" : text, ChatColor.BLACK)); } @Override public void sendResourcePack(Player player, String url, String hash, boolean forced, String prompt) { if (prompt == null && !forced) { super.sendResourcePack(player, url, hash, false, null); } else { player.setResourcePack(url, CoreUtilities.toLowerCase(hash), forced, PaperModule.parseFormattedText(prompt, ChatColor.WHITE)); } } @Override public void sendSignUpdate(Player player, Location loc, String[] text) { List components = new ArrayList<>(); for (String line : text) { components.add(PaperModule.parseFormattedText(line, ChatColor.BLACK)); } player.sendSignChange(loc, components); } @Override public String getCustomName(Nameable object) { return PaperModule.stringifyComponent(object.customName()); } @Override public void setCustomName(Nameable object, String name) { object.customName(PaperModule.parseFormattedText(name, ChatColor.BLACK)); } @Override public void sendConsoleMessage(CommandSender sender, String text) { sender.sendMessage(PaperModule.parseFormattedText(text, ChatColor.WHITE)); } @Override public InventoryView openAnvil(Player player, Location loc) { return player.openAnvil(loc, true); } @Override public void teleport(Entity entity, Location loc, PlayerTeleportEvent.TeleportCause cause, List entityTeleportFlags, List relativeTeleportFlags) { if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_19)) { super.teleport(entity, loc, cause, null, null); } List teleportFlags = new ArrayList<>(); if (entityTeleportFlags != null) { for (TeleportCommand.EntityState entityTeleportFlag : entityTeleportFlags) { teleportFlags.add(TeleportFlag.EntityState.values()[entityTeleportFlag.ordinal()]); } } if (relativeTeleportFlags != null) { // TODO: MC 1.21.3: Paper updated this API to work differently due to underlying Minecraft changes. for (TeleportCommand.Relative relativeTeleportFlag : relativeTeleportFlags) { teleportFlags.add(new ElementTag(relativeTeleportFlag.name()).asEnum(TeleportFlag.Relative.class)); } } entity.teleport(loc, cause, teleportFlags.toArray(new TeleportFlag[0])); } record BrewingRecipeMatchers(String inputMatcher, String ingredientMatcher) {} public static final Map potionMixes = new HashMap<>(); @Override public void registerBrewingRecipe(String keyName, ItemStack result, String input, String ingredient, ItemScriptContainer itemScriptContainer) { if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { throw new UnsupportedOperationException(); } TagContext context = DenizenCore.implementation.getTagContext(itemScriptContainer); RecipeChoice inputChoice = parseBrewingRecipeChoice(itemScriptContainer, input, context); if (inputChoice == null) { return; } RecipeChoice ingredientChoice = parseBrewingRecipeChoice(itemScriptContainer, ingredient, context); if (ingredientChoice == null) { return; } NamespacedKey key = new NamespacedKey(Denizen.getInstance(), keyName); potionMixes.put(key, new BrewingRecipeMatchers(input.startsWith("matcher:") ? input : null, ingredient.startsWith("matcher:") ? ingredient : null)); Bukkit.getPotionBrewer().addPotionMix(new PotionMix(key, result, inputChoice, ingredientChoice)); } @Override public void clearBrewingRecipes() { if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_18)) { return; } PotionBrewer brewer = Bukkit.getPotionBrewer(); for (NamespacedKey mix : new ArrayList<>(potionMixes.keySet())) { brewer.removePotionMix(mix); potionMixes.remove(mix); } } public static RecipeChoice parseBrewingRecipeChoice(ItemScriptContainer container, String choice, TagContext context) { if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) && choice.startsWith("matcher:")) { String matcher = choice.substring("matcher:".length()); return PotionMix.createPredicateChoice(item -> new ItemTag(item).tryAdvancedMatcher(matcher, context)); } boolean exact = true; if (choice.startsWith("material:")) { choice = choice.substring("material:".length()); exact = false; } ItemStack[] items = ItemScriptHelper.textToItemArray(container, choice, exact); if (items == null) { return null; } if (exact) { return new RecipeChoice.ExactChoice(items); } Material[] mats = new Material[items.length]; for (int i = 0; i < items.length; i++) { mats[i] = items[i].getType(); } return new RecipeChoice.MaterialChoice(mats); } @Override public String getBrewingRecipeInputMatcher(NamespacedKey recipeId) { return potionMixes.get(recipeId).inputMatcher(); } @Override public String getBrewingRecipeIngredientMatcher(NamespacedKey recipeId) { return potionMixes.get(recipeId).ingredientMatcher(); } @Override public RecipeChoice createPredicateRecipeChoice(Predicate predicate) { return PotionMix.createPredicateChoice(predicate); } @Override public String getDeathMessage(PlayerDeathEvent event) { return PaperModule.stringifyComponent(event.deathMessage()); } @Override public void setDeathMessage(PlayerDeathEvent event, String message) { event.deathMessage(PaperModule.parseFormattedText(message, ChatColor.WHITE)); } public Set modifiedTextures = new HashSet<>(); @Override public void setSkin(Player player, String name) { if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_18)) { NMSHandler.instance.getProfileEditor().setPlayerSkin(player, name); return; } // Note: this API is present on all supported versions, but currently used for 1.19+ only PlayerProfile skinProfile = Bukkit.createProfile(name); boolean isOwnName = CoreUtilities.equalsIgnoreCase(player.getName(), name); if (isOwnName && modifiedTextures.contains(player.getUniqueId())) { skinProfile.removeProperty("textures"); } Bukkit.getScheduler().runTaskAsynchronously(Denizen.instance, () -> { if (!skinProfile.complete()) { return; } DenizenCore.runOnMainThread(() -> { PlayerProfile playerProfile = player.getPlayerProfile(); playerProfile.setProperty(getProfileProperty(skinProfile, "textures")); player.setPlayerProfile(playerProfile); if (isOwnName) { modifiedTextures.remove(player.getUniqueId()); } else { modifiedTextures.add(player.getUniqueId()); } }); }); } @Override public void setSkinBlob(Player player, String blob) { if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_18)) { NMSHandler.instance.getProfileEditor().setPlayerSkinBlob(player, blob); return; } // Note: this API is present on all supported versions, but currently used for 1.19+ only List split = CoreUtilities.split(blob, ';'); PlayerProfile playerProfile = player.getPlayerProfile(); ProfileProperty currentTextures = getProfileProperty(playerProfile, "textures"); String value = split.get(0); String signature = split.size() > 1 ? split.get(1) : null; if (!value.equals(currentTextures.getValue()) && (signature == null || !signature.equals(currentTextures.getSignature()))) { modifiedTextures.add(player.getUniqueId()); } playerProfile.setProperty(new ProfileProperty("textures", value, signature)); player.setPlayerProfile(playerProfile); } public ProfileProperty getProfileProperty(PlayerProfile profile, String name) { for (ProfileProperty property : profile.getProperties()) { if (property.getName().equals(name)) { return property; } } return null; } @Override public T spawnEntity(Location location, Class type, Consumer configure, CreatureSpawnEvent.SpawnReason reason) { if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_19)) { // Takes the deprecated bukkit consumer on older versions if (WORLD_SPAWN_BUKKIT_CONSUMER == null) { WORLD_SPAWN_BUKKIT_CONSUMER = ReflectionHelper.getMethodHandle(RegionAccessor.class, "spawn", Location.class, Class.class, Consumer.class, CreatureSpawnEvent.SpawnReason.class); } try { return (T) WORLD_SPAWN_BUKKIT_CONSUMER.invoke(location.getWorld(), location, type, configure, reason); } catch (Throwable e) { Debug.echoError(e); return null; } } return location.getWorld().spawn(location, type, configure, reason); } @Override public void setTeamPrefix(Team team, String prefix) { team.prefix(PaperModule.parseFormattedText(prefix, ChatColor.WHITE)); } @Override public void setTeamSuffix(Team team, String suffix) { team.suffix(PaperModule.parseFormattedText(suffix, ChatColor.WHITE)); } @Override public String getTeamPrefix(Team team) { return PaperModule.stringifyComponent(team.prefix()); } @Override public String getTeamSuffix(Team team) { return PaperModule.stringifyComponent(team.suffix()); } @Override public String convertTextToMiniMessage(String text, boolean splitNewlines) { if (splitNewlines) { List lines = CoreUtilities.split(text, '\n'); return lines.stream().map(l -> convertTextToMiniMessage(l, false)).collect(Collectors.joining("\n")); } Component parsed = PaperModule.jsonToComponent(FormattedTextHelper.componentToJson(FormattedTextHelper.parse(text, ChatColor.WHITE, false))); return MiniMessage.miniMessage().serialize(parsed); } @Override public Merchant createMerchant(String title) { return Bukkit.createMerchant(PaperModule.parseFormattedText(title, ChatColor.BLACK)); } @Override public String getText(TextDisplay textDisplay) { return PaperModule.stringifyComponent(textDisplay.text()); } @Override public void setText(TextDisplay textDisplay, String text) { textDisplay.text(PaperModule.parseFormattedText(text, ChatColor.WHITE)); } @Override public void kickPlayer(Player player, String message) { player.kick(PaperModule.parseFormattedText(message, ChatColor.WHITE)); } @Override public String getClientBrand(Player player) { String clientBrand = player.getClientBrandName(); return clientBrand != null ? clientBrand : "unknown"; } @Override public boolean canUseEquipmentSlot(LivingEntity entity, EquipmentSlot slot) { return NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20) ? entity.canUseEquipmentSlot(slot) : super.canUseEquipmentSlot(entity, slot); } @Override public boolean hasCustomName(PotionMeta meta) { return meta.hasCustomPotionName(); } @Override public void setMaterialTags(Material type, Set tags) { if (!NMSHandler.getVersion().isAtLeast(NMSVersion.v1_21)) { super.setMaterialTags(type, tags); return; } BlockTagsSetter.INSTANCE.setTags(type, tags); } @Override public void addLink(ServerLinks links, String display, URI uri) { links.addLink(PaperModule.parseFormattedText(display, ChatColor.WHITE), uri); } @Override public double[] getRecentTps() { return Bukkit.getTPS(); } @Override public String getCopperGolemState(CopperGolem copperGolem) { return copperGolem.getWeatheringState().name(); } @Override public void setCopperGolemState(ElementTag variant, CopperGolem copperGolem, Mechanism mechanism) { if (mechanism.requireEnum(WeatheringCopperState.class)) { copperGolem.setWeatheringState(variant.asEnum(WeatheringCopperState.class)); } } } ================================================ FILE: plugin/pom.xml ================================================ 4.0.0 com.denizenscript denizen 1.3.2-SNAPSHOT Denizen Scriptable Minecraft and Citizens2 UTF-8 Unknown CUSTOM everything https://maven.citizensnpcs.co/repo org.spigotmc spigot-api 26.1.2-R0.1-SNAPSHOT jar provided com.denizenscript denizencore 1.91.0-SNAPSHOT compile net.citizensnpcs citizens-main 2.0.42-SNAPSHOT jar provided * * org.json json LATEST compile net.milkbowl.vault Vault 1.5.6 system ${project.basedir}/lib/Vault.jar net.kyori adventure-nbt 4.26.1 it.unimi.dsi fastutil-core 8.5.8 provided jenkins https://ci.citizensnpcs.co scm:git:git://github.com/DenizenScript/Denizen.git scm:git:git:@github.com:DenizenScript/Denizen.git https://github.com/DenizenScript/Denizen/tree/dev/ citizens-repo https://maven.citizensnpcs.co/repo src/main/java false ${basedir}/src/main/resources *.mid true ${basedir}/src/main/resources *.yml *.dsc org.apache.maven.plugins maven-deploy-plugin 3.0.0 default-deploy deploy org.apache.maven.plugins maven-shade-plugin 3.4.1 package shade true com.denizenscript:denizencore ** org.json:json ** com.denizenscript:denizen-v** ** com.denizenscript:denizen-nmshandler ** org.apache.maven.plugins maven-compiler-plugin 3.10.1 16 16 ================================================ FILE: plugin/src/main/java/com/denizenscript/denizen/Denizen.java ================================================ package com.denizenscript.denizen; import com.denizenscript.denizen.events.ScriptEventRegistry; import com.denizenscript.denizen.events.bukkit.SavesReloadEvent; import com.denizenscript.denizen.events.server.ServerPrestartScriptEvent; import com.denizenscript.denizen.events.server.ServerStartScriptEvent; import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.NMSVersion; import com.denizenscript.denizen.nms.interfaces.FakeArrow; import com.denizenscript.denizen.nms.interfaces.FakePlayer; import com.denizenscript.denizen.nms.interfaces.ItemProjectile; import com.denizenscript.denizen.npc.DenizenNPCHelper; import com.denizenscript.denizen.npc.TraitRegistry; import com.denizenscript.denizen.objects.InventoryTag; import com.denizenscript.denizen.objects.NPCTag; import com.denizenscript.denizen.objects.PlayerTag; import com.denizenscript.denizen.objects.properties.PropertyRegistry; import com.denizenscript.denizen.scripts.commands.BukkitCommandRegistry; import com.denizenscript.denizen.scripts.commands.player.ClickableCommand; import com.denizenscript.denizen.scripts.containers.ContainerRegistry; import com.denizenscript.denizen.scripts.containers.core.*; import com.denizenscript.denizen.scripts.triggers.TriggerRegistry; import com.denizenscript.denizen.scripts.triggers.core.ChatTrigger; import com.denizenscript.denizen.tags.BukkitTagContext; import com.denizenscript.denizen.tags.core.NPCTagBase; import com.denizenscript.denizen.utilities.*; import com.denizenscript.denizen.utilities.blocks.FullBlockData; import com.denizenscript.denizen.utilities.command.*; import com.denizenscript.denizen.utilities.command.manager.CommandManager; import com.denizenscript.denizen.utilities.command.manager.Injector; import com.denizenscript.denizen.utilities.command.manager.messaging.Messaging; import com.denizenscript.denizen.utilities.debugging.BStatsMetricsLite; import com.denizenscript.denizen.utilities.debugging.DebugSubmit; import com.denizenscript.denizen.utilities.debugging.StatsRecord; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; import com.denizenscript.denizen.utilities.flags.PlayerFlagHandler; import com.denizenscript.denizen.utilities.flags.WorldFlagHandler; import com.denizenscript.denizen.utilities.implementation.DenizenCoreImplementation; import com.denizenscript.denizen.utilities.maps.DenizenMapManager; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; import com.denizenscript.denizen.utilities.world.VoidGenerator; import com.denizenscript.denizen.utilities.world.WorldListChangeTracker; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.ObjectFetcher; import com.denizenscript.denizencore.objects.core.SecretTag; import com.denizenscript.denizencore.objects.core.TimeTag; import com.denizenscript.denizencore.objects.notable.NoteManager; import com.denizenscript.denizencore.scripts.ScriptHelper; import com.denizenscript.denizencore.scripts.commands.queue.RunLaterCommand; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.utilities.debugging.DebugInternals; import com.denizenscript.denizencore.utilities.debugging.StrongWarning; import com.denizenscript.denizencore.utilities.text.ConfigUpdater; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.OfflinePlayer; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; import java.io.*; import java.net.URLDecoder; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; public class Denizen extends JavaPlugin { public static Denizen instance; public static Denizen getInstance() { return instance; } public static boolean hasTickedOnce = false; public static String versionTag = null; private boolean startedSuccessful = false; public static boolean supportsPaper = false; public CommandManager commandManager; public TriggerRegistry triggerRegistry; public DenizenNPCHelper npcHelper; public BukkitWorldScriptHelper worldScriptHelper; public ItemScriptHelper itemScriptHelper; public ExCommandHandler exCommand; public DenizenCoreImplementation coreImplementation = new DenizenCoreImplementation(); /* * Sets up Denizen on start of the CraftBukkit server. */ @Override public void onEnable() { long startTime = System.currentTimeMillis(); instance = this; try { versionTag = this.getDescription().getVersion(); CoreUtilities.noDebugContext = new BukkitTagContext(null, null, null, false, null); CoreUtilities.noDebugContext.showErrors = () -> false; CoreUtilities.basicContext = new BukkitTagContext(null, null, null, true, null); CoreUtilities.errorButNoDebugContext = new BukkitTagContext(null, null, null, false, null); // Load Denizen's core DenizenCore.init(coreImplementation); } catch (Exception e) { e.printStackTrace(); getServer().getPluginManager().disablePlugin(this); startedSuccessful = false; return; } PlayerFlagHandler.dataFolder = new File(getDataFolder(), "player_flags"); if (!PlayerFlagHandler.dataFolder.exists()) { PlayerFlagHandler.dataFolder.mkdir(); } DebugInternals.alternateTrimLogic = FormattedTextHelper::bukkitSafeDebugTrimming; String javaVersion = System.getProperty("java.version"); Debug.log("Running on java version: " + javaVersion); if (javaVersion.startsWith("8") || javaVersion.startsWith("1.8") || javaVersion.startsWith("9") || javaVersion.startsWith("1.9") || javaVersion.startsWith("10") || javaVersion.startsWith("1.10") || javaVersion.startsWith("11") || javaVersion.startsWith("12") || javaVersion.startsWith("13") || javaVersion.startsWith("14") || javaVersion.startsWith("15")) { Debug.log("Running on outdated Java version somehow. Denizen requires Java 16+ or newer to function."); } else if (javaVersion.startsWith("16")) { Debug.log("Running on fully supported Java 16."); } else if (javaVersion.startsWith("17")) { Debug.log("Running on fully supported Java 17."); } else if (javaVersion.startsWith("18") || javaVersion.startsWith("19")) { getLogger().warning("Running unreliable Java version. modern Minecraft versions are built for Java 25, 21, or 17. Other Java versions are not guaranteed to function properly."); } else if (javaVersion.startsWith("21")) { Debug.log("Running on fully supported Java 21."); } else if (javaVersion.startsWith("25")) { Debug.log("Running on fully supported Java 25."); } else { Debug.log("Running on unrecognized (future?) Java version. May or may not work."); } try { if (Class.forName("com.destroystokyo.paper.PaperConfig") != null) { supportsPaper = true; } } catch (ClassNotFoundException ex) { // Ignore. } catch (Throwable ex) { Debug.echoError(ex); } if (!NMSHandler.initialize(this)) { getLogger().warning("-------------------------------------"); getLogger().warning("This build of Denizen is not compatible with this Spigot version! Deactivating Denizen!"); getLogger().warning("-------------------------------------"); getServer().getPluginManager().disablePlugin(this); startedSuccessful = false; return; } if (!NMSHandler.instance.isExactServerVersionMatch()) { String serverSoftware = supportsPaper ? "Paper" : "Spigot"; getLogger().warning(""" \n------------------------------------- This build of Denizen was built for a different Minecraft version! This may potentially cause issues. If you are experiencing trouble, update Denizen and both to latest builds! If this message appears with both Denizen and fully up-to-date, contact the Denizen team (via Discord) to request an update be built. -------------------------------------""".replace("", serverSoftware) ); } triggerRegistry = new TriggerRegistry(); boolean citizensBork = false; try { // Activate dependencies Depends.initialize(); if (Depends.citizens == null) { if (Bukkit.getPluginManager().getPlugin("Citizens") != null) { citizensBork = true; getLogger().warning("Citizens is present but doesn't seem to be activated! You may have an error earlier in your logs, or you may have a broken plugin load order."); } else { getLogger().warning("Citizens does not seem to be available! Denizen will have reduced functionality!"); } } startedSuccessful = true; } catch (Exception e) { Debug.echoError(e); } try { // Populate config.yml if it doesn't yet exist. saveDefaultConfig(); reloadConfig(); // Startup procedure Debug.log(ChatColor.LIGHT_PURPLE + "+-------------------------+"); Debug.log(ChatColor.YELLOW + " Denizen " + ChatColor.GRAY + " scriptable minecraft"); Debug.log(""); Debug.log(ChatColor.GRAY + "by:" + ChatColor.WHITE + " The DenizenScript team"); Debug.log(ChatColor.GRAY + "Chat with us at:" + ChatColor.WHITE + " https://discord.gg/Q6pZGSR"); Debug.log(ChatColor.GRAY + "Or learn more at:" + ChatColor.WHITE + " https://denizenscript.com"); Debug.log(ChatColor.GRAY + "version: " + ChatColor.WHITE + versionTag); Debug.log(ChatColor.LIGHT_PURPLE + "+-------------------------+"); } catch (Exception e) { Debug.echoError(e); } // bstats.org try { BStatsMetricsLite metrics = new BStatsMetricsLite(this); } catch (Throwable e) { Debug.echoError(e); } try { DebugSubmit.init(); // If Citizens is enabled, Create the NPC Helper if (Depends.citizens != null) { npcHelper = new DenizenNPCHelper(); } // Create our CommandManager to handle '/denizen' commands commandManager = new CommandManager(); commandManager.setInjector(new Injector(this)); commandManager.register(DenizenCommandHandler.class); // If Citizens is enabled, let it handle '/npc' commands if (Depends.citizens != null) { Depends.citizens.registerCommandClass(NPCCommandHandler.class); } DenizenEntityType.registerEntityType("ITEM_PROJECTILE", ItemProjectile.class); DenizenEntityType.registerEntityType("FAKE_ARROW", FakeArrow.class); DenizenEntityType.registerEntityType("FAKE_PLAYER", FakePlayer.class); // Track all player names for quick PlayerTag matching for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { PlayerTag.notePlayer(player); } } catch (Exception e) { Debug.echoError(e); } try { BukkitCommandRegistry.registerCommands(); } catch (Exception e) { Debug.echoError(e); } try { ContainerRegistry.registerMainContainers(); } catch (Exception e) { Debug.echoError(e); } try { // Ensure the Scripts and Midi folder exist new File(getDataFolder() + "/scripts").mkdirs(); new File(getDataFolder() + "/midi").mkdirs(); new File(getDataFolder() + "/schematics").mkdirs(); // Ensure the example Denizen.mid sound file is available if (!new File(getDataFolder() + "/midi/Denizen.mid").exists()) { String sourceFile = URLDecoder.decode(Denizen.class.getProtectionDomain().getCodeSource().getLocation().getFile()); Debug.log("Denizen.mid not found, extracting from " + sourceFile); Utilities.extractFile(new File(sourceFile), "Denizen.mid", getDataFolder() + "/midi/"); } } catch (Exception e) { Debug.echoError(e); } try { // Automatic config file update InputStream properConfig = Denizen.class.getResourceAsStream("/config.yml"); String properConfigString = ScriptHelper.convertStreamToString(properConfig); properConfig.close(); FileInputStream currentConfig = new FileInputStream(getDataFolder() + "/config.yml"); String currentConfigString = ScriptHelper.convertStreamToString(currentConfig); currentConfig.close(); String updated = ConfigUpdater.updateConfig(currentConfigString, properConfigString); if (updated != null) { Debug.log("Your config file is outdated. Automatically updating it..."); FileOutputStream configOutput = new FileOutputStream(getDataFolder() + "/config.yml"); OutputStreamWriter writer = new OutputStreamWriter(configOutput); writer.write(updated); writer.close(); configOutput.close(); reloadConfig(); } if (Settings.cache_legacySpigotNamesSupport) { Debug.log("Legacy Spigot name support enabled. This may be unnecessary; see config.yml for more information."); } } catch (Exception e) { Debug.echoError(e); } try { worldScriptHelper = new BukkitWorldScriptHelper(); itemScriptHelper = new ItemScriptHelper(); new InventoryScriptHelper(); new EntityScriptHelper(); new CommandScriptHelper(); } catch (Exception e) { Debug.echoError(e); } try { if (Depends.citizens != null) { // Register traits TraitRegistry.registerMainTraits(); } } catch (Exception e) { Debug.echoError(e); } // Register Core Members in the Denizen Registries try { if (Depends.citizens != null) { triggerRegistry.registerCoreMembers(); } } catch (Exception e) { Debug.echoError(e); } try { ScriptEventRegistry.registerMainEvents(); CommonRegistries.registerMainObjects(); CommonRegistries.registerMainTagHandlers(); } catch (Exception e) { Debug.echoError(e); } try { // Initialize all properties PropertyRegistry.registerMainProperties(); } catch (Exception e) { Debug.echoError(e); } try { // TODO: temporary patch, should switch to custom click events if (NMSHandler.getVersion().isAtMost(NMSVersion.v1_20)) { new CommandEvents(); } if (Settings.cache_packetInterceptAutoInit) { NetworkInterceptHelper.enable(); } } catch (Exception e) { Debug.echoError(e); } try { if (supportsPaper) { final Class clazz = Class.forName("com.denizenscript.denizen.paper.PaperModule"); clazz.getMethod("init").invoke(null); } } catch (ClassNotFoundException ex) { supportsPaper = false; } catch (Throwable ex) { supportsPaper = false; Debug.echoError(ex); } Debug.log("Loaded " + DenizenCore.commandRegistry.instances.size() + " core commands and " + ObjectFetcher.objectsByPrefix.size() + " core object types, at " + (System.currentTimeMillis() - startTime) + "ms from start."); exCommand = new ExCommandHandler(); exCommand.enableFor(getCommand("ex")); ExSustainedCommandHandler exsCommand = new ExSustainedCommandHandler(); exsCommand.enableFor(getCommand("exs")); FullBlockData.init(); // Load script files without processing. DenizenCore.preloadScripts(false, null); // Load the saves.yml into memory reloadSaves(); try { // Fire the 'on Server PreStart' world event ServerPrestartScriptEvent.instance.specialHackRunEvent(); } catch (Throwable ex) { Debug.echoError(ex); } Debug.log("Final full init took " + (System.currentTimeMillis() - startTime) + "ms."); final boolean hadCitizensBork = citizensBork; // Run everything else on the first server tick Bukkit.getScheduler().scheduleSyncDelayedTask(this, () -> { hasTickedOnce = true; try { if (hadCitizensBork) { Depends.setupCitizens(); if (Depends.citizens != null) { getLogger().warning("Citizens was activated late - this means a plugin load order error occurred. You may have plugins with invalid 'plugin.yml' files (eg that use the 'loadbefore' directive, or that have circular dependencies)."); npcHelper = new DenizenNPCHelper(); Depends.citizens.registerCommandClass(NPCCommandHandler.class); TraitRegistry.registerMainTraits(); triggerRegistry.registerCoreMembers(); BukkitCommandRegistry.registerCitizensCommands(); ScriptEventRegistry.registerCitizensEvents(); new NPCTagBase(); ObjectFetcher.registerWithObjectFetcher(NPCTag.class, NPCTag.tagProcessor); } } } catch (Throwable ex) { Debug.echoError(ex); } try { // Process script files (events, etc). NoteManager.reload(); DenizenCore.postLoadScripts(); Debug.log(ChatColor.LIGHT_PURPLE + "+-------------------------+"); // Fire the 'on Server Start' world event ServerStartScriptEvent.instance.fire(); worldScriptHelper.serverStartEvent(); if (Settings.allowStupidx()) { Debug.echoError("Don't screw with bad config values."); Bukkit.shutdown(); } Bukkit.getScheduler().scheduleSyncRepeatingTask(Denizen.this, () -> { DenizenCore.tick(50); // Sadly, minecraft has no delta timing, so a tick is always 50ms. }, 1, 1); InventoryTag.setupInventoryTracker(); if (!CoreConfiguration.skipAllFlagCleanings && !Settings.skipChunkFlagCleaning) { BukkitWorldScriptHelper.cleanAllWorldChunkFlags(); } Bukkit.getPluginManager().registerEvents(new PlayerFlagHandler(), this); Debug.log("Denizen fully loaded at: " + TimeTag.now().format()); } catch (Throwable ex) { Debug.echoError(ex); } }, 1); new BukkitRunnable() { @Override public void run() { if (Settings.canRecordStats()) { StatsRecord.trigger(); } } }.runTaskTimer(this, 100, 20 * 60 * 60); new BukkitRunnable() { @Override public void run() { PlayerFlagHandler.cleanCache(); } }.runTaskTimer(this, 100, 20 * 60); new BukkitRunnable() { @Override public void run() { if (!StrongWarning.recentWarnings.isEmpty()) { StringBuilder warnText = new StringBuilder(); warnText.append(ChatColor.YELLOW).append("[Denizen] ").append(ChatColor.RED).append("Recent strong system warnings, scripters need to address ASAP (check earlier console logs for details):"); for (StrongWarning warning : StrongWarning.recentWarnings.keySet()) { warnText.append("\n- ").append(warning.message); } StrongWarning.recentWarnings.clear(); Bukkit.getConsoleSender().sendMessage(warnText.toString()); for (Player player : Bukkit.getOnlinePlayers()) { if (player.isOp()) { player.sendMessage(warnText.toString()); } } } } }.runTaskTimer(this, 100, 20 * 60 * 5); Bukkit.getPluginManager().registerEvents(new WorldListChangeTracker(), this); } public boolean hasDisabled = false; /* * Unloads Denizen on shutdown of the server. */ @Override public void onDisable() { if (!startedSuccessful) { return; } if (hasDisabled) { return; } hasDisabled = true; DenizenCore.shutdown(); ScoreboardHelper._saveScoreboards(); InventoryScriptHelper.savePlayerInventories(); triggerRegistry.disableCoreMembers(); getLogger().log(Level.INFO, " v" + getDescription().getVersion() + " disabled."); Bukkit.getServer().getScheduler().cancelTasks(this); HandlerList.unregisterAll(this); saveSaves(true); worldFlags.shutdown(); } @Override public void reloadConfig() { super.reloadConfig(); Settings.refillCache(); SecretTag.load(); if (!CoreConfiguration.defaultDebugMode) { getLogger().warning("Debug is disabled in the Denizen config. This is almost always a mistake, and should not be done in the majority of cases."); } } private FileConfiguration scoreboardsConfig = null; private File scoreboardsConfigFile = null; public WorldFlagHandler worldFlags; public void reloadSaves() { if (scoreboardsConfigFile == null) { scoreboardsConfigFile = new File(getDataFolder(), "scoreboards.yml"); } scoreboardsConfig = YamlConfiguration.loadConfiguration(scoreboardsConfigFile); // Reload scoreboards from scoreboards.yml ScoreboardHelper._recallScoreboards(); // Load maps from maps.yml DenizenMapManager.reloadMaps(); DenizenCore.reloadSaves(); if (worldFlags == null) { worldFlags = new WorldFlagHandler(); } worldFlags.shutdown(); worldFlags.init(); RunLaterCommand.init(new File(getDataFolder(), "run_later.yml").getPath()); if (new File(getDataFolder(), "saves.yml").exists()) { LegacySavesUpdater.updateLegacySaves(); } Bukkit.getServer().getPluginManager().callEvent(new SavesReloadEvent()); } public FileConfiguration getScoreboards() { if (scoreboardsConfig == null) { reloadSaves(); } return scoreboardsConfig; } /** * Immediately saves all non-core save data. * @param lockUntilDone 'true' if the system should sleep and lock the thread until saves are complete. 'false' is saves can happen in the future. */ public void saveSaves(boolean lockUntilDone) { // Save scoreboards to scoreboards.yml ScoreboardHelper._saveScoreboards(); // Save maps to maps.yml DenizenMapManager.saveMaps(); InventoryScriptHelper.savePlayerInventories(); // Save server flags try { scoreboardsConfig.save(scoreboardsConfigFile); } catch (IOException ex) { Logger.getLogger(JavaPlugin.class.getName()).log(Level.SEVERE, "Could not save to " + scoreboardsConfigFile, ex); } PlayerFlagHandler.saveAllNow(lockUntilDone); worldFlags.saveAll(lockUntilDone); RunLaterCommand.saveToFile(!lockUntilDone); } @Override public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args) { if (cmd.getName().equals("denizenclickable")) { if (!(sender instanceof Player)) { return false; } if (args.length >= 2 && CoreUtilities.equalsIgnoreCase(args[0], "chat")) { ChatTrigger.instance.chatTriggerInternal(new PlayerChatEvent((Player) sender, Arrays.stream(args).skip(1).collect(Collectors.joining(" ")))); return true; } if (args.length != 1) { return false; } UUID id; try { id = UUID.fromString(args[0]); } catch (IllegalArgumentException ex) { return false; } ClickableCommand.runClickable(id, (Player) sender); return true; } String modifier = args.length > 0 ? args[0] : ""; if (!commandManager.hasCommand(cmd, modifier) && !modifier.isEmpty()) { return suggestClosestModifier(sender, cmd.getName(), modifier); } Object[] methodArgs = {sender}; return commandManager.executeSafe(cmd, args, sender, methodArgs); } @Override public List onTabComplete(CommandSender commandSender, Command command, String alias, String[] strings) { if (alias.equals("denizen")) { return commandManager.onTabComplete(commandSender, command, alias, strings); } return null; } private boolean suggestClosestModifier(CommandSender sender, String command, String modifier) { String closest = commandManager.getClosestCommandModifier(command, modifier); if (!closest.isEmpty()) { Messaging.send(sender, "<7>Unknown command. Did you mean:"); Messaging.send(sender, " /" + command + " " + closest); return true; } return false; } @Override public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { return switch (CoreUtilities.toLowerCase(id)) { case "void" -> new VoidGenerator(true); case "void_biomes" -> new VoidGenerator(false); default -> null; }; } @Override public File getFile() { return super.getFile(); } } ================================================ FILE: plugin/src/main/java/com/denizenscript/denizen/events/BukkitScriptEvent.java ================================================ package com.denizenscript.denizen.events; import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.npc.traits.AssignmentTrait; import com.denizenscript.denizen.objects.*; import com.denizenscript.denizen.scripts.containers.core.EntityScriptHelper; import com.denizenscript.denizen.scripts.containers.core.InventoryScriptHelper; import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper; import com.denizenscript.denizen.tags.BukkitTagContext; import com.denizenscript.denizen.utilities.NotedAreaTracker; import com.denizenscript.denizen.utilities.Utilities; import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData; import com.denizenscript.denizen.utilities.inventory.SlotHelper; import com.denizenscript.denizencore.events.ScriptEvent; import com.denizenscript.denizencore.flags.AbstractFlagTracker; import com.denizenscript.denizencore.flags.FlaggableObject; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.JavaReflectedObjectTag; import com.denizenscript.denizencore.objects.notable.Notable; import com.denizenscript.denizencore.objects.notable.NoteManager; import com.denizenscript.denizencore.tags.TagContext; import com.denizenscript.denizencore.utilities.CoreConfiguration; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.Deprecations; import com.denizenscript.denizencore.utilities.debugging.Debug; import org.bukkit.*; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Vehicle; import org.bukkit.event.*; import org.bukkit.event.inventory.InventoryType; import org.bukkit.plugin.EventExecutor; import org.bukkit.plugin.IllegalPluginAccessException; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredListener; import org.bukkit.scheduler.BukkitRunnable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.*; import java.util.function.Function; public abstract class BukkitScriptEvent extends ScriptEvent { // <--[language] // @name Advanced Object Matchables // @group Object System // @description // Script events have a variety of matchable object inputs, and the range of inputs they accept may not always be obvious. // For example, an event might be "player clicks "... what can "" be filled with? // // "" usually indicates that a LocationTag and/or MaterialTag will be matched against. // This means you can specify any valid block material name, like "stone" or "air", like "on player clicks stone:" (will only run the event if the player is clicking stone) // You can also use a catch-all such as "block", like "on player clicks block:" (will always run the event when the player clicks anything/anywhere) // You can also use some more complicated matchables such as "vanilla_tagged:", like "on player clicks vanilla_tagged:mineable/axe:" (will run if the block is mineable with axes) // (For more block-related options, refer to the <@link objecttype LocationTag> and <@link objecttype MaterialTag> matchers lists.) // // Many object types can be used for matchables, the valid inputs are unique depending on the object type involved. // // Some inputs don't refer to any object at all - they're just advanced matchers for some generic plaintext, // for example "" implies an enumeration of causes will be matched against. // // Many inputs support advanced matchers. For details on that, see <@link language Advanced Object Matching>. // // A common matchable type found among different objects is a Flag Matchable. This usually looks like "item_flagged:" // This matches if the object has the specified flag, and fails to match if the object doesn't have that flag. // You can specify multiple required flags with '|', like "item_flagged:a|b|c", which will match if-and-only-if the item has ALL the flags named. // They can also be used to require the object does NOT have the flag with a "!" like "item_flagged:!". // When using multiple flags with "|", the "!" is per-entry, so "item_flagged:!a|b" requires the item DOES have 'b' but does NOT have 'a'. // // Note also that in addition to events, tags often also have matchables as input params, // usually documented like ".types[]", with tag documentation specifying what matcher is used, // or like "" to indicate in this example specifically MaterialTag matchables are allowed. // // Not all object types have defined matchable options, and those that do list them in their ObjectType meta. For an example of this, check <@link objecttype ItemTag>. // // As a special case, "in:" style matchable listings in event conform to the following option set: // "biome:": matches if the location is in a given biome, using advanced matchers. // "cuboid" plaintext: matches if the location is in any noted cuboid. // "ellipsoid" plaintext: matches if the location is in any noted ellipsoid. // "polygon" plaintext: matches if the location is in any noted polygon. // "chunk_flagged:": a Flag Matchable for ChunkTag flags. // "area_flagged:": a Flag Matchable for AreaObject flags. // Area note name: matches if an AreaObject note that matches the given advanced matcher contains the location. // If none of the above are used, uses WorldTag matchers. // // --> // <--[extension] // @name Advanced Object Matching Extension // @target_type language // @target_name Advanced Object Matching // @description // Object types have their own special supported matchable inputs, refer to <@link language Advanced Object Matchables>. // --> // <--[language] // @name Script Event Switches // @group Script Events // @description // Modern script events support the concept of 'switches'. // A switch is a specification of additional requirements in an event line other than what's in the event label it. // // A switch consists of a name and a value input, and are can be added anywhere in an event line as "name:". // For example, "on delta time secondly every:5:" is a valid event, where "delta time secondly" is the event itself, and "every:<#>" is a switch available to the event. // // A traditional Denizen event might look like "on damaged", // where "" can be filled with "entity" or any entity type (like "player"). // A switch-using event would instead take the format "on entity damaged" with switch "type:" // meaning you can do "on entity damaged" for any entity, or "on entity damaged type:player:" for players specifically. // This is both more efficient to process and more explicit in what's going on, however it is less clear/readable to the average user, so it is not often used. // Some events may have switches for less-often specified data, and use the event line for other options. // // There are also some standard switches available to every script event, and some available to an entire category of script events. // // One switch available to every event is "server_flagged:", which requires that there be a server flag under the given name. // For example, "on console output server_flagged:recording:" will only run the handler for console output when the "recording" flag is set on the server. // This can also be used to require the server does NOT have a flag with "server_flagged:!" // // "chance:" is also a globally available switch. // For example, "on player breaks diamond_ore chance:25:" will only fire on average one in every four times that a player breaks a diamond ore block. // // Events that have a player linked have the "flagged" and "permission" switches available. // // If the switch is specified, and an event doesn't have a linked player, the event will automatically fail to match. // The "flagged:" switch will limit the event to only fire when the player has the flag with the specified name. // It can be used like "on player breaks block flagged:nobreak:" (that would be used alongside "- flag player nobreak"). // You can also use "flagged:!" to require the player does NOT have the flag, like "on player breaks block flagged:!griefbypass:" // // The "permission:" will limit the event to only fire when the player has the specified permission key. // It can be used like "on player breaks block permission:denizen.my.perm:" // For multiple flag or permission requirements, just list them separated by '|' pipes, like "flagged:a|b|c". This will require all named flags/permissions to be present, not just one. // // Events that have an NPC linked have the "assigned" switch available. // If the switch is specified, and an event doesn't have a linked NPC, the event will automatically fail to match. // The "assigned: