From f2d4c388434195e65fa344dcb6030be0fc966461 Mon Sep 17 00:00:00 2001 From: fullwall Date: Sun, 13 Jun 2021 03:20:18 +0800 Subject: [PATCH] Preliminary update to 1.17 - known bugs include every entity glowing --- dist/pom.xml | 9 +- main/pom.xml | 4 +- .../main/java/net/citizensnpcs/util/NMS.java | 39 +- pom.xml | 5 +- v1_10_R1/pom.xml | 2 +- v1_11_R1/pom.xml | 2 +- v1_12_R1/pom.xml | 2 +- v1_13_R2/pom.xml | 2 +- v1_14_R1/pom.xml | 2 +- v1_15_R1/pom.xml | 2 +- .../v1_15_R1/entity/PufferFishController.java | 2 +- v1_16_R3/pom.xml | 2 +- .../v1_16_R3/entity/PufferFishController.java | 2 +- .../entity/TraderLlamaController.java | 6 +- .../nonliving/FishingHookController.java | 4 +- .../v1_16_R3/util/CitizensBlockBreaker.java | 2 +- v1_17_R1/pom.xml | 119 + .../v1_17_R1/entity/AxolotlController.java | 221 ++ .../nms/v1_17_R1/entity/BatController.java | 168 ++ .../nms/v1_17_R1/entity/BeeController.java | 164 ++ .../nms/v1_17_R1/entity/BlazeController.java | 157 ++ .../nms/v1_17_R1/entity/CatController.java | 206 ++ .../v1_17_R1/entity/CaveSpiderController.java | 205 ++ .../v1_17_R1/entity/ChickenController.java | 215 ++ .../nms/v1_17_R1/entity/CodController.java | 237 ++ .../nms/v1_17_R1/entity/CowController.java | 222 ++ .../v1_17_R1/entity/CreeperController.java | 216 ++ .../v1_17_R1/entity/DolphinController.java | 221 ++ .../v1_17_R1/entity/DrownedController.java | 193 ++ .../entity/EnderDragonController.java | 177 ++ .../v1_17_R1/entity/EndermanController.java | 218 ++ .../v1_17_R1/entity/EndermiteController.java | 201 ++ .../nms/v1_17_R1/entity/EntityHumanNPC.java | 620 ++++++ .../nms/v1_17_R1/entity/EvokerController.java | 194 ++ .../nms/v1_17_R1/entity/FoxController.java | 206 ++ .../nms/v1_17_R1/entity/GhastController.java | 166 ++ .../nms/v1_17_R1/entity/GiantController.java | 202 ++ .../v1_17_R1/entity/GlowSquidController.java | 202 ++ .../nms/v1_17_R1/entity/GoatController.java | 206 ++ .../v1_17_R1/entity/GuardianController.java | 209 ++ .../entity/GuardianElderController.java | 209 ++ .../nms/v1_17_R1/entity/HoglinController.java | 196 ++ .../nms/v1_17_R1/entity/HorseController.java | 252 +++ .../entity/HorseDonkeyController.java | 251 +++ .../v1_17_R1/entity/HorseMuleController.java | 251 +++ .../entity/HorseSkeletonController.java | 251 +++ .../entity/HorseZombieController.java | 251 +++ .../nms/v1_17_R1/entity/HumanController.java | 96 + .../v1_17_R1/entity/IllusionerController.java | 194 ++ .../v1_17_R1/entity/IronGolemController.java | 202 ++ .../nms/v1_17_R1/entity/LlamaController.java | 223 ++ .../v1_17_R1/entity/MagmaCubeController.java | 222 ++ .../v1_17_R1/entity/MobEntityController.java | 71 + .../entity/MushroomCowController.java | 216 ++ .../nms/v1_17_R1/entity/OcelotController.java | 213 ++ .../nms/v1_17_R1/entity/PandaController.java | 206 ++ .../nms/v1_17_R1/entity/ParrotController.java | 177 ++ .../v1_17_R1/entity/PhantomController.java | 239 ++ .../nms/v1_17_R1/entity/PigController.java | 222 ++ .../v1_17_R1/entity/PigZombieController.java | 194 ++ .../entity/PiglinBruteController.java | 199 ++ .../nms/v1_17_R1/entity/PiglinController.java | 196 ++ .../v1_17_R1/entity/PillagerController.java | 206 ++ .../v1_17_R1/entity/PolarBearController.java | 172 ++ .../v1_17_R1/entity/PufferFishController.java | 275 +++ .../nms/v1_17_R1/entity/RabbitController.java | 229 ++ .../v1_17_R1/entity/RavagerController.java | 206 ++ .../nms/v1_17_R1/entity/SalmonController.java | 235 ++ .../nms/v1_17_R1/entity/SheepController.java | 207 ++ .../v1_17_R1/entity/ShulkerController.java | 219 ++ .../v1_17_R1/entity/SilverfishController.java | 200 ++ .../v1_17_R1/entity/SkeletonController.java | 202 ++ .../entity/SkeletonStrayController.java | 202 ++ .../entity/SkeletonWitherController.java | 202 ++ .../nms/v1_17_R1/entity/SlimeController.java | 223 ++ .../v1_17_R1/entity/SnowmanController.java | 215 ++ .../nms/v1_17_R1/entity/SpiderController.java | 203 ++ .../nms/v1_17_R1/entity/SquidController.java | 202 ++ .../v1_17_R1/entity/StriderController.java | 193 ++ .../entity/TraderLlamaController.java | 225 ++ .../entity/TropicalFishController.java | 237 ++ .../nms/v1_17_R1/entity/TurtleController.java | 233 ++ .../nms/v1_17_R1/entity/VexController.java | 160 ++ .../v1_17_R1/entity/VillagerController.java | 255 +++ .../v1_17_R1/entity/VindicatorController.java | 208 ++ .../entity/WanderingTraderController.java | 253 +++ .../nms/v1_17_R1/entity/WitchController.java | 202 ++ .../nms/v1_17_R1/entity/WitherController.java | 166 ++ .../nms/v1_17_R1/entity/WolfController.java | 219 ++ .../nms/v1_17_R1/entity/ZoglinController.java | 195 ++ .../nms/v1_17_R1/entity/ZombieController.java | 193 ++ .../v1_17_R1/entity/ZombieHuskController.java | 193 ++ .../entity/ZombieVillagerController.java | 193 ++ .../nonliving/AreaEffectCloudController.java | 95 + .../nonliving/ArmorStandController.java | 110 + .../entity/nonliving/BoatController.java | 230 ++ .../nonliving/DragonFireballController.java | 107 + .../entity/nonliving/EggController.java | 113 + .../nonliving/EnderCrystalController.java | 95 + .../nonliving/EnderPearlController.java | 99 + .../nonliving/EnderSignalController.java | 96 + .../nonliving/EvokerFangsController.java | 110 + .../nonliving/ExperienceOrbController.java | 95 + .../nonliving/FallingBlockController.java | 161 ++ .../entity/nonliving/FireworkController.java | 96 + .../nonliving/FishingHookController.java | 119 + .../nonliving/GlowItemFrameController.java | 139 ++ .../entity/nonliving/ItemController.java | 142 ++ .../entity/nonliving/ItemFrameController.java | 138 ++ .../nonliving/LargeFireballController.java | 107 + .../entity/nonliving/LeashController.java | 101 + .../entity/nonliving/LlamaSpitController.java | 116 + .../entity/nonliving/MarkerController.java | 95 + .../nonliving/MinecartChestController.java | 97 + .../nonliving/MinecartCommandController.java | 96 + .../nonliving/MinecartFurnaceController.java | 96 + .../nonliving/MinecartHopperController.java | 77 + .../nonliving/MinecartRideableController.java | 95 + .../nonliving/MinecartSpawnerController.java | 77 + .../nonliving/MinecartTNTController.java | 77 + .../entity/nonliving/PaintingController.java | 100 + .../nonliving/ShulkerBulletController.java | 95 + .../nonliving/SmallFireballController.java | 98 + .../entity/nonliving/SnowballController.java | 95 + .../nonliving/SpectralArrowController.java | 96 + .../entity/nonliving/TNTPrimedController.java | 96 + .../nonliving/ThrownExpBottleController.java | 99 + .../nonliving/ThrownPotionController.java | 114 + .../nonliving/ThrownTridentController.java | 96 + .../nonliving/TippedArrowController.java | 95 + .../nonliving/WitherSkullController.java | 95 + .../nms/v1_17_R1/network/EmptyChannel.java | 80 + .../nms/v1_17_R1/network/EmptyNetHandler.java | 17 + .../v1_17_R1/network/EmptyNetworkManager.java | 25 + .../nms/v1_17_R1/network/EmptySocket.java | 21 + .../nms/v1_17_R1/trait/Commands.java | 561 +++++ .../v1_17_R1/util/CitizensBlockBreaker.java | 188 ++ .../v1_17_R1/util/CustomEntityRegistry.java | 348 +++ .../util/EmptyAdvancementDataPlayer.java | 75 + .../v1_17_R1/util/ForwardingNPCHolder.java | 21 + .../nms/v1_17_R1/util/NMSBoundingBox.java | 20 + .../nms/v1_17_R1/util/NMSImpl.java | 1963 +++++++++++++++++ .../v1_17_R1/util/PlayerAnimationImpl.java | 152 ++ .../nms/v1_17_R1/util/PlayerBodyControl.java | 61 + .../v1_17_R1/util/PlayerControllerJump.java | 21 + .../nms/v1_17_R1/util/PlayerLookControl.java | 141 ++ .../nms/v1_17_R1/util/PlayerMoveControl.java | 138 ++ .../nms/v1_17_R1/util/PlayerNavigation.java | 563 +++++ .../v1_17_R1/util/PlayerNodeEvaluator.java | 517 +++++ .../util/PlayerNodeEvaluatorBase.java | 88 + .../nms/v1_17_R1/util/PlayerPathfinder.java | 152 ++ .../nms/v1_17_R1/util/PlayerlistTracker.java | 100 + v1_8_R3/pom.xml | 2 +- 153 files changed, 25575 insertions(+), 23 deletions(-) create mode 100644 v1_17_R1/pom.xml create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/AxolotlController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BeeController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BlazeController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CatController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CaveSpiderController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ChickenController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CodController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CowController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CreeperController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DolphinController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DrownedController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EnderDragonController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermanController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermiteController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EntityHumanNPC.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EvokerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/FoxController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GhastController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GiantController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GlowSquidController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GoatController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianElderController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HoglinController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseDonkeyController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseMuleController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseSkeletonController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseZombieController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HumanController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IllusionerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IronGolemController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/LlamaController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MagmaCubeController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MushroomCowController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/OcelotController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PandaController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ParrotController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PhantomController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigZombieController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinBruteController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PillagerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PolarBearController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PufferFishController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RabbitController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RavagerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SalmonController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SheepController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ShulkerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SilverfishController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonStrayController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonWitherController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SlimeController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SnowmanController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SpiderController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SquidController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/StriderController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TraderLlamaController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TropicalFishController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TurtleController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VexController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VillagerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VindicatorController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WanderingTraderController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitchController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitherController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WolfController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZoglinController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieHuskController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieVillagerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/AreaEffectCloudController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ArmorStandController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/BoatController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/DragonFireballController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EggController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderCrystalController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderPearlController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderSignalController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EvokerFangsController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ExperienceOrbController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FallingBlockController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FireworkController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FishingHookController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/GlowItemFrameController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemFrameController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LargeFireballController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LeashController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LlamaSpitController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MarkerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartChestController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartCommandController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartFurnaceController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartHopperController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartRideableController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartSpawnerController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartTNTController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/PaintingController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ShulkerBulletController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SmallFireballController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SnowballController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SpectralArrowController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TNTPrimedController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownExpBottleController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownPotionController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownTridentController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TippedArrowController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/WitherSkullController.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyChannel.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetHandler.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetworkManager.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptySocket.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/trait/Commands.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CitizensBlockBreaker.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CustomEntityRegistry.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/EmptyAdvancementDataPlayer.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/ForwardingNPCHolder.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSBoundingBox.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerAnimationImpl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerBodyControl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerControllerJump.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerLookControl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerMoveControl.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNavigation.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluator.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluatorBase.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerPathfinder.java create mode 100644 v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java diff --git a/dist/pom.xml b/dist/pom.xml index d9973220e..5c5dcb30a 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -5,7 +5,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens pom @@ -87,5 +87,12 @@ jar compile + + ${project.groupId} + citizens-v1_17_R1 + ${project.version} + jar + compile + diff --git a/main/pom.xml b/main/pom.xml index a7296973d..30a76d533 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -7,13 +7,13 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-main UTF-8 - 1.16.5-R0.1-SNAPSHOT + 1.17-R0.1-SNAPSHOT ${project.version} 1.4.12 7.0.4 diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index fe2ab9678..c78475152 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -164,6 +164,37 @@ public class NMS { return null; } + public static MethodHandle getFirstMethodHandle(Class clazz, boolean log, Class... params) { + if (clazz == null) + return null; + try { + Method first = null; + for (Method method : clazz.getDeclaredMethods()) { + Class[] paramTypes = method.getParameterTypes(); + if (paramTypes.length == params.length) { + first = method; + for (int i = 0; i < paramTypes.length; i++) { + if (paramTypes[i] != params[i]) { + first = null; + } + } + if (first != null) { + break; + } + } + } + if (first == null) + return null; + first.setAccessible(true); + return LOOKUP.unreflect(first); + } catch (Exception e) { + if (log) { + Messaging.logTr(Messages.ERROR_GETTING_METHOD, e.getLocalizedMessage()); + } + } + return null; + } + public static GameProfileRepository getGameProfileRepository() { return BRIDGE.getGameProfileRepository(); } @@ -320,7 +351,12 @@ public class NMS { } public static void loadBridge(String rev) throws Exception { - Class entity = Class.forName("net.minecraft.server.v" + rev + ".Entity"); + Class entity = null; + try { + entity = Class.forName("net.minecraft.server.v" + rev + ".Entity"); + } catch (ClassNotFoundException ex) { + entity = Class.forName("net.minecraft.world.entity.Entity"); + } giveReflectiveAccess(entity, NMS.class); BRIDGE = (NMSBridge) Class.forName("net.citizensnpcs.nms.v" + rev + ".util.NMSImpl").getConstructor() .newInstance(); @@ -518,7 +554,6 @@ public class NMS { private static Object UNSAFE; private static MethodHandle UNSAFE_FIELD_OFFSET; private static MethodHandle UNSAFE_PUT_OBJECT; - private static MethodHandle UNSAFE_STATIC_FIELD_OFFSET; static { diff --git a/pom.xml b/pom.xml index bf9f9f096..879d033e3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,10 +7,10 @@ pom net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT Unknown - 2.0.27 + 2.0.28 clean package install @@ -25,6 +25,7 @@ v1_14_R1 v1_15_R1 v1_16_R3 + v1_17_R1 dist \ No newline at end of file diff --git a/v1_10_R1/pom.xml b/v1_10_R1/pom.xml index 75ac2553f..183c1ab50 100644 --- a/v1_10_R1/pom.xml +++ b/v1_10_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_10_R1 diff --git a/v1_11_R1/pom.xml b/v1_11_R1/pom.xml index 7e6777beb..aa2fdee81 100644 --- a/v1_11_R1/pom.xml +++ b/v1_11_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_11_R1 diff --git a/v1_12_R1/pom.xml b/v1_12_R1/pom.xml index 53f42c526..b1ec9e1e8 100644 --- a/v1_12_R1/pom.xml +++ b/v1_12_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_12_R1 diff --git a/v1_13_R2/pom.xml b/v1_13_R2/pom.xml index d4abef809..88f1536a4 100644 --- a/v1_13_R2/pom.xml +++ b/v1_13_R2/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_13_R2 diff --git a/v1_14_R1/pom.xml b/v1_14_R1/pom.xml index a9c73dd2f..240f2303b 100644 --- a/v1_14_R1/pom.xml +++ b/v1_14_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_14_R1 diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml index 2b273aac5..67a188623 100644 --- a/v1_15_R1/pom.xml +++ b/v1_15_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_15_R1 diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/PufferFishController.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/PufferFishController.java index 3642b15ce..f4c56cba1 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/PufferFishController.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/PufferFishController.java @@ -121,7 +121,7 @@ public class PufferFishController extends MobEntityController { @Override public boolean doAITick() { - return false; + return npc == null ? super.doAITick() : false; } @Override diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml index f1d5ff30e..80888db1b 100644 --- a/v1_16_R3/pom.xml +++ b/v1_16_R3/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_16_R3 diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/PufferFishController.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/PufferFishController.java index 282dbeeb1..10e5951ff 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/PufferFishController.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/PufferFishController.java @@ -123,7 +123,7 @@ public class PufferFishController extends MobEntityController { @Override public boolean doAITick() { - return false; + return npc == null ? super.doAITick() : false; } @Override diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/TraderLlamaController.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/TraderLlamaController.java index a68088f1e..114130c08 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/TraderLlamaController.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/TraderLlamaController.java @@ -205,8 +205,8 @@ public class TraderLlamaController extends MobEntityController { super.mobTick(); } try { - if (bF != null) { - bF.invoke(this, 10); // DespawnDelay + if (bw != null) { + bw.invoke(this, 10); // DespawnDelay } } catch (Throwable e) { } @@ -223,7 +223,7 @@ public class TraderLlamaController extends MobEntityController { return super.n(entity); } - private static final MethodHandle bF = NMS.getSetter(EntityLlamaTrader.class, "bF"); + private static final MethodHandle bw = NMS.getSetter(EntityLlamaTrader.class, "bw"); } public static class TraderLlamaNPC extends CraftTraderLlama implements ForwardingNPCHolder { diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/nonliving/FishingHookController.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/nonliving/FishingHookController.java index eb3449340..5aaf131ff 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/nonliving/FishingHookController.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/nonliving/FishingHookController.java @@ -110,7 +110,7 @@ public class FishingHookController extends MobEntityController { ((EntityHuman) getShooter()).inventory.items.set(((EntityHuman) getShooter()).inventory.itemInHandIndex, new ItemStack(Items.FISHING_ROD, 1)); try { - D.invoke(this, 0); + G.invoke(this, 0); } catch (Throwable e) { e.printStackTrace(); } @@ -120,7 +120,7 @@ public class FishingHookController extends MobEntityController { } } - private static MethodHandle D = NMS.getSetter(EntityFishingHook.class, "d"); + private static MethodHandle G = NMS.getSetter(EntityFishingHook.class, "g"); } public static class FishingHookNPC extends CraftFishHook implements ForwardingNPCHolder { diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/CitizensBlockBreaker.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/CitizensBlockBreaker.java index c0760d0ea..41b680c4e 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/CitizensBlockBreaker.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/util/CitizensBlockBreaker.java @@ -58,7 +58,7 @@ public class CitizensBlockBreaker extends BlockBreaker { } private float getStrength(IBlockData block) { - float base = block.getBlock().a(block, null, new BlockPosition(0, 0, 0)); + float base = block.h(null, new BlockPosition(0, 0, 0)); return base < 0.0F ? 0.0F : (!isDestroyable(block) ? 1.0F / base / 100.0F : strengthMod(block) / base / 30.0F); } diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml new file mode 100644 index 000000000..9cecf9595 --- /dev/null +++ b/v1_17_R1/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + + net.citizensnpcs + citizens-parent + 2.0.28-SNAPSHOT + + citizens-v1_17_R1 + + + UTF-8 + 1.17-R0.1-SNAPSHOT + + + + + everything + http://repo.citizensnpcs.co + + + + + + ${project.groupId} + citizens-main + ${project.version} + provided + + + org.spigotmc + spigot + ${craftbukkit.version} + remapped-mojang + provided + + + + + clean package install + ${basedir}/src/main/java + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + eclipse + 1.8 + 1.8 + + + + org.codehaus.plexus + plexus-compiler-eclipse + 2.8.6 + + + + + + net.md-5 + specialsource-maven-plugin + 1.2.2 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:1.17-R0.1-SNAPSHOT:txt:maps-mojang + true + org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:1.17-R0.1-SNAPSHOT:csrg:maps-spigot + org.spigotmc:spigot:1.17-R0.1-SNAPSHOT:jar:remapped-obf + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + + + diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/AxolotlController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/AxolotlController.java new file mode 100644 index 000000000..e55db0d71 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/AxolotlController.java @@ -0,0 +1,221 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftAxolotl; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class AxolotlController extends MobEntityController { + public AxolotlController() { + super(EntityAxolotlNPC.class); + } + + @Override + public org.bukkit.entity.Axolotl getBukkitEntity() { + return (org.bukkit.entity.Axolotl) super.getBukkitEntity(); + } + + public static class AxolotlNPC extends CraftAxolotl implements ForwardingNPCHolder { + public AxolotlNPC(EntityAxolotlNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityAxolotlNPC extends Axolotl implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityAxolotlNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityAxolotlNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + protected PathNavigation createNavigation(Level world) { + return new GroundPathNavigation(this, world); + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new AxolotlNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isInWater() { + return npc == null ? super.isInWater() : false; + } + + @Override + public boolean isInWaterRainOrBubble() { + return npc == null ? super.isInWaterRainOrBubble() : true; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java new file mode 100644 index 000000000..bb6960455 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java @@ -0,0 +1,168 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftBat; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ambient.Bat; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class BatController extends MobEntityController { + public BatController() { + super(EntityBatNPC.class); + } + + @Override + public org.bukkit.entity.Bat getBukkitEntity() { + return (org.bukkit.entity.Bat) super.getBukkitEntity(); + } + + public static class BatNPC extends CraftBat implements ForwardingNPCHolder { + public BatNPC(EntityBatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityBatNPC extends Bat implements NPCHolder { + private final CitizensNPC npc; + + public EntityBatNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityBatNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + setFlying(false); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new BatNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(net.minecraft.world.entity.Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + public void setFlying(boolean flying) { + setResting(flying); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BeeController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BeeController.java new file mode 100644 index 000000000..bde20787e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BeeController.java @@ -0,0 +1,164 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftBee; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class BeeController extends MobEntityController { + public BeeController() { + super(EntityBeeNPC.class); + } + + @Override + public org.bukkit.entity.Bee getBukkitEntity() { + return (org.bukkit.entity.Bee) super.getBukkitEntity(); + } + + public static class BeeNPC extends CraftBee implements ForwardingNPCHolder { + public BeeNPC(EntityBeeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityBeeNPC extends Bee implements NPCHolder { + private final CitizensNPC npc; + + public EntityBeeNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityBeeNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } + NMSImpl.updateAI(this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new BeeNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BlazeController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BlazeController.java new file mode 100644 index 000000000..5ea55eb18 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BlazeController.java @@ -0,0 +1,157 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftBlaze; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Blaze; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class BlazeController extends MobEntityController { + public BlazeController() { + super(BlazeNPC.class); + } + + @Override + public org.bukkit.entity.Blaze getBukkitEntity() { + return (org.bukkit.entity.Blaze) super.getBukkitEntity(); + } + + public static class BlazeNPC extends CraftBlaze implements ForwardingNPCHolder { + public BlazeNPC(EntityBlazeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityBlazeNPC extends Blaze implements NPCHolder { + private final CitizensNPC npc; + + public EntityBlazeNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityBlazeNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new BlazeNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CatController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CatController.java new file mode 100644 index 000000000..9b27a7358 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CatController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftCat; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CatController extends MobEntityController { + public CatController() { + super(EntityCatNPC.class); + } + + @Override + public org.bukkit.entity.Cat getBukkitEntity() { + return (org.bukkit.entity.Cat) super.getBukkitEntity(); + } + + public static class CatNPC extends CraftCat implements ForwardingNPCHolder { + public CatNPC(EntityCatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCatNPC extends Cat implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityCatNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCatNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CatNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CaveSpiderController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CaveSpiderController.java new file mode 100644 index 000000000..734810890 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CaveSpiderController.java @@ -0,0 +1,205 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftCaveSpider; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.CaveSpider; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CaveSpiderController extends MobEntityController { + public CaveSpiderController() { + super(EntityCaveSpiderNPC.class); + } + + @Override + public org.bukkit.entity.CaveSpider getBukkitEntity() { + return (org.bukkit.entity.CaveSpider) super.getBukkitEntity(); + } + + public static class CaveSpiderNPC extends CraftCaveSpider implements ForwardingNPCHolder { + public CaveSpiderNPC(EntityCaveSpiderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCaveSpiderNPC extends CaveSpider implements NPCHolder { + private final CitizensNPC npc; + + public EntityCaveSpiderNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCaveSpiderNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CaveSpiderNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) { + return super.isLeashed(); + } + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ChickenController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ChickenController.java new file mode 100644 index 000000000..aeeb290c9 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ChickenController.java @@ -0,0 +1,215 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftChicken; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Chicken; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ChickenController extends MobEntityController { + public ChickenController() { + super(EntityChickenNPC.class); + } + + @Override + public org.bukkit.entity.Chicken getBukkitEntity() { + return (org.bukkit.entity.Chicken) super.getBukkitEntity(); + } + + public static class ChickenNPC extends CraftChicken implements ForwardingNPCHolder { + public ChickenNPC(EntityChickenNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityChickenNPC extends Chicken implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityChickenNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityChickenNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + if (npc != null) { + this.eggTime = 100; + } + super.aiStep(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ChickenNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CodController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CodController.java new file mode 100644 index 000000000..24d3cd7c4 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CodController.java @@ -0,0 +1,237 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftCod; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.animal.Cod; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CodController extends MobEntityController { + public CodController() { + super(EntityCodNPC.class); + } + + @Override + public org.bukkit.entity.Cod getBukkitEntity() { + return (org.bukkit.entity.Cod) super.getBukkitEntity(); + } + + public static class CodNPC extends CraftCod implements ForwardingNPCHolder { + public CodNPC(EntityCodNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCodNPC extends Cod implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityCodNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCodNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + public void aiStep() { + boolean lastInWater = this.verticalCollision; + if (npc != null) { + this.verticalCollision = false; + } + super.aiStep(); + if (npc != null) { + this.verticalCollision = lastInWater; + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + if (!npc.useMinecraftAI()) { + NMSImpl.setNotInSchool(this); + } + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CodNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + protected InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if (itemstack.getItem() == Items.WATER_BUCKET && isAlive()) { + return InteractionResult.FAIL; + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CowController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CowController.java new file mode 100644 index 000000000..cafa52cb8 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CowController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftCow; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Cow; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CowController extends MobEntityController { + public CowController() { + super(EntityCowNPC.class); + } + + @Override + public org.bukkit.entity.Cow getBukkitEntity() { + return (org.bukkit.entity.Cow) super.getBukkitEntity(); + } + + public static class CowNPC extends CraftCow implements ForwardingNPCHolder { + public CowNPC(EntityCowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCowNPC extends Cow implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityCowNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCowNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CowNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if (itemstack.getItem() == Items.BUCKET && !entityhuman.getAbilities().instabuild && !this.isBaby()) { + return InteractionResult.FAIL; + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CreeperController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CreeperController.java new file mode 100644 index 000000000..11ce937de --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/CreeperController.java @@ -0,0 +1,216 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftCreeper; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.monster.Creeper; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class CreeperController extends MobEntityController { + public CreeperController() { + super(EntityCreeperNPC.class); + } + + @Override + public org.bukkit.entity.Creeper getBukkitEntity() { + return (org.bukkit.entity.Creeper) super.getBukkitEntity(); + } + + public static class CreeperNPC extends CraftCreeper implements ForwardingNPCHolder { + public CreeperNPC(EntityCreeperNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCreeperNPC extends Creeper implements NPCHolder { + private boolean allowPowered; + private final CitizensNPC npc; + + public EntityCreeperNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCreeperNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CreeperNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + public void setAllowPowered(boolean allowPowered) { + this.allowPowered = allowPowered; + } + + @Override + public void thunderHit(ServerLevel worldserver, LightningBolt entitylightning) { + if (npc == null || allowPowered) { + super.thunderHit(worldserver, entitylightning); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DolphinController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DolphinController.java new file mode 100644 index 000000000..ae9a2e7d6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DolphinController.java @@ -0,0 +1,221 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftDolphin; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.animal.Dolphin; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class DolphinController extends MobEntityController { + public DolphinController() { + super(EntityDolphinNPC.class); + } + + @Override + public org.bukkit.entity.Dolphin getBukkitEntity() { + return (org.bukkit.entity.Dolphin) super.getBukkitEntity(); + } + + public static class DolphinNPC extends CraftDolphin implements ForwardingNPCHolder { + public DolphinNPC(EntityDolphinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityDolphinNPC extends Dolphin implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityDolphinNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityDolphinNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + protected PathNavigation createNavigation(Level world) { + return new GroundPathNavigation(this, world); + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new DolphinNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isInWater() { + return npc == null ? super.isInWater() : false; + } + + @Override + public boolean isInWaterRainOrBubble() { + return npc == null ? super.isInWaterRainOrBubble() : true; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DrownedController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DrownedController.java new file mode 100644 index 000000000..4da2d0382 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/DrownedController.java @@ -0,0 +1,193 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftDrowned; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Drowned; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class DrownedController extends MobEntityController { + public DrownedController() { + super(EntityDrownedNPC.class); + } + + @Override + public org.bukkit.entity.Drowned getBukkitEntity() { + return (org.bukkit.entity.Drowned) super.getBukkitEntity(); + } + + public static class DrownedNPC extends CraftDrowned implements ForwardingNPCHolder { + public DrownedNPC(EntityDrownedNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityDrownedNPC extends Drowned implements NPCHolder { + private final CitizensNPC npc; + + public EntityDrownedNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityDrownedNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new DrownedNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EnderDragonController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EnderDragonController.java new file mode 100644 index 000000000..bd5c03287 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EnderDragonController.java @@ -0,0 +1,177 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEnderDragon; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +public class EnderDragonController extends MobEntityController { + public EnderDragonController() { + super(EntityEnderDragonNPC.class); + } + + @Override + public org.bukkit.entity.EnderDragon getBukkitEntity() { + return (org.bukkit.entity.EnderDragon) super.getBukkitEntity(); + } + + public static class EnderDragonNPC extends CraftEnderDragon implements ForwardingNPCHolder { + public EnderDragonNPC(EntityEnderDragonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEnderDragonNPC extends EnderDragon implements NPCHolder { + private final CitizensNPC npc; + + public EntityEnderDragonNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEnderDragonNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + if (npc != null) { + npc.update(); + NMSImpl.updateMinecraftAIState(npc, this); + } + if (npc != null && !npc.useMinecraftAI()) { + Vec3 mot = getDeltaMovement(); + if (mot.x != 0 || mot.y != 0 || mot.z != 0) { + mot = mot.multiply(0.98, 0.98, 0.98); + setYRot(getCorrectYaw(getX() + mot.x, getZ() + mot.z)); + setPos(getX() + mot.x, getY() + mot.y, getZ() + mot.z); + setDeltaMovement(mot); + } + } else { + super.aiStep(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EnderDragonNPC(this)); + } + return super.getBukkitEntity(); + } + + private float getCorrectYaw(double tX, double tZ) { + if (getZ() > tZ) + return (float) (-Math.toDegrees(Math.atan((getX() - tX) / (getZ() - tZ)))); + if (getZ() < tZ) { + return (float) (-Math.toDegrees(Math.atan((getX() - tX) / (getX() - tZ)))) + 180.0F; + } + return getYRot(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermanController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermanController.java new file mode 100644 index 000000000..a6378485b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermanController.java @@ -0,0 +1,218 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import java.util.Optional; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEnderman; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class EndermanController extends MobEntityController { + public EndermanController() { + super(EntityEndermanNPC.class); + } + + @Override + public org.bukkit.entity.Enderman getBukkitEntity() { + return (org.bukkit.entity.Enderman) super.getBukkitEntity(); + } + + public static class EndermanNPC extends CraftEnderman implements ForwardingNPCHolder { + public EndermanNPC(EntityEndermanNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEndermanNPC extends EnderMan implements NPCHolder { + private final CitizensNPC npc; + + public EntityEndermanNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEndermanNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + try { + } catch (Throwable e) { + e.printStackTrace(); + } + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EndermanNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public Optional safeTeleport(double d0, double d1, double d2, boolean flag, + PlayerTeleportEvent.TeleportCause cause) { + if (npc == null) { + return super.safeTeleport(d0, d1, d2, flag, cause); + } + return Optional.of(false); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermiteController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermiteController.java new file mode 100644 index 000000000..e2357dfcc --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EndermiteController.java @@ -0,0 +1,201 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEndermite; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Endermite; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class EndermiteController extends MobEntityController { + public EndermiteController() { + super(EntityEndermiteNPC.class); + } + + @Override + public org.bukkit.entity.Endermite getBukkitEntity() { + return (org.bukkit.entity.Endermite) super.getBukkitEntity(); + } + + public static class EndermiteNPC extends CraftEndermite implements ForwardingNPCHolder { + public EndermiteNPC(EntityEndermiteNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEndermiteNPC extends Endermite implements NPCHolder { + private final CitizensNPC npc; + + public EntityEndermiteNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEndermiteNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EndermiteNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EntityHumanNPC.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EntityHumanNPC.java new file mode 100644 index 000000000..e0f838b59 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EntityHumanNPC.java @@ -0,0 +1,620 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.net.Socket; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.metadata.MetadataValue; +import org.bukkit.plugin.Plugin; +import org.bukkit.util.Vector; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.mojang.authlib.GameProfile; +import com.mojang.datafixers.util.Pair; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.trait.trait.Inventory; +import net.citizensnpcs.nms.v1_17_R1.network.EmptyNetHandler; +import net.citizensnpcs.nms.v1_17_R1.network.EmptyNetworkManager; +import net.citizensnpcs.nms.v1_17_R1.network.EmptySocket; +import net.citizensnpcs.nms.v1_17_R1.util.EmptyAdvancementDataPlayer; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerControllerJump; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerLookControl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerNavigation; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerlistTracker; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.npc.skin.SkinPacketTracker; +import net.citizensnpcs.npc.skin.SkinnableEntity; +import net.citizensnpcs.trait.Gravity; +import net.citizensnpcs.trait.SkinTrait; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketFlow; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.level.ServerPlayerGameMode; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.AttributeMap; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.phys.Vec3; + +public class EntityHumanNPC extends ServerPlayer implements NPCHolder, SkinnableEntity { + private final Map bz = Maps.newEnumMap(BlockPathTypes.class); + private PlayerControllerJump controllerJump; + private PlayerLookControl controllerLook; + private PlayerMoveControl controllerMove; + private final Map equipmentCache = Maps.newEnumMap(EquipmentSlot.class); + private int jumpTicks = 0; + private PlayerNavigation navigation; + private final CitizensNPC npc; + private final Location packetLocationCache = new Location(null, 0, 0, 0); + private PlayerlistTracker playerlistTracker; + private final SkinPacketTracker skinTracker; + private int updateCounter = 0; + + public EntityHumanNPC(MinecraftServer minecraftServer, ServerLevel world, GameProfile gameProfile, NPC npc) { + super(minecraftServer, world, gameProfile); + this.npc = (CitizensNPC) npc; + + if (npc != null) { + skinTracker = new SkinPacketTracker(this); + try { + GAMEMODE_SETTING.invoke(gameMode, GameType.SURVIVAL, null); + } catch (Throwable e) { + e.printStackTrace(); + } + initialise(minecraftServer); + } else { + skinTracker = null; + } + } + + @Override + public boolean broadcastToPlayer(ServerPlayer entityplayer) { + if (npc != null && playerlistTracker == null) { + return false; + } + return super.broadcastToPlayer(entityplayer); + } + + public boolean canCutCorner(BlockPathTypes pathtype) { + return (pathtype != BlockPathTypes.DANGER_FIRE && pathtype != BlockPathTypes.DANGER_CACTUS + && pathtype != BlockPathTypes.DANGER_OTHER && pathtype != BlockPathTypes.WALKABLE_DOOR); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void die(DamageSource damagesource) { + // players that die are not normally removed from the world. when the + // NPC dies, we are done with the instance and it should be removed. + if (dead) { + return; + } + super.die(damagesource); + Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() { + @Override + public void run() { + ((ServerLevel) level).getChunkProvider().removeEntity(EntityHumanNPC.this); + } + }, 35); // give enough time for death and smoke animation + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public void doTick() { + if (npc == null) { + super.doTick(); + return; + } + super.tick(); + boolean navigating = npc.getNavigator().isNavigating(); + if (!navigating && getBukkitEntity() != null + && (!npc.hasTrait(Gravity.class) || npc.getOrAddTrait(Gravity.class).hasGravity()) + && Util.isLoaded(getBukkitEntity().getLocation(LOADED_LOCATION))) { + travel(new Vec3(0, 0, 0)); + } + Vec3 mot = getDeltaMovement(); + if (Math.abs(mot.x) < EPSILON && Math.abs(mot.y) < EPSILON && Math.abs(mot.z) < EPSILON) { + setDeltaMovement(new Vec3(0, 0, 0)); + } + if (navigating) { + if (!NMSImpl.isNavigationFinished(navigation)) { + NMSImpl.updateNavigation(navigation); + } + moveOnCurrentHeading(); + } + NMSImpl.updateAI(this); + + if (isSpectator()) { + this.noPhysics = true; + this.onGround = false; + } + + if (this.hurtTime > 0) + this.hurtTime--; + if (this.invulnerableTime > 0) + this.invulnerableTime--; + if (isDeadOrDying()) + tickDeath(); + if (this.lastHurtByPlayerTime > 0) { + this.lastHurtByPlayerTime--; + } else { + this.lastHurtByPlayer = null; + } + if (this.lastHurtByMob != null) { + if (!this.lastHurtByMob.isAlive()) { + setLastHurtByMob((LivingEntity) null); + } else if (this.tickCount - this.lastHurtByMobTimestamp > 100) { + setLastHurtByMob((LivingEntity) null); + } + } + tickEffects(); + this.animStepO = this.animStep; + this.yBodyRotO = this.yBodyRot; + this.yHeadRotO = this.yHeadRot; + this.yRotO = getYRot(); + this.xRotO = getXRot(); + } + + @Override + public Packet getAddEntityPacket() { + if (playerlistTracker != null) { + playerlistTracker.updateLastPlayer(); + } + return super.getAddEntityPacket(); + } + + @Override + public CraftPlayer getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PlayerNPC(this)); + } + return super.getBukkitEntity(); + } + + public PlayerControllerJump getControllerJump() { + return controllerJump; + } + + public PlayerMoveControl getMoveControl() { + return controllerMove; + } + + public PathNavigation getNavigation() { + return navigation; + } + + @Override + public NPC getNPC() { + return npc; + } + + public float getPathfindingMalus(BlockPathTypes pathtype) { + return this.bz.containsKey(pathtype) ? this.bz.get(pathtype).floatValue() : pathtype.getMalus(); + } + + @Override + public GameProfile getProfile() { + return super.getGameProfile(); + } + + @Override + public String getSkinName() { + String skinName = npc.getOrAddTrait(SkinTrait.class).getSkinName(); + if (skinName == null) { + skinName = npc.getName(); + } + return skinName.toLowerCase(); + } + + @Override + public SkinPacketTracker getSkinTracker() { + return skinTracker; + } + + @Override + public Component getTabListDisplayName() { + if (Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()) { + return new TextComponent(""); + } + return super.getTabListDisplayName(); + } + + @Override + public boolean hurt(DamageSource damagesource, float f) { + // knock back velocity is cancelled and sent to client for handling when + // the entity is a player. there is no client so make this happen + // manually. + boolean damaged = super.hurt(damagesource, f); + if (damaged && hurtMarked) { + hurtMarked = false; + Bukkit.getScheduler().runTask(CitizensAPI.getPlugin(), new Runnable() { + @Override + public void run() { + EntityHumanNPC.this.hurtMarked = true; + } + }); + } + return damaged; + } + + private void initialise(MinecraftServer minecraftServer) { + Socket socket = new EmptySocket(); + EmptyNetworkManager conn = null; + try { + conn = new EmptyNetworkManager(PacketFlow.CLIENTBOUND); + connection = new EmptyNetHandler(minecraftServer, conn, this); + conn.setListener(connection); + socket.close(); + } catch (IOException e) { + // swallow + } + + AttributeInstance range = getAttribute(Attributes.FOLLOW_RANGE); + if (range == null) { + try { + AttributeSupplier provider = (AttributeSupplier) ATTRIBUTE_SUPPLIER.invoke(getAttributes()); + Map all = Maps + .newHashMap((Map) ATTRIBUTE_PROVIDER_MAP.invoke(provider)); + all.put(Attributes.FOLLOW_RANGE, + new AttributeInstance(Attributes.FOLLOW_RANGE, new Consumer() { + @Override + public void accept(AttributeInstance att) { + throw new UnsupportedOperationException( + "Tried to change value for default attribute instance FOLLOW_RANGE"); + } + })); + ATTRIBUTE_PROVIDER_MAP_SETTER.invoke(provider, ImmutableMap.copyOf(all)); + } catch (Throwable e) { + e.printStackTrace(); + } + range = getAttribute(Attributes.FOLLOW_RANGE); + } + range.setBaseValue(Setting.DEFAULT_PATHFINDING_RANGE.asDouble()); + + controllerJump = new PlayerControllerJump(this); + controllerLook = new PlayerLookControl(this); + controllerMove = new PlayerMoveControl(this); + navigation = new PlayerNavigation(this, level); + this.invulnerableTime = 0; + NMS.setStepHeight(getBukkitEntity(), 1); // the default (0) breaks step climbing + setSkinFlags((byte) 0xFF); + + EmptyAdvancementDataPlayer.clear(this.getAdvancements()); + NMSImpl.setAdvancement(this.getBukkitEntity(), + new EmptyAdvancementDataPlayer(minecraftServer.getFixerUpper(), minecraftServer.getPlayerList(), + minecraftServer.getAdvancements(), CitizensAPI.getDataFolder().getParentFile(), this)); + } + + @Override + public boolean isInWall() { + if (npc == null || noPhysics || isSleeping()) { + return super.isInWall(); + } + return Util.inBlock(getBukkitEntity()); + } + + public boolean isNavigating() { + return npc.getNavigator().isNavigating(); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() : npc.data().get(NPC.COLLIDABLE_METADATA, true); + } + + private void moveOnCurrentHeading() { + if (jumping) { + if (onGround && jumpTicks == 0) { + jumpFromGround(); + jumpTicks = 10; + } + } else { + jumpTicks = 0; + } + xxa *= 0.98F; + zza *= 0.98F; + travel(new Vec3(this.xxa, this.yya, this.zza)); + NMS.setHeadYaw(getBukkitEntity(), getYRot()); + if (jumpTicks > 0) { + jumpTicks--; + } + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void remove(RemovalReason reason) { + super.remove(reason); + getAdvancements().save(); + } + + public void setMoveDestination(double x, double y, double z, double speed) { + controllerMove.setWantedPosition(x, y, z, speed); + } + + public void setPathfindingMalus(BlockPathTypes pathtype, float f) { + this.bz.put(pathtype, Float.valueOf(f)); + } + + public void setShouldJump() { + controllerJump.jump(); + } + + @Override + public void setSkinFlags(byte flags) { + this.getEntityData().set(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION, flags); + } + + @Override + public void setSkinName(String name) { + npc.getOrAddTrait(SkinTrait.class).setSkinName(name); + } + + @Override + public void setSkinName(String name, boolean forceUpdate) { + npc.getOrAddTrait(SkinTrait.class).setSkinName(name, forceUpdate); + } + + @Override + public void setSkinPersistent(String skinName, String signature, String data) { + npc.getOrAddTrait(SkinTrait.class).setSkinPersistent(skinName, signature, data); + } + + public void setTargetLook(Entity target, float yawOffset, float renderOffset) { + controllerLook.a(target, yawOffset, renderOffset); + } + + public void setTargetLook(Location target) { + controllerLook.a(target.getX(), target.getY(), target.getZ()); + } + + public void setTracked(PlayerlistTracker tracker) { + this.playerlistTracker = tracker; + } + + @Override + public void tick() { + super.tick(); + if (npc == null) + return; + noPhysics = isSpectator(); + if (updateCounter + 1 > Setting.PACKET_UPDATE_DELAY.asInt()) { + effectsDirty = true; + } + Bukkit.getServer().getPluginManager().unsubscribeFromPermission("bukkit.broadcast.user", getBukkitEntity()); + + boolean navigating = npc.getNavigator().isNavigating(); + updatePackets(navigating); + + if (invulnerableTime > 0) { + --invulnerableTime; + } + + npc.update(); + /* + double diff = this.yaw - this.aK; + if (diff != 40 && diff != -40) { + ++this.yawUpdateRequiredTicks; + } + if (this.yawUpdateRequiredTicks > 5) { + this.yaw = (diff > -40 && diff < 0) || (diff > 0 && diff > 40) ? this.aK - 40 : this.aK + 40; + this.yawUpdateRequiredTicks = 0; + } + */ + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + public void updateAI() { + controllerMove.tick(); + controllerLook.a(); + controllerJump.b(); + } + + private void updatePackets(boolean navigating) { + updateCounter++; + boolean itemChanged = false; + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack equipment = getItemBySlot(slot); + ItemStack cache = equipmentCache.get(slot); + if (!(cache == null && equipment == null) + && (cache == null ^ equipment == null || !ItemStack.isSame(cache, equipment))) { + itemChanged = true; + } + equipmentCache.put(slot, equipment); + } + if (updateCounter++ <= Setting.PACKET_UPDATE_DELAY.asInt() && !itemChanged) + return; + + updateCounter = 0; + Location current = getBukkitEntity().getLocation(packetLocationCache); + Packet[] packets = new Packet[1]; + List> vals = Lists.newArrayList(); + for (EquipmentSlot slot : EquipmentSlot.values()) { + vals.add(new Pair(slot, getItemBySlot(slot))); + } + packets[0] = new ClientboundSetEquipmentPacket(getId(), vals); + NMSImpl.sendPacketsNearby(getBukkitEntity(), current, packets); + } + + public void updatePathfindingRange(float pathfindingRange) { + this.navigation.setRange(pathfindingRange); + } + + public static class PlayerNPC extends CraftPlayer implements NPCHolder, SkinnableEntity { + private final CraftServer cserver; + private final CitizensNPC npc; + + private PlayerNPC(EntityHumanNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + this.cserver = (CraftServer) Bukkit.getServer(); + npc.getOrAddTrait(Inventory.class); + } + + @Override + public Player getBukkitEntity() { + return this; + } + + @Override + public EntityHumanNPC getHandle() { + return (EntityHumanNPC) this.entity; + } + + @Override + public List getMetadata(String metadataKey) { + return cserver.getEntityMetadata().getMetadata(this, metadataKey); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public String getSkinName() { + return ((SkinnableEntity) this.entity).getSkinName(); + } + + @Override + public SkinPacketTracker getSkinTracker() { + return ((SkinnableEntity) this.entity).getSkinTracker(); + } + + @Override + public boolean hasMetadata(String metadataKey) { + return cserver.getEntityMetadata().hasMetadata(this, metadataKey); + } + + @Override + public void removeMetadata(String metadataKey, Plugin owningPlugin) { + cserver.getEntityMetadata().removeMetadata(this, metadataKey, owningPlugin); + } + + @Override + public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { + cserver.getEntityMetadata().setMetadata(this, metadataKey, newMetadataValue); + } + + @Override + public void setSkinFlags(byte flags) { + ((SkinnableEntity) this.entity).setSkinFlags(flags); + } + + @Override + public void setSkinName(String name) { + ((SkinnableEntity) this.entity).setSkinName(name); + } + + @Override + public void setSkinName(String skinName, boolean forceUpdate) { + ((SkinnableEntity) this.entity).setSkinName(skinName, forceUpdate); + } + + @Override + public void setSkinPersistent(String skinName, String signature, String data) { + ((SkinnableEntity) this.entity).setSkinPersistent(skinName, signature, data); + } + } + + private static final MethodHandle ATTRIBUTE_PROVIDER_MAP = NMS.getGetter(AttributeSupplier.class, "a"); + private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFinalSetter(AttributeSupplier.class, "a"); + private static final MethodHandle ATTRIBUTE_SUPPLIER = NMS.getGetter(AttributeMap.class, "d"); + private static final float EPSILON = 0.005F; + private static final MethodHandle GAMEMODE_SETTING = NMS.getFirstMethodHandle(ServerPlayerGameMode.class, true, + GameType.class, GameType.class); + private static final Location LOADED_LOCATION = new Location(null, 0, 0, 0); +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EvokerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EvokerController.java new file mode 100644 index 000000000..a8ef0b8a2 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/EvokerController.java @@ -0,0 +1,194 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEvoker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Evoker; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class EvokerController extends MobEntityController { + public EvokerController() { + super(EntityEvokerNPC.class); + } + + @Override + public org.bukkit.entity.Evoker getBukkitEntity() { + return (org.bukkit.entity.Evoker) super.getBukkitEntity(); + } + + public static class EntityEvokerNPC extends Evoker implements NPCHolder { + private final CitizensNPC npc; + + public EntityEvokerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEvokerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EvokerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class EvokerNPC extends CraftEvoker implements ForwardingNPCHolder { + public EvokerNPC(EntityEvokerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/FoxController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/FoxController.java new file mode 100644 index 000000000..7d83760b4 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/FoxController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftFox; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class FoxController extends MobEntityController { + public FoxController() { + super(EntityFoxNPC.class); + } + + @Override + public org.bukkit.entity.Fox getBukkitEntity() { + return (org.bukkit.entity.Fox) super.getBukkitEntity(); + } + + public static class EntityFoxNPC extends Fox implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityFoxNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityFoxNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new FoxNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class FoxNPC extends CraftFox implements ForwardingNPCHolder { + public FoxNPC(EntityFoxNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GhastController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GhastController.java new file mode 100644 index 000000000..476f5328b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GhastController.java @@ -0,0 +1,166 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGhast; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Ghast; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class GhastController extends MobEntityController { + public GhastController() { + super(EntityGhastNPC.class); + } + + @Override + public org.bukkit.entity.Ghast getBukkitEntity() { + return (org.bukkit.entity.Ghast) super.getBukkitEntity(); + } + + public static class EntityGhastNPC extends Ghast implements NPCHolder { + private final CitizensNPC npc; + + public EntityGhastNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGhastNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + npc.update(); + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } + } + super.customServerAiStep(); + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GhastNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isAutoSpinAttack() { + return npc != null; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } + + public static class GhastNPC extends CraftGhast implements ForwardingNPCHolder { + public GhastNPC(EntityGhastNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GiantController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GiantController.java new file mode 100644 index 000000000..ddd31d8c2 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GiantController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGiant; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Giant; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class GiantController extends MobEntityController { + public GiantController() { + super(EntityGiantNPC.class); + } + + @Override + public org.bukkit.entity.Giant getBukkitEntity() { + return (org.bukkit.entity.Giant) super.getBukkitEntity(); + } + + public static class EntityGiantNPC extends Giant implements NPCHolder { + private final CitizensNPC npc; + + public EntityGiantNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGiantNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GiantNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class GiantNPC extends CraftGiant implements ForwardingNPCHolder { + public GiantNPC(EntityGiantNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GlowSquidController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GlowSquidController.java new file mode 100644 index 000000000..3aea55543 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GlowSquidController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGlowSquid; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.GlowSquid; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class GlowSquidController extends MobEntityController { + public GlowSquidController() { + super(EntityGlowSquidNPC.class); + } + + @Override + public org.bukkit.entity.GlowSquid getBukkitEntity() { + return (org.bukkit.entity.GlowSquid) super.getBukkitEntity(); + } + + public static class EntityGlowSquidNPC extends GlowSquid implements NPCHolder { + private final CitizensNPC npc; + + public EntityGlowSquidNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGlowSquidNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GlowSquidNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class GlowSquidNPC extends CraftGlowSquid implements ForwardingNPCHolder { + public GlowSquidNPC(EntityGlowSquidNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GoatController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GoatController.java new file mode 100644 index 000000000..fc7813d39 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GoatController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGoat; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.goat.Goat; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class GoatController extends MobEntityController { + public GoatController() { + super(EntityGoatNPC.class); + } + + @Override + public org.bukkit.entity.Goat getBukkitEntity() { + return (org.bukkit.entity.Goat) super.getBukkitEntity(); + } + + public static class EntityGoatNPC extends Goat implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityGoatNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGoatNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GoatNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class GoatNPC extends CraftGoat implements ForwardingNPCHolder { + public GoatNPC(EntityGoatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianController.java new file mode 100644 index 000000000..320ec5070 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianController.java @@ -0,0 +1,209 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGuardian; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Guardian; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class GuardianController extends MobEntityController { + public GuardianController() { + super(EntityGuardianNPC.class); + } + + @Override + public org.bukkit.entity.Guardian getBukkitEntity() { + return (org.bukkit.entity.Guardian) super.getBukkitEntity(); + } + + public static class EntityGuardianNPC extends Guardian implements NPCHolder { + private final CitizensNPC npc; + + public EntityGuardianNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGuardianNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + if (npc == null) { + super.aiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } else { + super.aiStep(); + } + npc.update(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GuardianNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class GuardianNPC extends CraftGuardian implements ForwardingNPCHolder { + public GuardianNPC(EntityGuardianNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianElderController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianElderController.java new file mode 100644 index 000000000..bb140d3c6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/GuardianElderController.java @@ -0,0 +1,209 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftElderGuardian; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.ElderGuardian; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class GuardianElderController extends MobEntityController { + public GuardianElderController() { + super(EntityGuardianElderNPC.class); + } + + @Override + public org.bukkit.entity.ElderGuardian getBukkitEntity() { + return (org.bukkit.entity.ElderGuardian) super.getBukkitEntity(); + } + + public static class EntityGuardianElderNPC extends ElderGuardian implements NPCHolder { + private final CitizensNPC npc; + + public EntityGuardianElderNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGuardianElderNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + if (npc == null) { + super.aiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } else { + super.aiStep(); + } + npc.update(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GuardianElderNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class GuardianElderNPC extends CraftElderGuardian implements ForwardingNPCHolder { + public GuardianElderNPC(EntityGuardianElderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HoglinController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HoglinController.java new file mode 100644 index 000000000..dcae5dcc1 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HoglinController.java @@ -0,0 +1,196 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftHoglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.hoglin.Hoglin; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HoglinController extends MobEntityController { + public HoglinController() { + super(EntityHoglinNPC.class); + } + + @Override + public org.bukkit.entity.Hoglin getBukkitEntity() { + return (org.bukkit.entity.Hoglin) super.getBukkitEntity(); + } + + public static class EntityHoglinNPC extends Hoglin implements NPCHolder { + private final CitizensNPC npc; + + public EntityHoglinNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHoglinNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + setImmuneToZombification(true); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HoglinNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HoglinNPC extends CraftHoglin implements ForwardingNPCHolder { + public HoglinNPC(EntityHoglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseController.java new file mode 100644 index 000000000..46df28001 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseController.java @@ -0,0 +1,252 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.Controllable; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HorseController extends MobEntityController { + public HorseController() { + super(EntityHorseNPC.class); + } + + @Override + public org.bukkit.entity.Horse getBukkitEntity() { + return (org.bukkit.entity.Horse) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityHorseNPC extends Horse implements NPCHolder { + private double baseMovementSpeed; + private boolean calledNMSHeight = false; + private final CitizensNPC npc; + private boolean riding; + + public EntityHorseNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHorseNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + org.bukkit.entity.Horse horse = (org.bukkit.entity.Horse) getBukkitEntity(); + horse.setDomestication(horse.getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + public boolean canBeControlledByRider() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.canBeControlledByRider(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc == null) + return; + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.hasTrait(Controllable.class) && npc.getOrAddTrait(Controllable.class).isEnabled()) { + riding = getBukkitEntity().getPassengers().size() > 0; + getAttribute(Attributes.MOVEMENT_SPEED) + .setBaseValue(baseMovementSpeed * npc.getNavigator().getDefaultParameters().speedModifier()); + } else { + riding = false; + } + if (riding) { + if (npc.getNavigator().isNavigating()) { + org.bukkit.entity.Entity basePassenger = passengers.get(0).getBukkitEntity(); + NMS.look(basePassenger, getYRot(), getXRot()); + } + setFlag(4, true); // datawatcher method + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HorseNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HorseNPC extends CraftHorse implements ForwardingNPCHolder { + public HorseNPC(EntityHorseNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseDonkeyController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseDonkeyController.java new file mode 100644 index 000000000..caf67d85e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseDonkeyController.java @@ -0,0 +1,251 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftDonkey; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.Controllable; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.horse.Donkey; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HorseDonkeyController extends MobEntityController { + public HorseDonkeyController() { + super(EntityHorseDonkeyNPC.class); + } + + @Override + public org.bukkit.entity.Donkey getBukkitEntity() { + return (org.bukkit.entity.Donkey) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.addTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityHorseDonkeyNPC extends Donkey implements NPCHolder { + private double baseMovementSpeed; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + private boolean riding; + + public EntityHorseDonkeyNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHorseDonkeyNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.Donkey) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Donkey) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + public boolean canBeControlledByRider() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.canBeControlledByRider(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.hasTrait(Controllable.class) && npc.getOrAddTrait(Controllable.class).isEnabled()) { + riding = getBukkitEntity().getPassengers().size() > 0; + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue( + baseMovementSpeed * npc.getNavigator().getDefaultParameters().speedModifier()); + } else { + riding = false; + } + if (riding) { + if (npc.getNavigator().isNavigating()) { + org.bukkit.entity.Entity basePassenger = passengers.get(0).getBukkitEntity(); + NMS.look(basePassenger, getYRot(), getXRot()); + } + setFlag(4, true); // datawatcher method + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HorseDonkeyNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HorseDonkeyNPC extends CraftDonkey implements ForwardingNPCHolder { + public HorseDonkeyNPC(EntityHorseDonkeyNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseMuleController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseMuleController.java new file mode 100644 index 000000000..3731fcd24 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseMuleController.java @@ -0,0 +1,251 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMule; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.Controllable; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.horse.Mule; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HorseMuleController extends MobEntityController { + public HorseMuleController() { + super(EntityHorseMuleNPC.class); + } + + @Override + public org.bukkit.entity.Mule getBukkitEntity() { + return (org.bukkit.entity.Mule) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityHorseMuleNPC extends Mule implements NPCHolder { + private double baseMovementSpeed; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + private boolean riding; + + public EntityHorseMuleNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHorseMuleNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.Mule) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Mule) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + public boolean canBeControlledByRider() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.canBeControlledByRider(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.hasTrait(Controllable.class) && npc.getOrAddTrait(Controllable.class).isEnabled()) { + riding = getBukkitEntity().getPassengers().size() > 0; + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue( + baseMovementSpeed * npc.getNavigator().getDefaultParameters().speedModifier()); + } else { + riding = false; + } + if (riding) { + if (npc.getNavigator().isNavigating()) { + org.bukkit.entity.Entity basePassenger = passengers.get(0).getBukkitEntity(); + NMS.look(basePassenger, getYRot(), getXRot()); + } + setFlag(4, true); // datawatcher method + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HorseMuleNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HorseMuleNPC extends CraftMule implements ForwardingNPCHolder { + public HorseMuleNPC(EntityHorseMuleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseSkeletonController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseSkeletonController.java new file mode 100644 index 000000000..41a4e09c9 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseSkeletonController.java @@ -0,0 +1,251 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSkeletonHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.Controllable; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.horse.SkeletonHorse; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HorseSkeletonController extends MobEntityController { + public HorseSkeletonController() { + super(EntityHorseSkeletonNPC.class); + } + + @Override + public org.bukkit.entity.SkeletonHorse getBukkitEntity() { + return (org.bukkit.entity.SkeletonHorse) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityHorseSkeletonNPC extends SkeletonHorse implements NPCHolder { + private double baseMovementSpeed; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + private boolean riding; + + public EntityHorseSkeletonNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHorseSkeletonNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.SkeletonHorse) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.SkeletonHorse) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + public boolean canBeControlledByRider() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.canBeControlledByRider(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.hasTrait(Controllable.class) && npc.getOrAddTrait(Controllable.class).isEnabled()) { + riding = getBukkitEntity().getPassengers().size() > 0; + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue( + baseMovementSpeed * npc.getNavigator().getDefaultParameters().speedModifier()); + } else { + riding = false; + } + if (riding) { + if (npc.getNavigator().isNavigating()) { + org.bukkit.entity.Entity basePassenger = passengers.get(0).getBukkitEntity(); + NMS.look(basePassenger, getYRot(), getXRot()); + } + setFlag(4, true); // datawatcher method + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HorseSkeletonNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HorseSkeletonNPC extends CraftSkeletonHorse implements ForwardingNPCHolder { + public HorseSkeletonNPC(EntityHorseSkeletonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseZombieController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseZombieController.java new file mode 100644 index 000000000..3d4e50c9b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HorseZombieController.java @@ -0,0 +1,251 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftZombieHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.Controllable; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.animal.horse.ZombieHorse; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class HorseZombieController extends MobEntityController { + public HorseZombieController() { + super(EntityHorseZombieNPC.class); + } + + @Override + public org.bukkit.entity.ZombieHorse getBukkitEntity() { + return (org.bukkit.entity.ZombieHorse) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityHorseZombieNPC extends ZombieHorse implements NPCHolder { + private double baseMovementSpeed; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + private boolean riding; + + public EntityHorseZombieNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityHorseZombieNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.ZombieHorse) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.ZombieHorse) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + public boolean canBeControlledByRider() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.canBeControlledByRider(); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.hasTrait(Controllable.class) && npc.getOrAddTrait(Controllable.class).isEnabled()) { + riding = getBukkitEntity().getPassengers().size() > 0; + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue( + baseMovementSpeed * npc.getNavigator().getDefaultParameters().speedModifier()); + } else { + riding = false; + } + if (riding) { + if (npc.getNavigator().isNavigating()) { + org.bukkit.entity.Entity basePassenger = passengers.get(0).getBukkitEntity(); + NMS.look(basePassenger, getYRot(), getXRot()); + } + setFlag(4, true); // datawatcher method + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new HorseZombieNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class HorseZombieNPC extends CraftZombieHorse implements ForwardingNPCHolder { + public HorseZombieNPC(EntityHorseZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HumanController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HumanController.java new file mode 100644 index 000000000..0042da2c0 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/HumanController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import com.mojang.authlib.GameProfile; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.npc.skin.Skin; +import net.citizensnpcs.npc.skin.SkinnableEntity; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; + +public class HumanController extends AbstractEntityController { + public HumanController() { + super(); + } + + @Override + protected Entity createEntity(final Location at, final NPC npc) { + final ServerLevel nmsWorld = ((CraftWorld) at.getWorld()).getHandle(); + String coloredName = npc.getFullName(); + String name = coloredName.length() > 16 ? coloredName.substring(0, 16) : coloredName; + UUID uuid = npc.getUniqueId(); + if (uuid.version() == 4) { // clear version + long msb = uuid.getMostSignificantBits(); + msb &= ~0x0000000000004000L; + msb |= 0x0000000000002000L; + uuid = new UUID(msb, uuid.getLeastSignificantBits()); + } + + String teamName = Util.getTeamName(uuid); + if (npc.requiresNameHologram()) { + name = teamName; + } + + if (Setting.USE_SCOREBOARD_TEAMS.asBoolean()) { + Util.generateTeamFor(npc, name, teamName); + } + + final GameProfile profile = new GameProfile(uuid, name); + final EntityHumanNPC handle = new EntityHumanNPC(MinecraftServer.getServer(), nmsWorld, profile, npc); + + Skin skin = handle.getSkinTracker().getSkin(); + if (skin != null) { + skin.apply(handle); + } + + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { + @Override + public void run() { + if (getBukkitEntity() == null || !getBukkitEntity().isValid() + || getBukkitEntity() != handle.getBukkitEntity()) + return; + boolean removeFromPlayerList = npc.data().get("removefromplayerlist", + Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()); + NMS.addOrRemoveFromPlayerList(getBukkitEntity(), removeFromPlayerList); + } + }, 20); + + handle.getBukkitEntity().setSleepingIgnored(true); + + return handle.getBukkitEntity(); + } + + @Override + public Player getBukkitEntity() { + return (Player) super.getBukkitEntity(); + } + + @Override + public void remove() { + Player entity = getBukkitEntity(); + if (entity != null) { + if (Setting.USE_SCOREBOARD_TEAMS.asBoolean()) { + Util.removeTeamFor(NMS.getNPC(entity), entity.getName()); + } + NMS.removeFromWorld(entity); + SkinnableEntity npc = entity instanceof SkinnableEntity ? (SkinnableEntity) entity : null; + npc.getSkinTracker().onRemoveNPC(); + } + NMS.remove(entity); + // Paper decided to break Spigot compatibility. + // super.remove(); + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IllusionerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IllusionerController.java new file mode 100644 index 000000000..9e3131481 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IllusionerController.java @@ -0,0 +1,194 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftIllusioner; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Illusioner; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class IllusionerController extends MobEntityController { + public IllusionerController() { + super(EntityIllusionerNPC.class); + } + + @Override + public org.bukkit.entity.Illusioner getBukkitEntity() { + return (org.bukkit.entity.Illusioner) super.getBukkitEntity(); + } + + public static class EntityIllusionerNPC extends Illusioner implements NPCHolder { + private final CitizensNPC npc; + + public EntityIllusionerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityIllusionerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new IllusionerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class IllusionerNPC extends CraftIllusioner implements ForwardingNPCHolder { + public IllusionerNPC(EntityIllusionerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IronGolemController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IronGolemController.java new file mode 100644 index 000000000..4e8fb04ac --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/IronGolemController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftIronGolem; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class IronGolemController extends MobEntityController { + public IronGolemController() { + super(EntityIronGolemNPC.class); + } + + @Override + public org.bukkit.entity.IronGolem getBukkitEntity() { + return (org.bukkit.entity.IronGolem) super.getBukkitEntity(); + } + + public static class EntityIronGolemNPC extends IronGolem implements NPCHolder { + private final CitizensNPC npc; + + public EntityIronGolemNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityIronGolemNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new IronGolemNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class IronGolemNPC extends CraftIronGolem implements ForwardingNPCHolder { + public IronGolemNPC(EntityIronGolemNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/LlamaController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/LlamaController.java new file mode 100644 index 000000000..2191d6683 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/LlamaController.java @@ -0,0 +1,223 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftLlama; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class LlamaController extends MobEntityController { + public LlamaController() { + super(EntityLlamaNPC.class); + } + + @Override + public org.bukkit.entity.Llama getBukkitEntity() { + return (org.bukkit.entity.Llama) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityLlamaNPC extends Llama implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityLlamaNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityLlamaNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.Llama) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Llama) getBukkitEntity()).getMaxDomestication()); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI()) { + super.customServerAiStep(); + } + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new LlamaNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class LlamaNPC extends CraftLlama implements ForwardingNPCHolder { + public LlamaNPC(EntityLlamaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MagmaCubeController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MagmaCubeController.java new file mode 100644 index 000000000..14361db3b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MagmaCubeController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMagmaCube; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.monster.MagmaCube; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class MagmaCubeController extends MobEntityController { + public MagmaCubeController() { + super(EntityMagmaCubeNPC.class); + } + + @Override + public org.bukkit.entity.MagmaCube getBukkitEntity() { + return (org.bukkit.entity.MagmaCube) super.getBukkitEntity(); + } + + public static class EntityMagmaCubeNPC extends MagmaCube implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityMagmaCubeNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMagmaCubeNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + setSize(3, true); + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new PlayerMoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MagmaCubeNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void playerTouch(Player human) { + if (npc == null) { + super.playerTouch(human); + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class MagmaCubeNPC extends CraftMagmaCube implements ForwardingNPCHolder { + public MagmaCubeNPC(EntityMagmaCubeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java new file mode 100644 index 000000000..7b5a929be --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MobEntityController.java @@ -0,0 +1,71 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import java.lang.reflect.Constructor; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.entity.Entity; + +import com.google.common.collect.Maps; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; + +public abstract class MobEntityController extends AbstractEntityController { + private final Class clazz; + private final Constructor constructor; + + protected MobEntityController(Class clazz) { + super(clazz); + this.constructor = getConstructor(clazz); + this.clazz = clazz; + } + + @Override + protected Entity createEntity(Location at, NPC npc) { + EntityType type = NMSImpl.getEntityType(clazz); + net.minecraft.world.entity.Entity entity = createEntityFromClass(type, ((CraftWorld) at.getWorld()).getHandle(), + npc); + entity.absMoveTo(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); + + // entity.onGround isn't updated right away - we approximate here so + // that things like pathfinding still work *immediately* after spawn. + org.bukkit.Material beneath = at.getBlock().getRelative(BlockFace.DOWN).getType(); + if (beneath.isSolid()) { + entity.setOnGround(true); + } + try { + NMSImpl.UUID_FIELD.invoke(entity, npc.getUniqueId()); + } catch (Throwable e) { + e.printStackTrace(); + } + return entity.getBukkitEntity(); + } + + private net.minecraft.world.entity.Entity createEntityFromClass(Object... args) { + try { + return (net.minecraft.world.entity.Entity) constructor.newInstance(args); + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + } + + private static Constructor getConstructor(Class clazz) { + Constructor constructor = CONSTRUCTOR_CACHE.get(clazz); + if (constructor != null) + return constructor; + try { + return clazz.getConstructor(EntityType.class, Level.class, NPC.class); + } catch (Exception ex) { + throw new IllegalStateException("unable to find an entity constructor"); + } + } + + private static final Map, Constructor> CONSTRUCTOR_CACHE = Maps.newHashMap(); +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MushroomCowController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MushroomCowController.java new file mode 100644 index 000000000..b07c5a8e6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/MushroomCowController.java @@ -0,0 +1,216 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMushroomCow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class MushroomCowController extends MobEntityController { + public MushroomCowController() { + super(EntityMushroomCowNPC.class); + } + + @Override + public org.bukkit.entity.MushroomCow getBukkitEntity() { + return (org.bukkit.entity.MushroomCow) super.getBukkitEntity(); + } + + public static class EntityMushroomCowNPC extends MushroomCow implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityMushroomCowNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMushroomCowNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MushroomCowNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + return InteractionResult.FAIL; + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class MushroomCowNPC extends CraftMushroomCow implements ForwardingNPCHolder { + public MushroomCowNPC(EntityMushroomCowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/OcelotController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/OcelotController.java new file mode 100644 index 000000000..c2cbb9f18 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/OcelotController.java @@ -0,0 +1,213 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftOcelot; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.animal.Ocelot; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class OcelotController extends MobEntityController { + public OcelotController() { + super(EntityOcelotNPC.class); + } + + @Override + public org.bukkit.entity.Ocelot getBukkitEntity() { + return (org.bukkit.entity.Ocelot) super.getBukkitEntity(); + } + + public static class EntityOcelotNPC extends Ocelot implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityOcelotNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityOcelotNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + Pose old = this.getPose(); + boolean restorePose = !this.getMoveControl().hasWanted(); + super.customServerAiStep(); + if (restorePose) { + this.setPose(old); + } + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new OcelotNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class OcelotNPC extends CraftOcelot implements ForwardingNPCHolder { + public OcelotNPC(EntityOcelotNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PandaController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PandaController.java new file mode 100644 index 000000000..02a835192 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PandaController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPanda; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PandaController extends MobEntityController { + public PandaController() { + super(EntityPandaNPC.class); + } + + @Override + public org.bukkit.entity.Panda getBukkitEntity() { + return (org.bukkit.entity.Panda) super.getBukkitEntity(); + } + + public static class EntityPandaNPC extends Panda implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityPandaNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPandaNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PandaNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PandaNPC extends CraftPanda implements ForwardingNPCHolder { + public PandaNPC(EntityPandaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ParrotController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ParrotController.java new file mode 100644 index 000000000..68269cac0 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ParrotController.java @@ -0,0 +1,177 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftParrot; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Parrot; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class ParrotController extends MobEntityController { + public ParrotController() { + super(EntityParrotNPC.class); + } + + @Override + public org.bukkit.entity.Parrot getBukkitEntity() { + return (org.bukkit.entity.Parrot) super.getBukkitEntity(); + } + + public static class EntityParrotNPC extends Parrot implements NPCHolder { + private final CitizensNPC npc; + + public EntityParrotNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityParrotNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (!npc.useMinecraftAI()) { + NMSImpl.updateAI(this); + } else { + super.customServerAiStep(); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ParrotNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + // block feeding + if (npc == null || !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + return super.mobInteract(entityhuman, enumhand); + } + return InteractionResult.FAIL; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } + + public static class ParrotNPC extends CraftParrot implements ForwardingNPCHolder { + public ParrotNPC(EntityParrotNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PhantomController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PhantomController.java new file mode 100644 index 000000000..893012db6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PhantomController.java @@ -0,0 +1,239 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPhantom; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.Difficulty; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.LookControl; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.monster.Phantom; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.storage.WorldData; +import net.minecraft.world.phys.Vec3; + +public class PhantomController extends MobEntityController { + public PhantomController() { + super(EntityPhantomNPC.class); + } + + @Override + public org.bukkit.entity.Phantom getBukkitEntity() { + return (org.bukkit.entity.Phantom) super.getBukkitEntity(); + } + + public static class EntityPhantomNPC extends Phantom implements NPCHolder { + private final CitizensNPC npc; + private LookControl oldLookController; + private MoveControl oldMoveController; + + public EntityPhantomNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPhantomNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + setNoAi(true); + this.oldMoveController = this.moveControl; + this.oldLookController = this.lookControl; + this.moveControl = new MoveControl(this); + this.lookControl = new LookControl(this); + // TODO: phantom pitch reversed + } + } + + @Override + public void aiStep() { + super.aiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + this.lookControl = this.oldLookController; + setNoAi(false); + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + this.lookControl = new LookControl(this); + setNoAi(true); + } + if (npc.isProtected()) { + this.setSecondsOnFire(0); + } + npc.update(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PhantomNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean isSunBurnTick() { + if (npc == null || !npc.isProtected()) + return super.isSunBurnTick(); + return false; + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + // avoid suicide + boolean resetDifficulty = this.level.getDifficulty() == Difficulty.PEACEFUL; + if (npc != null && resetDifficulty) { + ((WorldData) this.level.getLevelData()).setDifficulty(Difficulty.NORMAL); + } + super.tick(); + if (npc != null && resetDifficulty) { + ((WorldData) this.level.getLevelData()).setDifficulty(Difficulty.PEACEFUL); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PhantomNPC extends CraftPhantom implements ForwardingNPCHolder { + public PhantomNPC(EntityPhantomNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigController.java new file mode 100644 index 000000000..f762e6c69 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPig; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PigController extends MobEntityController { + public PigController() { + super(EntityPigNPC.class); + } + + @Override + public org.bukkit.entity.Pig getBukkitEntity() { + return (org.bukkit.entity.Pig) super.getBukkitEntity(); + } + + public static class EntityPigNPC extends Pig implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityPigNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPigNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public boolean canBeControlledByRider() { + // block carrot-on-a-stick behaviour + return npc == null ? super.canBeControlledByRider() : false; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PigNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void thunderHit(ServerLevel worldserver, LightningBolt entitylightning) { + if (npc == null) { + super.thunderHit(worldserver, entitylightning); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PigNPC extends CraftPig implements ForwardingNPCHolder { + public PigNPC(EntityPigNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigZombieController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigZombieController.java new file mode 100644 index 000000000..10367fd20 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PigZombieController.java @@ -0,0 +1,194 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPigZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PigZombieController extends MobEntityController { + + public PigZombieController() { + super(EntityPigZombieNPC.class); + } + + @Override + public org.bukkit.entity.PigZombie getBukkitEntity() { + return (org.bukkit.entity.PigZombie) super.getBukkitEntity(); + } + + public static class EntityPigZombieNPC extends ZombifiedPiglin implements NPCHolder { + private final CitizensNPC npc; + + public EntityPigZombieNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPigZombieNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PigZombieNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PigZombieNPC extends CraftPigZombie implements ForwardingNPCHolder { + public PigZombieNPC(EntityPigZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinBruteController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinBruteController.java new file mode 100644 index 000000000..edfa47a8e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinBruteController.java @@ -0,0 +1,199 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import java.util.TreeMap; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPiglinBrute; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.piglin.PiglinBrute; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PiglinBruteController extends MobEntityController { + public PiglinBruteController() { + super(EntityPiglinBruteNPC.class); + } + + @Override + public org.bukkit.entity.PiglinBrute getBukkitEntity() { + return (org.bukkit.entity.PiglinBrute) super.getBukkitEntity(); + } + + public static class EntityPiglinBruteNPC extends PiglinBrute implements NPCHolder { + private TreeMap behaviorMap; + private final CitizensNPC npc; + + public EntityPiglinBruteNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPiglinBruteNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + setImmuneToZombification(true); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PiglinBruteNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PiglinBruteNPC extends CraftPiglinBrute implements ForwardingNPCHolder { + public PiglinBruteNPC(EntityPiglinBruteNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinController.java new file mode 100644 index 000000000..891f4c288 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PiglinController.java @@ -0,0 +1,196 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPiglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PiglinController extends MobEntityController { + public PiglinController() { + super(EntityPiglinNPC.class); + } + + @Override + public org.bukkit.entity.Piglin getBukkitEntity() { + return (org.bukkit.entity.Piglin) super.getBukkitEntity(); + } + + public static class EntityPiglinNPC extends Piglin implements NPCHolder { + private final CitizensNPC npc; + + public EntityPiglinNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPiglinNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + setImmuneToZombification(true); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PiglinNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PiglinNPC extends CraftPiglin implements ForwardingNPCHolder { + public PiglinNPC(EntityPiglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PillagerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PillagerController.java new file mode 100644 index 000000000..e24d1ba05 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PillagerController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPillager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Pillager; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PillagerController extends MobEntityController { + public PillagerController() { + super(EntityPillagerNPC.class); + } + + @Override + public org.bukkit.entity.Pillager getBukkitEntity() { + return (org.bukkit.entity.Pillager) super.getBukkitEntity(); + } + + public static class EntityPillagerNPC extends Pillager implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityPillagerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPillagerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PillagerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class PillagerNPC extends CraftPillager implements ForwardingNPCHolder { + public PillagerNPC(EntityPillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PolarBearController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PolarBearController.java new file mode 100644 index 000000000..ee4b66144 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PolarBearController.java @@ -0,0 +1,172 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPolarBear; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.PolarBear; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class PolarBearController extends MobEntityController { + public PolarBearController() { + super(EntityPolarBearNPC.class); + } + + @Override + public org.bukkit.entity.PolarBear getBukkitEntity() { + return (org.bukkit.entity.PolarBear) super.getBukkitEntity(); + } + + public static class EntityPolarBearNPC extends PolarBear implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityPolarBearNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPolarBearNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PolarBearNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } + + public static class PolarBearNPC extends CraftPolarBear implements ForwardingNPCHolder { + public PolarBearNPC(EntityPolarBearNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PufferFishController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PufferFishController.java new file mode 100644 index 000000000..b8e1c0012 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/PufferFishController.java @@ -0,0 +1,275 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPufferFish; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.versioned.PufferFishTrait; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class PufferFishController extends MobEntityController { + public PufferFishController() { + super(EntityPufferFishNPC.class); + } + + @Override + public org.bukkit.entity.PufferFish getBukkitEntity() { + return (org.bukkit.entity.PufferFish) super.getBukkitEntity(); + } + + public static class EntityPufferFishNPC extends Pufferfish implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityPufferFishNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPufferFishNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + public void aiStep() { + boolean lastInWater = this.verticalCollision; + int lastPuffState = getPuffState(); + if (npc != null) { + this.verticalCollision = false; + setPuffState(0); + } + super.aiStep(); + if (npc != null) { + this.verticalCollision = lastInWater; + setPuffState(lastPuffState); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PufferFishNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + public EntityDimensions getDimensions(Pose entitypose) { + if (npc == null) { + return super.getDimensions(entitypose); + } + return super.getDimensions(entitypose).scale(1 / s(getPuffState())).scale(0.5F); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isEffectiveAi() { + return npc == null ? super.isEffectiveAi() : false; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + protected InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if (itemstack.getItem() == Items.WATER_BUCKET && isAlive()) { + return InteractionResult.FAIL; + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + NMSImpl.resetPuffTicks(this); + } + super.tick(); + PufferFishTrait trait = null; + if (npc != null && (trait = npc.getTraitNullable(PufferFishTrait.class)) != null) { + setPuffState(trait.getPuffState()); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + private static float s(int i) { + switch (i) { + case 0: + return 0.5F; + case 1: + return 0.7F; + default: + return 1.0F; + } + } + } + + public static class PufferFishNPC extends CraftPufferFish implements ForwardingNPCHolder { + public PufferFishNPC(EntityPufferFishNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RabbitController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RabbitController.java new file mode 100644 index 000000000..e0e7d289d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RabbitController.java @@ -0,0 +1,229 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftRabbit; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class RabbitController extends MobEntityController { + public RabbitController() { + super(EntityRabbitNPC.class); + } + + @Override + public org.bukkit.entity.Rabbit getBukkitEntity() { + return (org.bukkit.entity.Rabbit) super.getBukkitEntity(); + } + + public static class EntityRabbitNPC extends Rabbit implements NPCHolder { + boolean calledNMSHeight = false; + + private final CitizensNPC npc; + + public EntityRabbitNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityRabbitNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.getNavigator().isNavigating()) { + NMS.setShouldJump(getBukkitEntity()); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new RabbitNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public LivingEntity getTarget() { + return npc != null ? null : super.getTarget(); + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void setRabbitType(int i) { + if (npc != null) { + if (NMSImpl.getRabbitTypeField() == null) + return; + this.entityData.set(NMSImpl.getRabbitTypeField(), i); + return; + } + super.setRabbitType(i); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class RabbitNPC extends CraftRabbit implements ForwardingNPCHolder { + public RabbitNPC(EntityRabbitNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RavagerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RavagerController.java new file mode 100644 index 000000000..27f9967b3 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/RavagerController.java @@ -0,0 +1,206 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftRavager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Ravager; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class RavagerController extends MobEntityController { + public RavagerController() { + super(EntityRavagerNPC.class); + } + + @Override + public org.bukkit.entity.Ravager getBukkitEntity() { + return (org.bukkit.entity.Ravager) super.getBukkitEntity(); + } + + public static class EntityRavagerNPC extends Ravager implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityRavagerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityRavagerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new RavagerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class RavagerNPC extends CraftRavager implements ForwardingNPCHolder { + public RavagerNPC(EntityRavagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SalmonController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SalmonController.java new file mode 100644 index 000000000..b58dd5241 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SalmonController.java @@ -0,0 +1,235 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSalmon; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.animal.Salmon; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SalmonController extends MobEntityController { + public SalmonController() { + super(EntitySalmonNPC.class); + } + + @Override + public org.bukkit.entity.Salmon getBukkitEntity() { + return (org.bukkit.entity.Salmon) super.getBukkitEntity(); + } + + public static class EntitySalmonNPC extends Salmon implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntitySalmonNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySalmonNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + public void aiStep() { + boolean lastInWater = this.verticalCollision; + if (npc != null) { + this.verticalCollision = false; + } + super.aiStep(); + if (npc != null) { + this.verticalCollision = lastInWater; + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.setNotInSchool(this); + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SalmonNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + protected InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if (itemstack.getItem() == Items.WATER_BUCKET && isAlive()) { + return InteractionResult.FAIL; + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SalmonNPC extends CraftSalmon implements ForwardingNPCHolder { + public SalmonNPC(EntitySalmonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SheepController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SheepController.java new file mode 100644 index 000000000..29a5bfc0b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SheepController.java @@ -0,0 +1,207 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSheep; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SheepController extends MobEntityController { + public SheepController() { + super(EntitySheepNPC.class); + } + + @Override + public org.bukkit.entity.Sheep getBukkitEntity() { + return (org.bukkit.entity.Sheep) super.getBukkitEntity(); + } + + public static class EntitySheepNPC extends Sheep implements NPCHolder { + boolean calledNMSHeight = false; + + private final CitizensNPC npc; + + public EntitySheepNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySheepNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SheepNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SheepNPC extends CraftSheep implements ForwardingNPCHolder { + public SheepNPC(EntitySheepNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ShulkerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ShulkerController.java new file mode 100644 index 000000000..711b8bd3c --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ShulkerController.java @@ -0,0 +1,219 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftShulker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.BodyRotationControl; +import net.minecraft.world.entity.monster.Shulker; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ShulkerController extends MobEntityController { + public ShulkerController() { + super(EntityShulkerNPC.class); + } + + @Override + public org.bukkit.entity.Shulker getBukkitEntity() { + return (org.bukkit.entity.Shulker) super.getBukkitEntity(); + } + + public static class EntityShulkerNPC extends Shulker implements NPCHolder { + private final CitizensNPC npc; + + public EntityShulkerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityShulkerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + if (npc == null || npc.useMinecraftAI()) { + super.aiStep(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + protected BodyRotationControl createBodyControl() { + return new BodyRotationControl(this); + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ShulkerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI()) { + super.tick(); + } + npc.update(); + } else { + super.tick(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class ShulkerNPC extends CraftShulker implements ForwardingNPCHolder { + public ShulkerNPC(EntityShulkerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SilverfishController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SilverfishController.java new file mode 100644 index 000000000..a53376b43 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SilverfishController.java @@ -0,0 +1,200 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSilverfish; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Silverfish; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SilverfishController extends MobEntityController { + public SilverfishController() { + super(EntitySilverfishNPC.class); + } + + @Override + public org.bukkit.entity.Silverfish getBukkitEntity() { + return (org.bukkit.entity.Silverfish) super.getBukkitEntity(); + } + + public static class EntitySilverfishNPC extends Silverfish implements NPCHolder { + private final CitizensNPC npc; + + public EntitySilverfishNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySilverfishNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) + super.dismountTo(d0, d1, d2); + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SilverfishNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SilverfishNPC extends CraftSilverfish implements ForwardingNPCHolder { + public SilverfishNPC(EntitySilverfishNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonController.java new file mode 100644 index 000000000..e7ad22a67 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSkeleton; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Skeleton; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SkeletonController extends MobEntityController { + public SkeletonController() { + super(EntitySkeletonNPC.class); + } + + @Override + public org.bukkit.entity.Skeleton getBukkitEntity() { + return (org.bukkit.entity.Skeleton) super.getBukkitEntity(); + } + + public static class EntitySkeletonNPC extends Skeleton implements NPCHolder { + private final CitizensNPC npc; + + public EntitySkeletonNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySkeletonNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SkeletonNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SkeletonNPC extends CraftSkeleton implements ForwardingNPCHolder { + public SkeletonNPC(EntitySkeletonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonStrayController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonStrayController.java new file mode 100644 index 000000000..154e2c8d2 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonStrayController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftStray; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Stray; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SkeletonStrayController extends MobEntityController { + public SkeletonStrayController() { + super(EntityStrayNPC.class); + } + + @Override + public org.bukkit.entity.Stray getBukkitEntity() { + return (org.bukkit.entity.Stray) super.getBukkitEntity(); + } + + public static class EntityStrayNPC extends Stray implements NPCHolder { + private final CitizensNPC npc; + + public EntityStrayNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityStrayNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new StrayNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class StrayNPC extends CraftStray implements ForwardingNPCHolder { + public StrayNPC(EntityStrayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonWitherController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonWitherController.java new file mode 100644 index 000000000..1e938dcd8 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SkeletonWitherController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWitherSkeleton; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.WitherSkeleton; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SkeletonWitherController extends MobEntityController { + public SkeletonWitherController() { + super(EntitySkeletonWitherNPC.class); + } + + @Override + public org.bukkit.entity.WitherSkeleton getBukkitEntity() { + return (org.bukkit.entity.WitherSkeleton) super.getBukkitEntity(); + } + + public static class EntitySkeletonWitherNPC extends WitherSkeleton implements NPCHolder { + private final CitizensNPC npc; + + public EntitySkeletonWitherNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySkeletonWitherNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SkeletonWitherNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SkeletonWitherNPC extends CraftWitherSkeleton implements ForwardingNPCHolder { + public SkeletonWitherNPC(EntitySkeletonWitherNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SlimeController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SlimeController.java new file mode 100644 index 000000000..cee80a3dc --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SlimeController.java @@ -0,0 +1,223 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSlime; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.monster.Slime; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SlimeController extends MobEntityController { + public SlimeController() { + super(EntitySlimeNPC.class); + } + + @Override + public org.bukkit.entity.Slime getBukkitEntity() { + return (org.bukkit.entity.Slime) super.getBukkitEntity(); + } + + public static class EntitySlimeNPC extends Slime implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntitySlimeNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySlimeNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + setSize(3, true); + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new PlayerMoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SlimeNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void playerTouch(Player human) { + if (npc == null) { + super.playerTouch(human); + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SlimeNPC extends CraftSlime implements ForwardingNPCHolder { + public SlimeNPC(EntitySlimeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SnowmanController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SnowmanController.java new file mode 100644 index 000000000..d39f4ef8d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SnowmanController.java @@ -0,0 +1,215 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSnowman; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.GameRules; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SnowmanController extends MobEntityController { + public SnowmanController() { + super(EntitySnowmanNPC.class); + } + + @Override + public org.bukkit.entity.Snowman getBukkitEntity() { + return (org.bukkit.entity.Snowman) super.getBukkitEntity(); + } + + public static class EntitySnowmanNPC extends SnowGolem implements NPCHolder { + private final CitizensNPC npc; + + public EntitySnowmanNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySnowmanNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + public void aiStep() { + boolean allowsGriefing = this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); + if (npc != null) { + this.level.getGameRules().getRule(GameRules.RULE_MOBGRIEFING).set(false, getServer()); + } + super.aiStep(); + if (npc != null) { + this.level.getGameRules().getRule(GameRules.RULE_MOBGRIEFING).set(allowsGriefing, getServer()); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SnowmanNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SnowmanNPC extends CraftSnowman implements ForwardingNPCHolder { + public SnowmanNPC(EntitySnowmanNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SpiderController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SpiderController.java new file mode 100644 index 000000000..0abb71b8b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SpiderController.java @@ -0,0 +1,203 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSpider; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Spider; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SpiderController extends MobEntityController { + public SpiderController() { + super(EntitySpiderNPC.class); + } + + @Override + public org.bukkit.entity.Spider getBukkitEntity() { + return (org.bukkit.entity.Spider) super.getBukkitEntity(); + } + + public static class EntitySpiderNPC extends Spider implements NPCHolder { + private final CitizensNPC npc; + + public EntitySpiderNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySpiderNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SpiderNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + } + + public static class SpiderNPC extends CraftSpider implements ForwardingNPCHolder { + public SpiderNPC(EntitySpiderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SquidController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SquidController.java new file mode 100644 index 000000000..1573db8ca --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/SquidController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSquid; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.Squid; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class SquidController extends MobEntityController { + public SquidController() { + super(EntitySquidNPC.class); + } + + @Override + public org.bukkit.entity.Squid getBukkitEntity() { + return (org.bukkit.entity.Squid) super.getBukkitEntity(); + } + + public static class EntitySquidNPC extends Squid implements NPCHolder { + private final CitizensNPC npc; + + public EntitySquidNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySquidNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SquidNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class SquidNPC extends CraftSquid implements ForwardingNPCHolder { + public SquidNPC(EntitySquidNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/StriderController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/StriderController.java new file mode 100644 index 000000000..644d67e27 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/StriderController.java @@ -0,0 +1,193 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftStrider; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Strider; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class StriderController extends MobEntityController { + public StriderController() { + super(EntityStriderNPC.class); + } + + @Override + public org.bukkit.entity.Strider getBukkitEntity() { + return (org.bukkit.entity.Strider) super.getBukkitEntity(); + } + + public static class EntityStriderNPC extends Strider implements NPCHolder { + private final CitizensNPC npc; + + public EntityStriderNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityStriderNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new StriderNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class StriderNPC extends CraftStrider implements ForwardingNPCHolder { + public StriderNPC(EntityStriderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TraderLlamaController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TraderLlamaController.java new file mode 100644 index 000000000..cce2d9d5f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TraderLlamaController.java @@ -0,0 +1,225 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTraderLlama; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.horse.TraderLlama; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class TraderLlamaController extends MobEntityController { + public TraderLlamaController() { + super(EntityTraderLlamaNPC.class); + } + + @Override + public org.bukkit.entity.TraderLlama getBukkitEntity() { + return (org.bukkit.entity.TraderLlama) super.getBukkitEntity(); + } + + @Override + public void spawn(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.spawn(at, npc); + } + + public static class EntityTraderLlamaNPC extends TraderLlama implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityTraderLlamaNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTraderLlamaNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + ((org.bukkit.entity.TraderLlama) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.TraderLlama) getBukkitEntity()).getMaxDomestication()); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI()) { + super.customServerAiStep(); + } + NMSImpl.setDespawnDelay(this, 10); + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TraderLlamaNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class TraderLlamaNPC extends CraftTraderLlama implements ForwardingNPCHolder { + + public TraderLlamaNPC(EntityTraderLlamaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TropicalFishController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TropicalFishController.java new file mode 100644 index 000000000..284f62f0d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TropicalFishController.java @@ -0,0 +1,237 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTropicalFish; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class TropicalFishController extends MobEntityController { + public TropicalFishController() { + super(EntityTropicalFishNPC.class); + } + + @Override + public org.bukkit.entity.TropicalFish getBukkitEntity() { + return (org.bukkit.entity.TropicalFish) super.getBukkitEntity(); + } + + public static class EntityTropicalFishNPC extends TropicalFish implements NPCHolder { + private final CitizensNPC npc; + private MoveControl oldMoveController; + + public EntityTropicalFishNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTropicalFishNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + } + } + + @Override + public void aiStep() { + boolean lastInWater = this.verticalCollision; + if (npc != null) { + this.verticalCollision = false; + } + super.aiStep(); + if (npc != null) { + this.verticalCollision = lastInWater; + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + if (!npc.useMinecraftAI()) { + NMSImpl.setNotInSchool(this); + } + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TropicalFishNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + protected InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if (itemstack.getItem() == Items.WATER_BUCKET && isAlive()) { + return InteractionResult.FAIL; + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class TropicalFishNPC extends CraftTropicalFish implements ForwardingNPCHolder { + public TropicalFishNPC(EntityTropicalFishNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TurtleController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TurtleController.java new file mode 100644 index 000000000..fd8b2663f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/TurtleController.java @@ -0,0 +1,233 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTurtle; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_17_R1.util.PlayerMoveControl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.JumpControl; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.animal.Turtle; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class TurtleController extends MobEntityController { + public TurtleController() { + super(EntityTurtleNPC.class); + } + + @Override + public org.bukkit.entity.Turtle getBukkitEntity() { + return (org.bukkit.entity.Turtle) super.getBukkitEntity(); + } + + public static class EntityTurtleNPC extends Turtle implements NPCHolder { + private final CitizensNPC npc; + private JumpControl oldJumpController; + private MoveControl oldMoveController; + + public EntityTurtleNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTurtleNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + this.oldMoveController = this.moveControl; + this.oldJumpController = this.jumpControl; + this.moveControl = new MoveControl(this); + this.jumpControl = new EmptyControllerJump(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + protected PathNavigation createNavigation(Level world) { + if (npc == null) { + return super.createNavigation(world); + } + return new GroundPathNavigation(this, world); + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + this.jumpControl = this.oldJumpController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new PlayerMoveControl(this); + this.jumpControl = new EmptyControllerJump(this); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TurtleNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + static class EmptyControllerJump extends JumpControl { + public EmptyControllerJump(Mob var1) { + super(var1); + } + + @Override + public void jump() { + this.jump = false; + } + } + } + + public static class TurtleNPC extends CraftTurtle implements ForwardingNPCHolder { + public TurtleNPC(EntityTurtleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VexController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VexController.java new file mode 100644 index 000000000..261b21965 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VexController.java @@ -0,0 +1,160 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftVex; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Vex; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class VexController extends MobEntityController { + public VexController() { + super(EntityVexNPC.class); + } + + @Override + public org.bukkit.entity.Vex getBukkitEntity() { + return (org.bukkit.entity.Vex) super.getBukkitEntity(); + } + + public static class EntityVexNPC extends Vex implements NPCHolder { + private final CitizensNPC npc; + + public EntityVexNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityVexNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + setNoGravity(true); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new VexNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) { + return super.isLeashed(); + } + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } + + public static class VexNPC extends CraftVex implements ForwardingNPCHolder { + public VexNPC(EntityVexNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VillagerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VillagerController.java new file mode 100644 index 000000000..7836ac16d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VillagerController.java @@ -0,0 +1,255 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftVillager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.trading.MerchantOffers; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class VillagerController extends MobEntityController { + public VillagerController() { + super(EntityVillagerNPC.class); + } + + @Override + public org.bukkit.entity.Villager getBukkitEntity() { + return (org.bukkit.entity.Villager) super.getBukkitEntity(); + } + + public static class EntityVillagerNPC extends Villager implements NPCHolder { + private boolean blockingATrade; + private boolean blockTrades = true; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityVillagerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityVillagerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.3); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new VillagerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + public boolean isBlockingTrades() { + return blockTrades; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean isTrading() { + if (blockingATrade) { + blockingATrade = false; + return true; + } + return super.isTrading(); + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc != null && blockTrades) { + blockingATrade = true; + MerchantOffers list = getOffers(); + if (list != null) { + list.clear(); + } + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + public void setBlockTrades(boolean blocked) { + this.blockTrades = blocked; + } + + @Override + public void thunderHit(ServerLevel worldserver, LightningBolt entitylightning) { + if (npc == null) { + super.thunderHit(worldserver, entitylightning); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class VillagerNPC extends CraftVillager implements ForwardingNPCHolder { + public VillagerNPC(EntityVillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VindicatorController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VindicatorController.java new file mode 100644 index 000000000..295c7dfb8 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/VindicatorController.java @@ -0,0 +1,208 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftVindicator; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class VindicatorController extends MobEntityController { + public VindicatorController() { + super(EntityVindicatorNPC.class); + } + + @Override + public org.bukkit.entity.Vindicator getBukkitEntity() { + return (org.bukkit.entity.Vindicator) super.getBukkitEntity(); + } + + public static class EntityVindicatorNPC extends Vindicator implements NPCHolder { + boolean calledNMSHeight = false; + + private final CitizensNPC npc; + + public EntityVindicatorNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityVindicatorNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new VindicatorNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class VindicatorNPC extends CraftVindicator implements ForwardingNPCHolder { + public VindicatorNPC(EntityVindicatorNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WanderingTraderController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WanderingTraderController.java new file mode 100644 index 000000000..0e177da6e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WanderingTraderController.java @@ -0,0 +1,253 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWanderingTrader; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.npc.WanderingTrader; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.item.trading.MerchantOffers; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class WanderingTraderController extends MobEntityController { + public WanderingTraderController() { + super(EntityWanderingTraderNPC.class); + } + + @Override + public org.bukkit.entity.WanderingTrader getBukkitEntity() { + return (org.bukkit.entity.WanderingTrader) super.getBukkitEntity(); + } + + public static class EntityWanderingTraderNPC extends WanderingTrader implements NPCHolder { + private boolean blockingATrade; + private boolean blockTrades = true; + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityWanderingTraderNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWanderingTraderNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WanderingTraderNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + public boolean isBlockingTrades() { + return blockTrades; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean isTrading() { + if (blockingATrade) { + blockingATrade = false; + return true; + } + return super.isTrading(); + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc != null && blockTrades) { + blockingATrade = true; + MerchantOffers list = getOffers(); + if (list != null) { + list.clear(); + } + } + return super.mobInteract(entityhuman, enumhand); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + public void setBlockTrades(boolean blocked) { + this.blockTrades = blocked; + } + + @Override + public void thunderHit(ServerLevel worldserver, LightningBolt entitylightning) { + if (npc == null) { + super.thunderHit(worldserver, entitylightning); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class WanderingTraderNPC extends CraftWanderingTrader implements ForwardingNPCHolder { + public WanderingTraderNPC(EntityWanderingTraderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitchController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitchController.java new file mode 100644 index 000000000..0b5f93c1f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitchController.java @@ -0,0 +1,202 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWitch; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Witch; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class WitchController extends MobEntityController { + public WitchController() { + super(EntityWitchNPC.class); + } + + @Override + public org.bukkit.entity.Witch getBukkitEntity() { + return (org.bukkit.entity.Witch) super.getBukkitEntity(); + } + + public static class EntityWitchNPC extends Witch implements NPCHolder { + private final CitizensNPC npc; + + public EntityWitchNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWitchNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WitchNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class WitchNPC extends CraftWitch implements ForwardingNPCHolder { + public WitchNPC(EntityWitchNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitherController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitherController.java new file mode 100644 index 000000000..74d85b79e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WitherController.java @@ -0,0 +1,166 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWither; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; + +public class WitherController extends MobEntityController { + public WitherController() { + super(EntityWitherNPC.class); + } + + @Override + public org.bukkit.entity.Wither getBukkitEntity() { + return (org.bukkit.entity.Wither) super.getBukkitEntity(); + } + + public static class EntityWitherNPC extends WitherBoss implements NPCHolder { + private final CitizensNPC npc; + + public EntityWitherNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWitherNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void customServerAiStep() { + if (npc == null) { + super.customServerAiStep(); + } else { + NMSImpl.updateMinecraftAIState(npc, this); + if (npc.useMinecraftAI()) { + super.customServerAiStep(); + } + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public int getAlternativeTarget(int i) { + return npc == null ? super.getAlternativeTarget(i) : 0; + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WitherNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + } + + public static class WitherNPC extends CraftWither implements ForwardingNPCHolder { + public WitherNPC(EntityWitherNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WolfController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WolfController.java new file mode 100644 index 000000000..a8316618a --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/WolfController.java @@ -0,0 +1,219 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWolf; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.animal.Wolf; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class WolfController extends MobEntityController { + public WolfController() { + super(EntityWolfNPC.class); + } + + @Override + public org.bukkit.entity.Wolf getBukkitEntity() { + return (org.bukkit.entity.Wolf) super.getBukkitEntity(); + } + + public static class EntityWolfNPC extends Wolf implements NPCHolder { + boolean calledNMSHeight = false; + private final CitizensNPC npc; + + public EntityWolfNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWolfNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WolfNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc != null && !calledNMSHeight) { + calledNMSHeight = true; + NMSImpl.checkAndUpdateHeight(this, datawatcherobject); + calledNMSHeight = false; + } + + super.onSyncedDataUpdated(datawatcherobject); + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public boolean setGoalTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fire) { + return npc == null || this.equals(entityliving) ? super.setGoalTarget(entityliving, reason, fire) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class WolfNPC extends CraftWolf implements ForwardingNPCHolder { + public WolfNPC(EntityWolfNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + + @Override + public void setSitting(boolean sitting) { + getHandle().setInSittingPose(sitting); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZoglinController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZoglinController.java new file mode 100644 index 000000000..d20cb0552 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZoglinController.java @@ -0,0 +1,195 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftZoglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Zoglin; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ZoglinController extends MobEntityController { + public ZoglinController() { + super(EntityZoglinNPC.class); + } + + @Override + public org.bukkit.entity.Zoglin getBukkitEntity() { + return (org.bukkit.entity.Zoglin) super.getBukkitEntity(); + } + + public static class EntityZoglinNPC extends Zoglin implements NPCHolder { + private final CitizensNPC npc; + + public EntityZoglinNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityZoglinNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ZoglinNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class ZoglinNPC extends CraftZoglin implements ForwardingNPCHolder { + public ZoglinNPC(EntityZoglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieController.java new file mode 100644 index 000000000..de0dd2ee1 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieController.java @@ -0,0 +1,193 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ZombieController extends MobEntityController { + public ZombieController() { + super(EntityZombieNPC.class); + } + + @Override + public org.bukkit.entity.Zombie getBukkitEntity() { + return (org.bukkit.entity.Zombie) super.getBukkitEntity(); + } + + public static class EntityZombieNPC extends Zombie implements NPCHolder { + private final CitizensNPC npc; + + public EntityZombieNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityZombieNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ZombieNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class ZombieNPC extends CraftZombie implements ForwardingNPCHolder { + public ZombieNPC(EntityZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieHuskController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieHuskController.java new file mode 100644 index 000000000..4bfc7a752 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieHuskController.java @@ -0,0 +1,193 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftHusk; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.Husk; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ZombieHuskController extends MobEntityController { + public ZombieHuskController() { + super(EntityZombieHuskNPC.class); + } + + @Override + public org.bukkit.entity.Husk getBukkitEntity() { + return (org.bukkit.entity.Husk) super.getBukkitEntity(); + } + + public static class EntityZombieHuskNPC extends Husk implements NPCHolder { + private final CitizensNPC npc; + + public EntityZombieHuskNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityZombieHuskNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ZombieHuskNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class ZombieHuskNPC extends CraftHusk implements ForwardingNPCHolder { + public ZombieHuskNPC(EntityZombieHuskNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieVillagerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieVillagerController.java new file mode 100644 index 000000000..1e8a010c8 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/ZombieVillagerController.java @@ -0,0 +1,193 @@ +package net.citizensnpcs.nms.v1_17_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftVillagerZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.NPCEnderTeleportEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class ZombieVillagerController extends MobEntityController { + public ZombieVillagerController() { + super(EntityZombieVillagerNPC.class); + } + + @Override + public org.bukkit.entity.ZombieVillager getBukkitEntity() { + return (org.bukkit.entity.ZombieVillager) super.getBukkitEntity(); + } + + public static class EntityZombieVillagerNPC extends ZombieVillager implements NPCHolder { + private final CitizensNPC npc; + + public EntityZombieVillagerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityZombieVillagerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + NMSImpl.clearGoals(npc, goalSelector, targetSelector); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + } + return super.canRide(entity); + } + + @Override + public boolean causeFallDamage(float f, float f1, DamageSource damagesource) { + if (npc == null || !npc.isFlyable()) { + return super.causeFallDamage(f, f1, damagesource); + } + return false; + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected void checkFallDamage(double d0, boolean flag, BlockState iblockdata, BlockPos blockposition) { + if (npc == null || !npc.isFlyable()) { + super.checkFallDamage(d0, flag, iblockdata, blockposition); + } + } + + @Override + public void customServerAiStep() { + super.customServerAiStep(); + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + } + } + + @Override + public void dismountTo(double d0, double d1, double d2) { + if (npc == null) { + super.dismountTo(d0, d1, d2); + return; + } + NPCEnderTeleportEvent event = new NPCEnderTeleportEvent(npc); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + super.dismountTo(d0, d1, d2); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.AMBIENT_SOUND_METADATA); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ZombieVillagerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.DEATH_SOUND_METADATA); + } + + @Override + public SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.HURT_SOUND_METADATA); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + if (npc == null) + return super.isLeashed(); + boolean protectedDefault = npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true); + if (!protectedDefault || !npc.data().get(NPC.LEASH_PROTECTED_METADATA, protectedDefault)) + return super.isLeashed(); + if (super.isLeashed()) { + dropLeash(true, false); // clearLeash with client update + } + return false; // shouldLeash + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + } + + public static class ZombieVillagerNPC extends CraftVillagerZombie implements ForwardingNPCHolder { + public ZombieVillagerNPC(EntityZombieVillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/AreaEffectCloudController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/AreaEffectCloudController.java new file mode 100644 index 000000000..cd6d489f9 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/AreaEffectCloudController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftAreaEffectCloud; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.AreaEffectCloud; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; + +public class AreaEffectCloudController extends MobEntityController { + public AreaEffectCloudController() { + super(EntityAreaEffectCloudNPC.class); + } + + @Override + public org.bukkit.entity.AreaEffectCloud getBukkitEntity() { + return (org.bukkit.entity.AreaEffectCloud) super.getBukkitEntity(); + } + + public static class AreaEffectCloudNPC extends CraftAreaEffectCloud implements ForwardingNPCHolder { + public AreaEffectCloudNPC(EntityAreaEffectCloudNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityAreaEffectCloudNPC extends AreaEffectCloud implements NPCHolder { + private final CitizensNPC npc; + + public EntityAreaEffectCloudNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityAreaEffectCloudNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new AreaEffectCloudNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ArmorStandController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ArmorStandController.java new file mode 100644 index 000000000..15c203a6b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ArmorStandController.java @@ -0,0 +1,110 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftArmorStand; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +public class ArmorStandController extends MobEntityController { + public ArmorStandController() { + super(EntityArmorStandNPC.class); + } + + @Override + public org.bukkit.entity.ArmorStand getBukkitEntity() { + return (org.bukkit.entity.ArmorStand) super.getBukkitEntity(); + } + + public static class ArmorStandNPC extends CraftArmorStand implements ForwardingNPCHolder { + public ArmorStandNPC(EntityArmorStandNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityArmorStandNPC extends ArmorStand implements NPCHolder { + private final CitizensNPC npc; + + public EntityArmorStandNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityArmorStandNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ArmorStandNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public InteractionResult interactAt(Player entityhuman, Vec3 vec3d, InteractionHand enumhand) { + if (npc == null) { + return super.interactAt(entityhuman, vec3d, enumhand); + } + PlayerInteractEntityEvent event = new PlayerInteractEntityEvent( + (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), getBukkitEntity()); + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled() ? InteractionResult.FAIL : InteractionResult.SUCCESS; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/BoatController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/BoatController.java new file mode 100644 index 000000000..b29c6a1f5 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/BoatController.java @@ -0,0 +1,230 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftBoat; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class BoatController extends MobEntityController { + public BoatController() { + super(EntityBoatNPC.class); + } + + @Override + public org.bukkit.entity.Boat getBukkitEntity() { + return (org.bukkit.entity.Boat) super.getBukkitEntity(); + } + + public static class BoatNPC extends CraftBoat implements ForwardingNPCHolder { + public BoatNPC(EntityBoatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityBoatNPC extends Boat implements NPCHolder { + private double aC; + private float aD; + private Status aE; + private Status aF; + private double ap; + private double ar; + private final CitizensNPC npc; + + public EntityBoatNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityBoatNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new BoatNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + private Status getStatus() { + Status entityboat_Status = u(); + if (entityboat_Status != null) { + this.aC = (getBoundingBox()).maxY; + return entityboat_Status; + } + if (t()) + return Status.IN_WATER; + float f = getGroundFriction(); + if (f > 0.0F) { + this.aD = f; + return Status.ON_LAND; + } + return Status.IN_AIR; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + private boolean t() { + boolean m = false; + AABB axisalignedbb = getBoundingBox(); + int i = Mth.floor(axisalignedbb.minX); + int j = Mth.ceil(axisalignedbb.maxX); + int k = Mth.floor(axisalignedbb.minY); + int l = Mth.ceil(axisalignedbb.minY + 0.001D); + int i1 = Mth.floor(axisalignedbb.minZ); + int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; + this.aC = Double.MIN_VALUE; + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + for (int k1 = i; k1 < j; k1++) { + for (int l1 = k; l1 < l; l1++) { + for (int i2 = i1; i2 < j1; i2++) { + blockposition_mutableblockposition.set(k1, l1, i2); + FluidState fluid = this.level.getFluidState(blockposition_mutableblockposition); + if (fluid.is(FluidTags.WATER)) { + float f = l1 + fluid.getHeight(this.level, blockposition_mutableblockposition); + this.aC = Math.max(f, this.aC); + m = flag | ((axisalignedbb.minY < f) ? true : false); + } + } + } + } + return m; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + this.aF = this.aE; + aE = getStatus(); + double d1 = isNoGravity() ? 0.0D : -0.04D; + double d2 = 0.0D; + this.ap = 0.05F; + if (this.aF == Status.IN_AIR && this.aE != Status.IN_AIR && this.aE != Status.ON_LAND) { + this.aC = getY(1.0D); + setPos(getX(), (getWaterLevelAbove() - getBbHeight()) + 0.101D, getZ()); + setDeltaMovement(getDeltaMovement().multiply(1.0D, 0.0D, 1.0D)); + this.aE = Status.IN_WATER; + } else { + if (this.aE == Status.IN_WATER) { + d2 = (this.aC - getY()) / getBbHeight(); + this.ap = 0.9F; + } else if (this.aE == Status.UNDER_FLOWING_WATER) { + d1 = -7.0E-4D; + this.ap = 0.9F; + } else if (this.aE == Status.UNDER_WATER) { + d2 = 0.01D; + this.ap = 0.45F; + } else if (this.aE == Status.IN_AIR) { + this.ap = 0.9F; + } else if (this.aE == Status.ON_LAND) { + this.ap = this.aD; + if (getControllingPassenger() instanceof ServerPlayer) { + this.aD /= 2.0F; + } + } + Vec3 vec3d = getDeltaMovement(); + setDeltaMovement(vec3d.x * this.ap, vec3d.y + d1, vec3d.z * this.ap); + this.ar *= this.ap; + if (d2 > 0.0D) { + Vec3 vec3d1 = getDeltaMovement(); + setDeltaMovement(vec3d1.x, (vec3d1.y + d2 * 0.0615D), vec3d1.z); + } + } + move(MoverType.SELF, getDeltaMovement()); + if (isVehicle()) { + setYRot((float) (getYRot() + this.ar)); + } + } else { + super.tick(); + } + } + + private Status u() { + AABB axisalignedbb = getBoundingBox(); + double d0 = axisalignedbb.maxY + 0.001D; + int i = Mth.floor(axisalignedbb.minX); + int j = Mth.ceil(axisalignedbb.maxX); + int k = Mth.floor(axisalignedbb.maxY); + int l = Mth.ceil(d0); + int i1 = Mth.floor(axisalignedbb.minZ); + int j1 = Mth.ceil(axisalignedbb.maxZ); + boolean flag = false; + BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + for (int k1 = i; k1 < j; k1++) { + for (int l1 = k; l1 < l; l1++) { + for (int i2 = i1; i2 < j1; i2++) { + blockposition_mutableblockposition.set(k1, l1, i2); + FluidState fluid = this.level.getFluidState(blockposition_mutableblockposition); + if (fluid.is(FluidTags.WATER) && d0 < (blockposition_mutableblockposition.getY() + + fluid.getHeight(this.level, blockposition_mutableblockposition))) { + if (!fluid.isSource()) + return Status.UNDER_FLOWING_WATER; + flag = true; + } + } + } + } + return flag ? Status.UNDER_WATER : null; + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/DragonFireballController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/DragonFireballController.java new file mode 100644 index 000000000..c7dbcfe9f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/DragonFireballController.java @@ -0,0 +1,107 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftDragonFireball; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.DragonFireball; +import net.minecraft.world.level.Level; + +public class DragonFireballController extends MobEntityController { + public DragonFireballController() { + super(EntityDragonFireballNPC.class); + } + + @Override + public org.bukkit.entity.DragonFireball getBukkitEntity() { + return (org.bukkit.entity.DragonFireball) super.getBukkitEntity(); + } + + public static class DragonFireballNPC extends CraftDragonFireball implements ForwardingNPCHolder { + public DragonFireballNPC(EntityDragonFireballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityDragonFireballNPC extends DragonFireball implements NPCHolder { + private final CitizensNPC npc; + + public EntityDragonFireballNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityDragonFireballNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new DragonFireballNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EggController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EggController.java new file mode 100644 index 000000000..6f44648bb --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EggController.java @@ -0,0 +1,113 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEgg; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownEgg; +import net.minecraft.world.level.Level; + +public class EggController extends AbstractEntityController { + public EggController() { + super(EntityEggNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + ServerLevel ws = ((CraftWorld) at.getWorld()).getHandle(); + final EntityEggNPC handle = new EntityEggNPC(ws, npc, at.getX(), at.getY(), at.getZ()); + return handle.getBukkitEntity(); + } + + @Override + public org.bukkit.entity.Egg getBukkitEntity() { + return (org.bukkit.entity.Egg) super.getBukkitEntity(); + } + + public static class EggNPC extends CraftEgg implements ForwardingNPCHolder { + public EggNPC(EntityEggNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEggNPC extends ThrownEgg implements NPCHolder { + private final CitizensNPC npc; + + public EntityEggNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEggNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + public EntityEggNPC(Level level, NPC npc, double d0, double d1, double d2) { + super(level, d0, d1, d2); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EggNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderCrystalController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderCrystalController.java new file mode 100644 index 000000000..7e02fdc7c --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderCrystalController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEnderCrystal; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import net.minecraft.world.level.Level; + +public class EnderCrystalController extends MobEntityController { + public EnderCrystalController() { + super(EntityEnderCrystalNPC.class); + } + + @Override + public org.bukkit.entity.EnderCrystal getBukkitEntity() { + return (org.bukkit.entity.EnderCrystal) super.getBukkitEntity(); + } + + public static class EnderCrystalNPC extends CraftEnderCrystal implements ForwardingNPCHolder { + public EnderCrystalNPC(EntityEnderCrystalNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEnderCrystalNPC extends EndCrystal implements NPCHolder { + private final CitizensNPC npc; + + public EntityEnderCrystalNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEnderCrystalNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EnderCrystalNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderPearlController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderPearlController.java new file mode 100644 index 000000000..b3890643b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderPearlController.java @@ -0,0 +1,99 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEnderPearl; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.entity.EnderPearl; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.level.Level; + +public class EnderPearlController extends MobEntityController { + public EnderPearlController() { + super(EntityEnderPearlNPC.class); + } + + @Override + public EnderPearl getBukkitEntity() { + return (EnderPearl) super.getBukkitEntity(); + } + + public static class EnderPearlNPC extends CraftEnderPearl implements ForwardingNPCHolder { + public EnderPearlNPC(EntityEnderPearlNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEnderPearlNPC extends ThrownEnderpearl implements NPCHolder { + private final CitizensNPC npc; + + public EntityEnderPearlNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEnderPearlNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EnderPearlNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderSignalController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderSignalController.java new file mode 100644 index 000000000..bf5fd58c2 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EnderSignalController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEnderSignal; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.entity.EnderSignal; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.EyeOfEnder; +import net.minecraft.world.level.Level; + +public class EnderSignalController extends MobEntityController { + public EnderSignalController() { + super(EntityEnderSignalNPC.class); + } + + @Override + public EnderSignal getBukkitEntity() { + return (EnderSignal) super.getBukkitEntity(); + } + + public static class EnderSignalNPC extends CraftEnderSignal implements ForwardingNPCHolder { + public EnderSignalNPC(EntityEnderSignalNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityEnderSignalNPC extends EyeOfEnder implements NPCHolder { + private final CitizensNPC npc; + + public EntityEnderSignalNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEnderSignalNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EnderSignalNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EvokerFangsController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EvokerFangsController.java new file mode 100644 index 000000000..6fef4074c --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/EvokerFangsController.java @@ -0,0 +1,110 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEvokerFangs; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.EvokerFangs; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; + +public class EvokerFangsController extends MobEntityController { + public EvokerFangsController() { + super(EntityEvokerFangsNPC.class); + } + + @Override + public org.bukkit.entity.EvokerFangs getBukkitEntity() { + return (org.bukkit.entity.EvokerFangs) super.getBukkitEntity(); + } + + public static class EntityEvokerFangsNPC extends EvokerFangs implements NPCHolder { + private final CitizensNPC npc; + + public EntityEvokerFangsNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityEvokerFangsNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EvokerFangsNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public InteractionResult interactAt(Player entityhuman, Vec3 vec3d, InteractionHand enumhand) { + if (npc == null) { + return super.interactAt(entityhuman, vec3d, enumhand); + } + PlayerInteractEntityEvent event = new PlayerInteractEntityEvent( + (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), getBukkitEntity()); + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled() ? InteractionResult.FAIL : InteractionResult.SUCCESS; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + } + + public static class EvokerFangsNPC extends CraftEvokerFangs implements ForwardingNPCHolder { + public EvokerFangsNPC(EntityEvokerFangsNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ExperienceOrbController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ExperienceOrbController.java new file mode 100644 index 000000000..454bec521 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ExperienceOrbController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftExperienceOrb; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.level.Level; + +public class ExperienceOrbController extends MobEntityController { + public ExperienceOrbController() { + super(EntityExperienceOrbNPC.class); + } + + @Override + public org.bukkit.entity.ExperienceOrb getBukkitEntity() { + return (org.bukkit.entity.ExperienceOrb) super.getBukkitEntity(); + } + + public static class EntityExperienceOrbNPC extends ExperienceOrb implements NPCHolder { + private final CitizensNPC npc; + + public EntityExperienceOrbNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityExperienceOrbNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ExperienceOrbNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class ExperienceOrbNPC extends CraftExperienceOrb implements ForwardingNPCHolder { + public ExperienceOrbNPC(EntityExperienceOrbNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FallingBlockController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FallingBlockController.java new file mode 100644 index 000000000..9f92da884 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FallingBlockController.java @@ -0,0 +1,161 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftFallingBlock; +import org.bukkit.craftbukkit.v1_17_R1.util.CraftMagicNumbers; +import org.bukkit.entity.FallingBlock; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.event.SpawnReason; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; + +public class FallingBlockController extends AbstractEntityController { + public FallingBlockController() { + super(EntityFallingBlockNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + ServerLevel ws = ((CraftWorld) at.getWorld()).getHandle(); + Block id = Blocks.STONE; + int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0)); + // TODO: how to incorporate this - probably delete? + if (npc.data().has("falling-block-id") || npc.data().has(NPC.ITEM_ID_METADATA)) { + id = CraftMagicNumbers.getBlock(Material.getMaterial( + npc.data(). get(NPC.ITEM_ID_METADATA, npc.data(). get("falling-block-id")))); + } + final EntityFallingBlockNPC handle = new EntityFallingBlockNPC(ws, npc, at.getX(), at.getY(), at.getZ(), + id.defaultBlockState()); + return handle.getBukkitEntity(); + } + + @Override + public FallingBlock getBukkitEntity() { + return (FallingBlock) super.getBukkitEntity(); + } + + public static class EntityFallingBlockNPC extends FallingBlockEntity implements NPCHolder { + private final CitizensNPC npc; + + public EntityFallingBlockNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityFallingBlockNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + public EntityFallingBlockNPC(Level world, NPC npc, double d0, double d1, double d2, BlockState data) { + super(world, d0, d1, d2, data); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new FallingBlockNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + Vec3 mot = getDeltaMovement(); + if (Math.abs(mot.x) > EPSILON || Math.abs(mot.y) > EPSILON || Math.abs(mot.z) > EPSILON) { + mot = mot.multiply(0.98, 0.98, 0.98); + setDeltaMovement(mot); + move(MoverType.SELF, mot); + } + } else { + super.tick(); + } + } + + private static final double EPSILON = 0.001; + } + + public static class FallingBlockNPC extends CraftFallingBlock implements NPCHolder { + private final CitizensNPC npc; + + public FallingBlockNPC(EntityFallingBlockNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + } + + @Override + public NPC getNPC() { + return npc; + } + + public void setType(Material material, int data) { + npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name()); + npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data); + if (npc.isSpawned()) { + npc.despawn(DespawnReason.PENDING_RESPAWN); + npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FireworkController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FireworkController.java new file mode 100644 index 000000000..ca62e1b4d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FireworkController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftFirework; +import org.bukkit.entity.Firework; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.level.Level; + +public class FireworkController extends MobEntityController { + public FireworkController() { + super(EntityFireworkNPC.class); + } + + @Override + public Firework getBukkitEntity() { + return (Firework) super.getBukkitEntity(); + } + + public static class EntityFireworkNPC extends FireworkRocketEntity implements NPCHolder { + private final CitizensNPC npc; + + public EntityFireworkNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityFireworkNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new FireworkNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class FireworkNPC extends CraftFirework implements ForwardingNPCHolder { + public FireworkNPC(EntityFireworkNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FishingHookController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FishingHookController.java new file mode 100644 index 000000000..97392cc12 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/FishingHookController.java @@ -0,0 +1,119 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftFishHook; +import org.bukkit.entity.FishHook; +import org.bukkit.util.Vector; + +import com.mojang.authlib.GameProfile; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.FishingHook; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; + +public class FishingHookController extends MobEntityController { + public FishingHookController() { + super(EntityFishingHookNPC.class); + } + + @Override + public FishHook getBukkitEntity() { + return (FishHook) super.getBukkitEntity(); + } + + public static class EntityFishingHookNPC extends FishingHook implements NPCHolder { + private final CitizensNPC npc; + + public EntityFishingHookNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityFishingHookNPC(EntityType types, Level level, NPC npc) { + super(new ServerPlayer(level.getServer().getServer(), (ServerLevel) level, + new GameProfile(UUID.randomUUID(), "dummyfishhook")) { + }, level, 0, 0); + this.npc = (CitizensNPC) npc; + } + + @Override + public double distanceToSqr(Entity entity) { + if (entity == getPlayerOwner()) { + return 0D; + } + return super.distanceToSqr(entity); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new FishingHookNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + ((ServerPlayer) getPlayerOwner()).setHealth(20F); + getPlayerOwner().unsetRemoved(); + ((ServerPlayer) getPlayerOwner()).getInventory().items.set( + ((ServerPlayer) getPlayerOwner()).getInventory().selected, new ItemStack(Items.FISHING_ROD, 1)); + NMSImpl.setLife(this, 0); + npc.update(); + } else { + super.tick(); + } + } + } + + public static class FishingHookNPC extends CraftFishHook implements ForwardingNPCHolder { + public FishingHookNPC(EntityFishingHookNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/GlowItemFrameController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/GlowItemFrameController.java new file mode 100644 index 000000000..e35ec2cef --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/GlowItemFrameController.java @@ -0,0 +1,139 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftGlowItemFrame; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.event.SpawnReason; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ItemFrameController.EntityItemFrameNPC; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.GlowItemFrame; +import net.minecraft.world.level.Level; + +public class GlowItemFrameController extends MobEntityController { + public GlowItemFrameController() { + super(EntityItemFrameNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + org.bukkit.entity.Entity e = super.createEntity(at, npc); + GlowItemFrame item = (GlowItemFrame) ((CraftEntity) e).getHandle(); + item.setDirection(Direction.EAST); + item.pos = new BlockPos(at.getX(), at.getY(), at.getZ()); + return e; + } + + @Override + public org.bukkit.entity.GlowItemFrame getBukkitEntity() { + return (org.bukkit.entity.GlowItemFrame) super.getBukkitEntity(); + } + + public static class EntityGlowItemFrameNPC extends GlowItemFrame implements NPCHolder { + private final CitizensNPC npc; + + public EntityGlowItemFrameNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityGlowItemFrameNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new GlowItemFrameNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public boolean survives() { + return npc == null || !npc.isProtected() ? super.survives() : true; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class GlowItemFrameNPC extends CraftGlowItemFrame implements NPCHolder { + private final CitizensNPC npc; + + public GlowItemFrameNPC(EntityGlowItemFrameNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + Material id = Material.STONE; + int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0)); + if (npc.data().has(NPC.ITEM_ID_METADATA)) { + id = Material.getMaterial(npc.data(). get(NPC.ITEM_ID_METADATA)); + } + getItem().setType(id); + getItem().setDurability((short) data); + } + + @Override + public NPC getNPC() { + return npc; + } + + public void setType(Material material, int data) { + npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name()); + npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data); + if (npc.isSpawned()) { + npc.despawn(DespawnReason.PENDING_RESPAWN); + npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemController.java new file mode 100644 index 000000000..9f16b3f3b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemController.java @@ -0,0 +1,142 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftItem; +import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; +import org.bukkit.entity.Item; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.event.SpawnReason; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public class ItemController extends AbstractEntityController { + public ItemController() { + super(EntityItemNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + ServerLevel ws = ((CraftWorld) at.getWorld()).getHandle(); + Material id = Material.STONE; + int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0)); + if (npc.data().has(NPC.ITEM_ID_METADATA)) { + id = Material.getMaterial(npc.data(). get(NPC.ITEM_ID_METADATA)); + } + final EntityItemNPC handle = new EntityItemNPC(ws, npc, at.getX(), at.getY(), at.getZ(), + CraftItemStack.asNMSCopy(new org.bukkit.inventory.ItemStack(id, 1, (short) data))); + return handle.getBukkitEntity(); + } + + @Override + public Item getBukkitEntity() { + return (Item) super.getBukkitEntity(); + } + + public static class EntityItemNPC extends ItemEntity implements NPCHolder { + private final CitizensNPC npc; + + public EntityItemNPC(EntityType types, Level level) { + super(types, level); + this.npc = null; + } + + public EntityItemNPC(Level world, NPC npc, double x, double y, double z, ItemStack stack) { + super(world, x, y, z, stack); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ItemNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void playerTouch(Player entityhuman) { + if (npc == null) { + super.playerTouch(entityhuman); + } + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class ItemNPC extends CraftItem implements NPCHolder { + private final CitizensNPC npc; + + public ItemNPC(EntityItemNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + } + + @Override + public NPC getNPC() { + return npc; + } + + public void setType(Material material, int data) { + npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name()); + npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data); + if (npc.isSpawned()) { + npc.despawn(DespawnReason.PENDING_RESPAWN); + npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemFrameController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemFrameController.java new file mode 100644 index 000000000..fa89ac2a8 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ItemFrameController.java @@ -0,0 +1,138 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftItemFrame; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.event.SpawnReason; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.level.Level; + +public class ItemFrameController extends MobEntityController { + public ItemFrameController() { + super(EntityItemFrameNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + org.bukkit.entity.Entity e = super.createEntity(at, npc); + ItemFrame item = (ItemFrame) ((CraftEntity) e).getHandle(); + item.setDirection(Direction.EAST); + item.pos = new BlockPos(at.getX(), at.getY(), at.getZ()); + return e; + } + + @Override + public org.bukkit.entity.ItemFrame getBukkitEntity() { + return (org.bukkit.entity.ItemFrame) super.getBukkitEntity(); + } + + public static class EntityItemFrameNPC extends ItemFrame implements NPCHolder { + private final CitizensNPC npc; + + public EntityItemFrameNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityItemFrameNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ItemFrameNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public boolean survives() { + return npc == null || !npc.isProtected() ? super.survives() : true; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class ItemFrameNPC extends CraftItemFrame implements NPCHolder { + private final CitizensNPC npc; + + public ItemFrameNPC(EntityItemFrameNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + Material id = Material.STONE; + int data = npc.data().get(NPC.ITEM_DATA_METADATA, npc.data().get("falling-block-data", 0)); + if (npc.data().has(NPC.ITEM_ID_METADATA)) { + id = Material.getMaterial(npc.data(). get(NPC.ITEM_ID_METADATA)); + } + getItem().setType(id); + getItem().setDurability((short) data); + } + + @Override + public NPC getNPC() { + return npc; + } + + public void setType(Material material, int data) { + npc.data().setPersistent(NPC.ITEM_ID_METADATA, material.name()); + npc.data().setPersistent(NPC.ITEM_DATA_METADATA, data); + if (npc.isSpawned()) { + npc.despawn(DespawnReason.PENDING_RESPAWN); + npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); + } + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LargeFireballController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LargeFireballController.java new file mode 100644 index 000000000..e92a2bf24 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LargeFireballController.java @@ -0,0 +1,107 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftLargeFireball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.level.Level; + +public class LargeFireballController extends MobEntityController { + public LargeFireballController() { + super(EntityLargeFireballNPC.class); + } + + @Override + public org.bukkit.entity.LargeFireball getBukkitEntity() { + return (org.bukkit.entity.LargeFireball) super.getBukkitEntity(); + } + + public static class EntityLargeFireballNPC extends LargeFireball implements NPCHolder { + private final CitizensNPC npc; + + public EntityLargeFireballNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityLargeFireballNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new LargeFireballNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public void refreshDimensions() { + if (npc == null) { + super.refreshDimensions(); + } else { + NMSImpl.setSize(this, firstTick); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } + + public static class LargeFireballNPC extends CraftLargeFireball implements ForwardingNPCHolder { + public LargeFireballNPC(EntityLargeFireballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LeashController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LeashController.java new file mode 100644 index 000000000..b99002328 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LeashController.java @@ -0,0 +1,101 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftLeash; +import org.bukkit.entity.LeashHitch; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; +import net.minecraft.world.level.Level; + +public class LeashController extends MobEntityController { + public LeashController() { + super(EntityLeashNPC.class); + } + + @Override + public LeashHitch getBukkitEntity() { + return (LeashHitch) super.getBukkitEntity(); + } + + public static class EntityLeashNPC extends LeashFenceKnotEntity implements NPCHolder { + private final CitizensNPC npc; + + public EntityLeashNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityLeashNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new LeashNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public boolean survives() { + return npc == null || !npc.isProtected() ? super.survives() : true; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class LeashNPC extends CraftLeash implements ForwardingNPCHolder { + public LeashNPC(EntityLeashNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LlamaSpitController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LlamaSpitController.java new file mode 100644 index 000000000..a1b094f5e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/LlamaSpitController.java @@ -0,0 +1,116 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftLlamaSpit; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.projectile.LlamaSpit; +import net.minecraft.world.level.Level; + +public class LlamaSpitController extends AbstractEntityController { + public LlamaSpitController() { + super(EntityLlamaSpitNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + ServerLevel ws = ((CraftWorld) at.getWorld()).getHandle(); + final EntityLlamaSpitNPC handle = new EntityLlamaSpitNPC( + NMSImpl. getEntityType(EntityLlamaSpitNPC.class), ws, npc); + handle.absMoveTo(at.getX(), at.getY(), at.getZ(), at.getPitch(), at.getYaw()); + return handle.getBukkitEntity(); + } + + @Override + public org.bukkit.entity.LlamaSpit getBukkitEntity() { + return (org.bukkit.entity.LlamaSpit) super.getBukkitEntity(); + } + + public static class EntityLlamaSpitNPC extends LlamaSpit implements NPCHolder { + private final CitizensNPC npc; + + public EntityLlamaSpitNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityLlamaSpitNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + public EntityLlamaSpitNPC(Level world, NPC npc, Llama entity) { + super(world, entity); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new LlamaSpitNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } + + public static class LlamaSpitNPC extends CraftLlamaSpit implements ForwardingNPCHolder { + public LlamaSpitNPC(EntityLlamaSpitNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MarkerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MarkerController.java new file mode 100644 index 000000000..06ae506fc --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MarkerController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMarker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Marker; +import net.minecraft.world.level.Level; + +public class MarkerController extends MobEntityController { + public MarkerController() { + super(EntityMarkerNPC.class); + } + + @Override + public org.bukkit.entity.Marker getBukkitEntity() { + return (org.bukkit.entity.Marker) super.getBukkitEntity(); + } + + public static class EntityMarkerNPC extends Marker implements NPCHolder { + private final CitizensNPC npc; + + public EntityMarkerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMarkerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MarkerNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class MarkerNPC extends CraftMarker implements ForwardingNPCHolder { + public MarkerNPC(EntityMarkerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartChestController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartChestController.java new file mode 100644 index 000000000..707355f9a --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartChestController.java @@ -0,0 +1,97 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMinecartChest; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartChest; +import net.minecraft.world.level.Level; + +public class MinecartChestController extends MobEntityController { + public MinecartChestController() { + super(EntityMinecartChestNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartChestNPC extends MinecartChest implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartChestNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartChestNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MinecartChestNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + } + + public static class MinecartChestNPC extends CraftMinecartChest implements ForwardingNPCHolder { + public MinecartChestNPC(EntityMinecartChestNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartCommandController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartCommandController.java new file mode 100644 index 000000000..ff4dc1cab --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartCommandController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMinecartCommand; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.level.Level; + +public class MinecartCommandController extends MobEntityController { + public MinecartCommandController() { + super(EntityMinecartCommandNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartCommandNPC extends MinecartCommandBlock implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartCommandNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartCommandNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MinecartCommandNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } + + public static class MinecartCommandNPC extends CraftMinecartCommand implements ForwardingNPCHolder { + public MinecartCommandNPC(EntityMinecartCommandNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartFurnaceController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartFurnaceController.java new file mode 100644 index 000000000..80adf564e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartFurnaceController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMinecartFurnace; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.level.Level; + +public class MinecartFurnaceController extends MobEntityController { + public MinecartFurnaceController() { + super(EntityMinecartFurnaceNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartFurnaceNPC extends MinecartFurnace implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartFurnaceNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartFurnaceNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MinecartFurnaceNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } + + public static class MinecartFurnaceNPC extends CraftMinecartFurnace implements ForwardingNPCHolder { + public MinecartFurnaceNPC(EntityMinecartFurnaceNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartHopperController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartHopperController.java new file mode 100644 index 000000000..3993244d9 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartHopperController.java @@ -0,0 +1,77 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartHopper; +import net.minecraft.world.level.Level; + +public class MinecartHopperController extends MobEntityController { + public MinecartHopperController() { + super(EntityMinecartHopperNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartHopperNPC extends MinecartHopper implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartHopperNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartHopperNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartRideableController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartRideableController.java new file mode 100644 index 000000000..cc8fcb94f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartRideableController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftMinecartRideable; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.Minecart; +import net.minecraft.world.level.Level; + +public class MinecartRideableController extends MobEntityController { + public MinecartRideableController() { + super(EntityMinecartRideableNPC.class); + } + + @Override + public org.bukkit.entity.Minecart getBukkitEntity() { + return (org.bukkit.entity.Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartRideableNPC extends Minecart implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartRideableNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartRideableNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new MinecartRideableNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } + + public static class MinecartRideableNPC extends CraftMinecartRideable implements ForwardingNPCHolder { + public MinecartRideableNPC(EntityMinecartRideableNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartSpawnerController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartSpawnerController.java new file mode 100644 index 000000000..000353944 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartSpawnerController.java @@ -0,0 +1,77 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartSpawner; +import net.minecraft.world.level.Level; + +public class MinecartSpawnerController extends MobEntityController { + public MinecartSpawnerController() { + super(EntityMinecartSpawnerNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartSpawnerNPC extends MinecartSpawner implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartSpawnerNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartSpawnerNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartTNTController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartTNTController.java new file mode 100644 index 000000000..e80a4f569 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/MinecartTNTController.java @@ -0,0 +1,77 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.vehicle.MinecartTNT; +import net.minecraft.world.level.Level; + +public class MinecartTNTController extends MobEntityController { + public MinecartTNTController() { + super(EntityMinecartTNTNPC.class); + } + + @Override + public Minecart getBukkitEntity() { + return (Minecart) super.getBukkitEntity(); + } + + public static class EntityMinecartTNTNPC extends MinecartTNT implements NPCHolder { + private final CitizensNPC npc; + + public EntityMinecartTNTNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityMinecartTNTNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/PaintingController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/PaintingController.java new file mode 100644 index 000000000..2ab581596 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/PaintingController.java @@ -0,0 +1,100 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPainting; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.level.Level; + +public class PaintingController extends MobEntityController { + public PaintingController() { + super(EntityPaintingNPC.class); + } + + @Override + public org.bukkit.entity.Painting getBukkitEntity() { + return (org.bukkit.entity.Painting) super.getBukkitEntity(); + } + + public static class EntityPaintingNPC extends Painting implements NPCHolder { + private final CitizensNPC npc; + + public EntityPaintingNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityPaintingNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new PaintingNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public boolean survives() { + return npc == null || !npc.isProtected() ? super.survives() : true; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class PaintingNPC extends CraftPainting implements ForwardingNPCHolder { + public PaintingNPC(EntityPaintingNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ShulkerBulletController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ShulkerBulletController.java new file mode 100644 index 000000000..afd3ae40e --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ShulkerBulletController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftShulkerBullet; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ShulkerBullet; +import net.minecraft.world.level.Level; + +public class ShulkerBulletController extends MobEntityController { + public ShulkerBulletController() { + super(EntityShulkerBulletNPC.class); + } + + @Override + public org.bukkit.entity.ShulkerBullet getBukkitEntity() { + return (org.bukkit.entity.ShulkerBullet) super.getBukkitEntity(); + } + + public static class EntityShulkerBulletNPC extends ShulkerBullet implements NPCHolder { + private final CitizensNPC npc; + + public EntityShulkerBulletNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityShulkerBulletNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ShulkerBulletNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class ShulkerBulletNPC extends CraftShulkerBullet implements ForwardingNPCHolder { + public ShulkerBulletNPC(EntityShulkerBulletNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SmallFireballController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SmallFireballController.java new file mode 100644 index 000000000..08c3f576a --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SmallFireballController.java @@ -0,0 +1,98 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSmallFireball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.level.Level; + +public class SmallFireballController extends MobEntityController { + public SmallFireballController() { + super(EntitySmallFireballNPC.class); + } + + @Override + public org.bukkit.entity.SmallFireball getBukkitEntity() { + return (org.bukkit.entity.SmallFireball) super.getBukkitEntity(); + } + + public static class EntitySmallFireballNPC extends SmallFireball implements NPCHolder { + private final CitizensNPC npc; + + public EntitySmallFireballNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySmallFireballNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SmallFireballNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } + + public static class SmallFireballNPC extends CraftSmallFireball implements ForwardingNPCHolder { + public SmallFireballNPC(EntitySmallFireballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SnowballController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SnowballController.java new file mode 100644 index 000000000..04bb5d29c --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SnowballController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftSnowball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.Snowball; +import net.minecraft.world.level.Level; + +public class SnowballController extends MobEntityController { + public SnowballController() { + super(EntitySnowballNPC.class); + } + + @Override + public org.bukkit.entity.Snowball getBukkitEntity() { + return (org.bukkit.entity.Snowball) super.getBukkitEntity(); + } + + public static class EntitySnowballNPC extends Snowball implements NPCHolder { + private final CitizensNPC npc; + + public EntitySnowballNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySnowballNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SnowballNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class SnowballNPC extends CraftSnowball implements ForwardingNPCHolder { + public SnowballNPC(EntitySnowballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SpectralArrowController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SpectralArrowController.java new file mode 100644 index 000000000..0ea24f251 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/SpectralArrowController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftArrow; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.entity.Arrow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.SpectralArrow; +import net.minecraft.world.level.Level; + +public class SpectralArrowController extends MobEntityController { + public SpectralArrowController() { + super(EntitySpectralArrowNPC.class); + } + + @Override + public Arrow getBukkitEntity() { + return (Arrow) super.getBukkitEntity(); + } + + public static class EntitySpectralArrowNPC extends SpectralArrow implements NPCHolder { + private final CitizensNPC npc; + + public EntitySpectralArrowNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySpectralArrowNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SpectralArrowNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class SpectralArrowNPC extends CraftArrow implements ForwardingNPCHolder { + public SpectralArrowNPC(EntitySpectralArrowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TNTPrimedController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TNTPrimedController.java new file mode 100644 index 000000000..fa87704f6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TNTPrimedController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTNTPrimed; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.level.Level; + +public class TNTPrimedController extends MobEntityController { + public TNTPrimedController() { + super(EntityTNTPrimedNPC.class); + } + + @Override + public TNTPrimed getBukkitEntity() { + return (TNTPrimed) super.getBukkitEntity(); + } + + public static class EntityTNTPrimedNPC extends PrimedTnt implements NPCHolder { + private final CitizensNPC npc; + + public EntityTNTPrimedNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTNTPrimedNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TNTPrimedNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class TNTPrimedNPC extends CraftTNTPrimed implements ForwardingNPCHolder { + public TNTPrimedNPC(EntityTNTPrimedNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownExpBottleController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownExpBottleController.java new file mode 100644 index 000000000..cf8de1471 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownExpBottleController.java @@ -0,0 +1,99 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftThrownExpBottle; +import org.bukkit.entity.ThrownExpBottle; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownExperienceBottle; +import net.minecraft.world.level.Level; + +public class ThrownExpBottleController extends MobEntityController { + public ThrownExpBottleController() { + super(EntityThrownExpBottleNPC.class); + } + + @Override + public ThrownExpBottle getBukkitEntity() { + return (ThrownExpBottle) super.getBukkitEntity(); + } + + public static class EntityThrownExpBottleNPC extends ThrownExperienceBottle implements NPCHolder { + private final CitizensNPC npc; + + public EntityThrownExpBottleNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityThrownExpBottleNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ThrownExpBottleNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.data().get(NPC.DEFAULT_PROTECTED_METADATA, true)) { + super.tick(); + } + } else { + super.tick(); + } + } + } + + public static class ThrownExpBottleNPC extends CraftThrownExpBottle implements ForwardingNPCHolder { + public ThrownExpBottleNPC(EntityThrownExpBottleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownPotionController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownPotionController.java new file mode 100644 index 000000000..27101604b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownPotionController.java @@ -0,0 +1,114 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftThrownPotion; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; + +public class ThrownPotionController extends MobEntityController { + public ThrownPotionController() { + super(EntityThrownPotionNPC.class); + } + + @Override + public org.bukkit.entity.ThrownPotion getBukkitEntity() { + return (org.bukkit.entity.ThrownPotion) super.getBukkitEntity(); + } + + public static class EntityThrownPotionNPC extends ThrownPotion implements NPCHolder { + private final CitizensNPC npc; + + public EntityThrownPotionNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityThrownPotionNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + if (getItem() != null && getItem().getItem().equals(Items.LINGERING_POTION)) { + NMSImpl.setBukkitEntity(this, new LingeringThrownPotionNPC(this)); + } else { + NMSImpl.setBukkitEntity(this, new SplashThrownPotionNPC(this)); + } + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class LingeringThrownPotionNPC extends CraftThrownPotion implements NPCHolder { + private final CitizensNPC npc; + + public LingeringThrownPotionNPC(EntityThrownPotionNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + } + + @Override + public NPC getNPC() { + return npc; + } + } + + public static class SplashThrownPotionNPC extends CraftThrownPotion implements ForwardingNPCHolder { + public SplashThrownPotionNPC(EntityThrownPotionNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownTridentController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownTridentController.java new file mode 100644 index 000000000..cee0c8441 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/ThrownTridentController.java @@ -0,0 +1,96 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTrident; +import org.bukkit.entity.Trident; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.ThrownTrident; +import net.minecraft.world.level.Level; + +public class ThrownTridentController extends MobEntityController { + public ThrownTridentController() { + super(EntityThrownTridentNPC.class); + } + + @Override + public Trident getBukkitEntity() { + return (Trident) super.getBukkitEntity(); + } + + public static class EntityThrownTridentNPC extends ThrownTrident implements NPCHolder { + private final CitizensNPC npc; + + public EntityThrownTridentNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityThrownTridentNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new ThrownTridentNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class ThrownTridentNPC extends CraftTrident implements ForwardingNPCHolder { + public ThrownTridentNPC(EntityThrownTridentNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TippedArrowController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TippedArrowController.java new file mode 100644 index 000000000..82f696de2 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/TippedArrowController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftTippedArrow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.Arrow; +import net.minecraft.world.level.Level; + +public class TippedArrowController extends MobEntityController { + public TippedArrowController() { + super(EntityTippedArrowNPC.class); + } + + @Override + public org.bukkit.entity.Arrow getBukkitEntity() { + return (org.bukkit.entity.Arrow) super.getBukkitEntity(); + } + + public static class EntityTippedArrowNPC extends Arrow implements NPCHolder { + private final CitizensNPC npc; + + public EntityTippedArrowNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTippedArrowNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TippedArrowNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class TippedArrowNPC extends CraftTippedArrow implements ForwardingNPCHolder { + public TippedArrowNPC(EntityTippedArrowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/WitherSkullController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/WitherSkullController.java new file mode 100644 index 000000000..4218727de --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/nonliving/WitherSkullController.java @@ -0,0 +1,95 @@ +package net.citizensnpcs.nms.v1_17_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWitherSkull; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_17_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_17_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.projectile.WitherSkull; +import net.minecraft.world.level.Level; + +public class WitherSkullController extends MobEntityController { + public WitherSkullController() { + super(EntityWitherSkullNPC.class); + } + + @Override + public org.bukkit.entity.WitherSkull getBukkitEntity() { + return (org.bukkit.entity.WitherSkull) super.getBukkitEntity(); + } + + public static class EntityWitherSkullNPC extends WitherSkull implements NPCHolder { + private final CitizensNPC npc; + + public EntityWitherSkullNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWitherSkullNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WitherSkullNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void push(double x, double y, double z) { + Vector vector = Util.callPushEvent(npc, x, y, z); + if (vector != null) { + super.push(vector.getX(), vector.getY(), vector.getZ()); + } + } + + @Override + public void push(Entity entity) { + // this method is called by both the entities involved - cancelling + // it will not stop the NPC from moving. + super.push(entity); + if (npc != null) { + Util.callCollisionEvent(npc, entity.getBukkitEntity()); + } + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + } + + public static class WitherSkullNPC extends CraftWitherSkull implements ForwardingNPCHolder { + public WitherSkullNPC(EntityWitherSkullNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyChannel.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyChannel.java new file mode 100644 index 000000000..d60a4740f --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyChannel.java @@ -0,0 +1,80 @@ +package net.citizensnpcs.nms.v1_17_R1.network; + +import java.net.SocketAddress; + +import io.netty.channel.AbstractChannel; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelMetadata; +import io.netty.channel.ChannelOutboundBuffer; +import io.netty.channel.DefaultChannelConfig; +import io.netty.channel.EventLoop; + +public class EmptyChannel extends AbstractChannel { + private final ChannelConfig config = new DefaultChannelConfig(this); + + public EmptyChannel(Channel parent) { + super(parent); + } + + @Override + public ChannelConfig config() { + config.setAutoRead(true); + return config; + } + + @Override + protected void doBeginRead() throws Exception { + } + + @Override + protected void doBind(SocketAddress arg0) throws Exception { + } + + @Override + protected void doClose() throws Exception { + } + + @Override + protected void doDisconnect() throws Exception { + } + + @Override + protected void doWrite(ChannelOutboundBuffer arg0) throws Exception { + } + + @Override + public boolean isActive() { + return false; + } + + @Override + protected boolean isCompatible(EventLoop arg0) { + return true; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + protected SocketAddress localAddress0() { + return null; + } + + @Override + public ChannelMetadata metadata() { + return new ChannelMetadata(true); + } + + @Override + protected AbstractUnsafe newUnsafe() { + return null; + } + + @Override + protected SocketAddress remoteAddress0() { + return null; + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetHandler.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetHandler.java new file mode 100644 index 000000000..f298e5a15 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetHandler.java @@ -0,0 +1,17 @@ +package net.citizensnpcs.nms.v1_17_R1.network; + +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.Packet; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; + +public class EmptyNetHandler extends ServerGamePacketListenerImpl { + public EmptyNetHandler(MinecraftServer minecraftServer, Connection networkManager, ServerPlayer entityPlayer) { + super(minecraftServer, networkManager, entityPlayer); + } + + @Override + public void send(Packet packet) { + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetworkManager.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetworkManager.java new file mode 100644 index 000000000..80eac78d6 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptyNetworkManager.java @@ -0,0 +1,25 @@ +package net.citizensnpcs.nms.v1_17_R1.network; + +import java.io.IOException; + +import io.netty.util.concurrent.GenericFutureListener; +import net.citizensnpcs.nms.v1_17_R1.util.NMSImpl; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketFlow; + +public class EmptyNetworkManager extends Connection { + public EmptyNetworkManager(PacketFlow flag) throws IOException { + super(flag); + NMSImpl.initNetworkManager(this); + } + + @Override + public boolean isConnected() { + return true; + } + + @Override + public void send(Packet packet, GenericFutureListener genericfuturelistener) { + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptySocket.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptySocket.java new file mode 100644 index 000000000..bfc0389bc --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/network/EmptySocket.java @@ -0,0 +1,21 @@ +package net.citizensnpcs.nms.v1_17_R1.network; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +public class EmptySocket extends Socket { + @Override + public InputStream getInputStream() { + return new ByteArrayInputStream(EMPTY); + } + + @Override + public OutputStream getOutputStream() { + return new ByteArrayOutputStream(10); + } + + private static final byte[] EMPTY = new byte[50]; +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/trait/Commands.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/trait/Commands.java new file mode 100644 index 000000000..f4e4566ad --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/trait/Commands.java @@ -0,0 +1,561 @@ +package net.citizensnpcs.nms.v1_17_R1.trait; + +import java.util.List; + +import org.bukkit.DyeColor; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarFlag; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Cat; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Fox; +import org.bukkit.entity.Llama.Color; +import org.bukkit.entity.MushroomCow; +import org.bukkit.entity.Panda; +import org.bukkit.entity.Parrot.Variant; +import org.bukkit.entity.TropicalFish.Pattern; +import org.bukkit.entity.Villager; +import org.bukkit.entity.Villager.Profession; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.Lists; + +import net.citizensnpcs.api.command.Command; +import net.citizensnpcs.api.command.CommandContext; +import net.citizensnpcs.api.command.Requirements; +import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.command.exception.CommandUsageException; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.util.Colorizer; +import net.citizensnpcs.api.util.Messaging; +import net.citizensnpcs.trait.VillagerProfession; +import net.citizensnpcs.trait.versioned.BeeTrait; +import net.citizensnpcs.trait.versioned.BossBarTrait; +import net.citizensnpcs.trait.versioned.CatTrait; +import net.citizensnpcs.trait.versioned.FoxTrait; +import net.citizensnpcs.trait.versioned.LlamaTrait; +import net.citizensnpcs.trait.versioned.MushroomCowTrait; +import net.citizensnpcs.trait.versioned.PandaTrait; +import net.citizensnpcs.trait.versioned.ParrotTrait; +import net.citizensnpcs.trait.versioned.PhantomTrait; +import net.citizensnpcs.trait.versioned.PolarBearTrait; +import net.citizensnpcs.trait.versioned.PufferFishTrait; +import net.citizensnpcs.trait.versioned.ShulkerTrait; +import net.citizensnpcs.trait.versioned.SnowmanTrait; +import net.citizensnpcs.trait.versioned.TropicalFishTrait; +import net.citizensnpcs.trait.versioned.VillagerTrait; +import net.citizensnpcs.util.Messages; +import net.citizensnpcs.util.Util; + +public class Commands { + @Command( + aliases = { "npc" }, + usage = "bee (-s/-n) --anger anger", + desc = "Sets bee modifiers", + modifiers = { "bee" }, + min = 1, + max = 1, + flags = "sn", + permission = "citizens.npc.bee") + @Requirements(selected = true, ownership = true, types = EntityType.BEE) + public void bee(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + BeeTrait trait = npc.getOrAddTrait(BeeTrait.class); + String output = ""; + if (args.hasValueFlag("anger")) { + int anger = args.getFlagInteger("anger"); + if (anger < 0) { + throw new CommandException(Messages.INVALID_BEE_ANGER); + } + trait.setAnger(anger); + output += ' ' + Messaging.tr(Messages.BEE_ANGER_SET, args.getFlag("anger")); + } + if (args.hasFlag('s')) { + trait.setStung(!trait.hasStung()); + output += ' ' + (trait.hasStung() ? Messaging.tr(Messages.BEE_STUNG, npc.getName()) + : Messaging.tr(Messages.BEE_NOT_STUNG, npc.getName())); + } + if (args.hasFlag('n')) { + trait.setNectar(!trait.hasNectar()); + output += ' ' + (trait.hasNectar() ? Messaging.tr(Messages.BEE_HAS_NECTAR, npc.getName()) + : Messaging.tr(Messages.BEE_NO_NECTAR, npc.getName())); + } + if (!output.isEmpty()) { + Messaging.send(sender, output.trim()); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "bossbar --color [color] --title [title] --visible [visible] --flags [flags]", + desc = "Edit bossbar properties", + modifiers = { "bossbar" }, + min = 1, + max = 1) + @Requirements(selected = true, ownership = true, types = { EntityType.WITHER, EntityType.ENDER_DRAGON }) + public void bossbar(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + BossBarTrait trait = npc.getOrAddTrait(BossBarTrait.class); + if (args.hasValueFlag("color")) { + BarColor color = Util.matchEnum(BarColor.values(), args.getFlag("color")); + trait.setColor(color); + } + + if (args.hasValueFlag("title")) { + trait.setTitle(Colorizer.parseColors(args.getFlag("title"))); + } + if (args.hasValueFlag("visible")) { + trait.setVisible(Boolean.parseBoolean(args.getFlag("visible"))); + } + if (args.hasValueFlag("flags")) { + List flags = Lists.newArrayList(); + for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(args.getFlag("flags"))) { + BarFlag flag = Util.matchEnum(BarFlag.values(), s); + if (flag != null) { + flags.add(flag); + } + } + trait.setFlags(flags); + } + } + + @Command( + aliases = { "npc" }, + usage = "cat (-s/-n/-l) --type type --ccolor collar color", + desc = "Sets cat modifiers", + modifiers = { "cat" }, + min = 1, + max = 1, + flags = "snl", + permission = "citizens.npc.cat") + @Requirements(selected = true, ownership = true, types = EntityType.CAT) + public void cat(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + CatTrait trait = npc.getOrAddTrait(CatTrait.class); + String output = ""; + if (args.hasValueFlag("type")) { + Cat.Type type = Util.matchEnum(Cat.Type.values(), args.getFlag("type")); + if (type == null) { + throw new CommandUsageException(Messages.INVALID_CAT_TYPE, Util.listValuesPretty(Cat.Type.values())); + } + trait.setType(type); + output += ' ' + Messaging.tr(Messages.CAT_TYPE_SET, args.getFlag("type")); + } + if (args.hasValueFlag("ccolor")) { + DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("ccolor")); + if (color == null) { + throw new CommandUsageException(Messages.INVALID_CAT_COLLAR_COLOR, + Util.listValuesPretty(DyeColor.values())); + } + trait.setCollarColor(color); + output += ' ' + Messaging.tr(Messages.CAT_COLLAR_COLOR_SET, args.getFlag("ccolor")); + } + if (args.hasFlag('s')) { + trait.setSitting(true); + output += ' ' + Messaging.tr(Messages.CAT_STARTED_SITTING, npc.getName()); + } else if (args.hasFlag('n')) { + trait.setSitting(false); + output += ' ' + Messaging.tr(Messages.CAT_STOPPED_SITTING, npc.getName()); + } + if (args.hasFlag('l')) { + trait.setLyingDown(!trait.isLyingDown()); + output += ' ' + Messaging.tr(trait.isLyingDown() ? Messages.CAT_STARTED_LYING : Messages.CAT_STOPPED_LYING, + npc.getName()); + } + if (!output.isEmpty()) { + Messaging.send(sender, output.trim()); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "fox --type type --sleeping [true|false] --sitting [true|false] --crouching [true|false]", + desc = "Sets fox modifiers", + modifiers = { "fox" }, + min = 1, + max = 1, + permission = "citizens.npc.fox") + @Requirements(selected = true, ownership = true, types = EntityType.FOX) + public void fox(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + FoxTrait trait = npc.getOrAddTrait(FoxTrait.class); + String output = ""; + if (args.hasValueFlag("type")) { + Fox.Type type = Util.matchEnum(Fox.Type.values(), args.getFlag("type")); + if (type == null) { + throw new CommandUsageException(Messages.INVALID_FOX_TYPE, Util.listValuesPretty(Fox.Type.values())); + } + trait.setType(type); + output += ' ' + Messaging.tr(Messages.FOX_TYPE_SET, args.getFlag("type")); + } + if (args.hasValueFlag("sleeping")) { + boolean sleeping = Boolean.parseBoolean(args.getFlag("sleeping")); + trait.setSleeping(sleeping); + output += ' ' + Messaging.tr(sleeping ? Messages.FOX_SLEEPING_SET : Messages.FOX_SLEEPING_UNSET); + } + if (args.hasValueFlag("sitting")) { + boolean sitting = Boolean.parseBoolean(args.getFlag("sitting")); + trait.setSitting(sitting); + output += ' ' + Messaging.tr(sitting ? Messages.FOX_SITTING_SET : Messages.FOX_SITTING_UNSET); + } + if (args.hasValueFlag("crouching")) { + boolean crouching = Boolean.parseBoolean(args.getFlag("crouching")); + trait.setCrouching(crouching); + output += ' ' + Messaging.tr(crouching ? Messages.FOX_CROUCHING_SET : Messages.FOX_CROUCHING_UNSET); + } + if (!output.isEmpty()) { + Messaging.send(sender, output.trim()); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "llama (--color color) (--strength strength)", + desc = "Sets llama modifiers", + modifiers = { "llama" }, + min = 1, + max = 1, + permission = "citizens.npc.llama") + @Requirements(selected = true, ownership = true, types = { EntityType.LLAMA, EntityType.TRADER_LLAMA }) + public void llama(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + LlamaTrait trait = npc.getOrAddTrait(LlamaTrait.class); + String output = ""; + if (args.hasValueFlag("color") || args.hasValueFlag("colour")) { + String colorRaw = args.getFlag("color", args.getFlag("colour")); + Color color = Util.matchEnum(Color.values(), colorRaw); + if (color == null) { + String valid = Util.listValuesPretty(Color.values()); + throw new CommandException(Messages.INVALID_LLAMA_COLOR, valid); + } + trait.setColor(color); + output += Messaging.tr(Messages.LLAMA_COLOR_SET, Util.prettyEnum(color)); + } + if (args.hasValueFlag("strength")) { + trait.setStrength(Math.max(1, Math.min(5, args.getFlagInteger("strength")))); + output += Messaging.tr(Messages.LLAMA_STRENGTH_SET, args.getFlagInteger("strength")); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } + } + + @Command( + aliases = { "npc" }, + usage = "mcow (--variant [variant])", + desc = "Sets mushroom cow modifiers.", + modifiers = { "mcow", "mushroomcow" }, + min = 1, + max = 1, + permission = "citizens.npc.mushroomcow") + @Requirements(selected = true, ownership = true, types = { EntityType.MUSHROOM_COW }) + public void mushroomcow(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + MushroomCowTrait trait = npc.getOrAddTrait(MushroomCowTrait.class); + boolean hasArg = false; + if (args.hasValueFlag("variant")) { + MushroomCow.Variant variant = Util.matchEnum(MushroomCow.Variant.values(), args.getFlag("variant")); + if (variant == null) { + Messaging.sendErrorTr(sender, Messages.INVALID_MUSHROOM_COW_VARIANT, + Util.listValuesPretty(MushroomCow.Variant.values())); + return; + } + trait.setVariant(variant); + Messaging.sendTr(sender, Messages.MUSHROOM_COW_VARIANT_SET, npc.getName(), variant); + hasArg = true; + } + if (!hasArg) { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "panda --gene (main gene) --hgene (hidden gene) -s(itting)", + desc = "Sets panda modifiers", + modifiers = { "panda" }, + flags = "s", + min = 1, + max = 1, + permission = "citizens.npc.panda") + @Requirements(selected = true, ownership = true, types = EntityType.PANDA) + public void panda(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + PandaTrait trait = npc.getOrAddTrait(PandaTrait.class); + String output = ""; + if (args.hasValueFlag("gene")) { + Panda.Gene gene = Util.matchEnum(Panda.Gene.values(), args.getFlag("gene")); + if (gene == null) { + throw new CommandUsageException(Messages.INVALID_PANDA_GENE, + Util.listValuesPretty(Panda.Gene.values())); + } + trait.setMainGene(gene); + output += ' ' + Messaging.tr(Messages.PANDA_MAIN_GENE_SET, args.getFlag("gene")); + } + if (args.hasValueFlag("hgene")) { + Panda.Gene gene = Util.matchEnum(Panda.Gene.values(), args.getFlag("hgene")); + if (gene == null) { + throw new CommandUsageException(Messages.INVALID_PANDA_GENE, + Util.listValuesPretty(Panda.Gene.values())); + } + trait.setHiddenGene(gene); + output += ' ' + Messaging.tr(Messages.PANDA_HIDDEN_GENE_SET, args.getFlag("hgene")); + } + if (args.hasFlag('s')) { + boolean isSitting = trait.toggleSitting(); + output += ' ' + Messaging.tr(isSitting ? Messages.PANDA_SITTING : Messages.PANDA_STOPPED_SITTING); + } + if (!output.isEmpty()) { + Messaging.send(sender, output.trim()); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "parrot (--variant variant)", + desc = "Sets parrot modifiers", + modifiers = { "parrot" }, + min = 1, + max = 1, + permission = "citizens.npc.parrot") + @Requirements(selected = true, ownership = true, types = EntityType.PARROT) + public void parrot(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + ParrotTrait trait = npc.getOrAddTrait(ParrotTrait.class); + String output = ""; + if (args.hasValueFlag("variant")) { + String variantRaw = args.getFlag("variant"); + Variant variant = Util.matchEnum(Variant.values(), variantRaw); + if (variant == null) { + String valid = Util.listValuesPretty(Variant.values()); + throw new CommandException(Messages.INVALID_PARROT_VARIANT, valid); + } + trait.setVariant(variant); + output += Messaging.tr(Messages.PARROT_VARIANT_SET, Util.prettyEnum(variant)); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } + } + + @Command( + aliases = { "npc" }, + usage = "phantom (--size size)", + desc = "Sets phantom modifiers", + modifiers = { "phantom" }, + min = 1, + max = 1, + permission = "citizens.npc.phantom") + @Requirements(selected = true, ownership = true, types = EntityType.PHANTOM) + public void phantom(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + PhantomTrait trait = npc.getOrAddTrait(PhantomTrait.class); + String output = ""; + if (args.hasValueFlag("size")) { + if (args.getFlagInteger("size") <= 0) { + throw new CommandUsageException(); + } + trait.setSize(args.getFlagInteger("size")); + output += Messaging.tr(Messages.PHANTOM_STATE_SET, args.getFlagInteger("size")); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "polarbear (-r)", + desc = "Sets polarbear modifiers.", + modifiers = { "polarbear" }, + min = 1, + max = 1, + flags = "r", + permission = "citizens.npc.polarbear") + @Requirements(selected = true, ownership = true, types = { EntityType.POLAR_BEAR }) + public void polarbear(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + PolarBearTrait trait = npc.getOrAddTrait(PolarBearTrait.class); + String output = ""; + if (args.hasFlag('r')) { + trait.setRearing(!trait.isRearing()); + output += Messaging.tr( + trait.isRearing() ? Messages.POLAR_BEAR_REARING : Messages.POLAR_BEAR_STOPPED_REARING, + npc.getName()); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "pufferfish (--state state)", + desc = "Sets pufferfish modifiers", + modifiers = { "pufferfish" }, + min = 1, + max = 1, + permission = "citizens.npc.pufferfish") + @Requirements(selected = true, ownership = true, types = EntityType.PUFFERFISH) + public void pufferfish(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + PufferFishTrait trait = npc.getOrAddTrait(PufferFishTrait.class); + String output = ""; + if (args.hasValueFlag("state")) { + int state = Math.min(Math.max(args.getFlagInteger("state"), 0), 3); + trait.setPuffState(state); + output += Messaging.tr(Messages.PUFFERFISH_STATE_SET, state); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } + } + + @Command( + aliases = { "npc" }, + usage = "shulker (--peek [peek] --color [color])", + desc = "Sets shulker modifiers.", + modifiers = { "shulker" }, + min = 1, + max = 1, + permission = "citizens.npc.shulker") + @Requirements(selected = true, ownership = true, types = { EntityType.SHULKER }) + public void shulker(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + ShulkerTrait trait = npc.getOrAddTrait(ShulkerTrait.class); + boolean hasArg = false; + if (args.hasValueFlag("peek")) { + int peek = (byte) args.getFlagInteger("peek"); + trait.setPeek(peek); + Messaging.sendTr(sender, Messages.SHULKER_PEEK_SET, npc.getName(), peek); + hasArg = true; + } + if (args.hasValueFlag("color")) { + DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("color")); + if (color == null) { + Messaging.sendErrorTr(sender, Messages.INVALID_SHULKER_COLOR, Util.listValuesPretty(DyeColor.values())); + return; + } + trait.setColor(color); + Messaging.sendTr(sender, Messages.SHULKER_COLOR_SET, npc.getName(), Util.prettyEnum(color)); + hasArg = true; + } + if (!hasArg) { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "snowman (-d[erp])", + desc = "Sets snowman modifiers.", + modifiers = { "snowman" }, + min = 1, + max = 1, + flags = "d", + permission = "citizens.npc.snowman") + @Requirements(selected = true, ownership = true, types = { EntityType.SNOWMAN }) + public void snowman(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + SnowmanTrait trait = npc.getOrAddTrait(SnowmanTrait.class); + boolean hasArg = false; + if (args.hasFlag('d')) { + boolean isDerp = trait.toggleDerp(); + Messaging.sendTr(sender, isDerp ? Messages.SNOWMAN_DERP_SET : Messages.SNOWMAN_DERP_STOPPED, npc.getName()); + hasArg = true; + } + if (!hasArg) { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "tfish (--body color) (--pattern pattern) (--patterncolor color)", + desc = "Sets tropical fish modifiers", + modifiers = { "tfish" }, + min = 1, + max = 1, + permission = "citizens.npc.tropicalfish") + @Requirements(selected = true, ownership = true, types = EntityType.TROPICAL_FISH) + public void tropicalfish(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + TropicalFishTrait trait = npc.getOrAddTrait(TropicalFishTrait.class); + String output = ""; + if (args.hasValueFlag("body")) { + DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("body")); + if (color == null) { + throw new CommandException(Messages.INVALID_TROPICALFISH_COLOR, + Util.listValuesPretty(DyeColor.values())); + } + trait.setBodyColor(color); + output += Messaging.tr(Messages.TROPICALFISH_BODY_COLOR_SET, Util.prettyEnum(color)); + } + if (args.hasValueFlag("patterncolor")) { + DyeColor color = Util.matchEnum(DyeColor.values(), args.getFlag("patterncolor")); + if (color == null) { + throw new CommandException(Messages.INVALID_TROPICALFISH_COLOR, + Util.listValuesPretty(DyeColor.values())); + } + trait.setPatternColor(color); + output += Messaging.tr(Messages.TROPICALFISH_PATTERN_COLOR_SET, Util.prettyEnum(color)); + } + if (args.hasValueFlag("pattern")) { + Pattern pattern = Util.matchEnum(Pattern.values(), args.getFlag("pattern")); + if (pattern == null) { + throw new CommandException(Messages.INVALID_TROPICALFISH_PATTERN, + Util.listValuesPretty(Pattern.values())); + } + trait.setPattern(pattern); + output += Messaging.tr(Messages.TROPICALFISH_PATTERN_SET, Util.prettyEnum(pattern)); + } + if (!output.isEmpty()) { + Messaging.send(sender, output); + } else { + throw new CommandUsageException(); + } + } + + @Command( + aliases = { "npc" }, + usage = "villager (--level level) (--type type) (--profession profession)", + desc = "Sets villager modifiers", + modifiers = { "villager" }, + min = 1, + max = 1, + permission = "citizens.npc.villager") + @Requirements(selected = true, ownership = true, types = EntityType.VILLAGER) + public void villager(CommandContext args, CommandSender sender, NPC npc) throws CommandException { + VillagerTrait trait = npc.getOrAddTrait(VillagerTrait.class); + String output = ""; + if (args.hasValueFlag("level")) { + if (args.getFlagInteger("level") < 0) { + throw new CommandUsageException(); + } + trait.setLevel(args.getFlagInteger("level")); + output += " " + Messaging.tr(Messages.VILLAGER_LEVEL_SET, args.getFlagInteger("level")); + } + if (args.hasValueFlag("type")) { + Villager.Type type = Util.matchEnum(Villager.Type.values(), args.getFlag("type")); + if (type == null) { + throw new CommandException(Messages.INVALID_VILLAGER_TYPE, + Util.listValuesPretty(Villager.Type.values())); + } + trait.setType(type); + output += " " + Messaging.tr(Messages.VILLAGER_TYPE_SET, args.getFlag("type")); + } + if (args.hasValueFlag("profession")) { + Profession parsed = Util.matchEnum(Profession.values(), args.getFlag("profession")); + if (parsed == null) { + throw new CommandException(Messages.INVALID_PROFESSION, args.getString(1), + Joiner.on(',').join(Profession.values())); + } + npc.getOrAddTrait(VillagerProfession.class).setProfession(parsed); + output += " " + Messaging.tr(Messages.PROFESSION_SET, npc.getName(), args.getFlag("profession")); + } + if (!output.isEmpty()) { + Messaging.send(sender, output.trim()); + } else { + throw new CommandUsageException(); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CitizensBlockBreaker.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CitizensBlockBreaker.java new file mode 100644 index 000000000..ffffe4654 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CitizensBlockBreaker.java @@ -0,0 +1,188 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; +import org.bukkit.entity.Player; + +import net.citizensnpcs.api.ai.tree.BehaviorStatus; +import net.citizensnpcs.api.npc.BlockBreaker; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.PlayerAnimation; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.FluidTags; +import net.minecraft.world.effect.MobEffectUtil; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; + +public class CitizensBlockBreaker extends BlockBreaker { + private final BlockBreakerConfiguration configuration; + private int currentDamage; + private int currentTick; + private final Entity entity; + private boolean isDigging = true; + private final Location location; + private boolean setTarget; + private int startDigTick; + private final int x, y, z; + + public CitizensBlockBreaker(org.bukkit.entity.Entity entity, org.bukkit.block.Block target, + BlockBreakerConfiguration config) { + this.entity = ((CraftEntity) entity).getHandle(); + this.x = target.getX(); + this.y = target.getY(); + this.z = target.getZ(); + this.location = target.getLocation(); + this.startDigTick = (int) (System.currentTimeMillis() / 50); + this.configuration = config; + } + + private double distanceSquared() { + return Math.pow(entity.getX() - x, 2) + Math.pow(NMS.getHeight(entity.getBukkitEntity()) + entity.getY() - y, 2) + + Math.pow(entity.getZ() - z, 2); + } + + private ItemStack getCurrentItem() { + return configuration.item() != null ? CraftItemStack.asNMSCopy(configuration.item()) + : entity instanceof LivingEntity ? ((LivingEntity) entity).getMainHandItem() : null; + } + + private float getStrength(BlockState block) { + float base = block.getDestroySpeed(null, BlockPos.ZERO); + return base < 0.0F ? 0.0F : (!isDestroyable(block) ? 1.0F / base / 100.0F : strengthMod(block) / base / 30.0F); + } + + private boolean isDestroyable(BlockState block) { + if (block.requiresCorrectToolForDrops()) { + return true; + } else { + ItemStack current = getCurrentItem(); + return current != null ? current.isCorrectToolForDrops(block) : false; + } + } + + @Override + public void reset() { + if (setTarget && entity instanceof NPCHolder) { + NPC npc = ((NPCHolder) entity).getNPC(); + if (npc != null && npc.getNavigator().isNavigating()) { + npc.getNavigator().cancelNavigation(); + } + } + setTarget = false; + if (configuration.callback() != null) { + configuration.callback().run(); + } + isDigging = false; + setBlockDamage(currentDamage = -1); + } + + @Override + public BehaviorStatus run() { + if (entity.isRemoved()) { + return BehaviorStatus.FAILURE; + } + if (!isDigging) { + return BehaviorStatus.SUCCESS; + } + currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit + if (configuration.radiusSquared() > 0 && distanceSquared() >= configuration.radiusSquared()) { + startDigTick = currentTick; + if (entity instanceof NPCHolder) { + NPC npc = ((NPCHolder) entity).getNPC(); + if (npc != null && !npc.getNavigator().isNavigating()) { + npc.getNavigator() + .setTarget(entity.level.getWorld().getBlockAt(x, y, z).getLocation().add(0, 1, 0)); + setTarget = true; + } + } + return BehaviorStatus.RUNNING; + } + Util.faceLocation(entity.getBukkitEntity(), location); + if (entity instanceof ServerPlayer) { + PlayerAnimation.ARM_SWING.play((Player) entity.getBukkitEntity()); + } + BlockState block = entity.level.getBlockState(new BlockPos(x, y, z)); + if (block == null || block.getBlock() == Blocks.AIR) { + return BehaviorStatus.SUCCESS; + } else { + int tickDifference = currentTick - startDigTick; + float damage = getStrength(block) * (tickDifference + 1) * configuration.blockStrengthModifier(); + if (damage >= 1F) { + entity.level.getWorld().getBlockAt(x, y, z) + .breakNaturally(CraftItemStack.asCraftMirror(getCurrentItem())); + return BehaviorStatus.SUCCESS; + } + int modifiedDamage = (int) (damage * 10.0F); + if (modifiedDamage != currentDamage) { + setBlockDamage(modifiedDamage); + currentDamage = modifiedDamage; + } + } + return BehaviorStatus.RUNNING; + } + + private void setBlockDamage(int modifiedDamage) { + ((ServerLevel) entity.level).destroyBlockProgress(entity.getId(), new BlockPos(x, y, z), modifiedDamage); + // TODO: check this works + } + + @Override + public boolean shouldExecute() { + return entity.level.getBlockState(new BlockPos(x, y, z)).getBlock() != Blocks.AIR; + } + + private float strengthMod(BlockState block) { + ItemStack itemstack = getCurrentItem(); + float f = itemstack.getDestroySpeed(block); + if (entity instanceof LivingEntity) { + LivingEntity handle = (LivingEntity) entity; + if (f > 1.0F) { + int i = EnchantmentHelper.getBlockEfficiency(handle); + if (i > 0) { + f += i * i + 1; + } + } + if (MobEffectUtil.hasDigSpeed(handle)) { + f *= 1.0F + (MobEffectUtil.getDigSpeedAmplification(handle) + 1) * 0.2F; + } + if (handle.hasEffect(MobEffects.DIG_SLOWDOWN)) { + float f1 = 1.0F; + switch (handle.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) { + case 0: + f1 = 0.3F; + break; + case 1: + f1 = 0.09F; + break; + case 2: + f1 = 0.0027F; + break; + case 3: + default: + f1 = 8.1E-4F; + } + f *= f1; + } + + if (handle.isEyeInFluid(FluidTags.WATER) && !EnchantmentHelper.hasAquaAffinity(handle)) { + f /= 5.0F; + } + + } + if (!entity.isOnGround()) { + f /= 5.0F; + } + return f; + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CustomEntityRegistry.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CustomEntityRegistry.java new file mode 100644 index 000000000..1ae95eeb0 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/CustomEntityRegistry.java @@ -0,0 +1,348 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.lang.invoke.MethodHandle; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.Set; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; +import com.mojang.serialization.Lifecycle; + +import net.citizensnpcs.util.NMS; +import net.minecraft.core.DefaultedRegistry; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.AreaEffectCloud; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.entity.GlowSquid; +import net.minecraft.world.entity.LightningBolt; +import net.minecraft.world.entity.Marker; +import net.minecraft.world.entity.ambient.Bat; +import net.minecraft.world.entity.animal.Bee; +import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.animal.Chicken; +import net.minecraft.world.entity.animal.Cod; +import net.minecraft.world.entity.animal.Cow; +import net.minecraft.world.entity.animal.Dolphin; +import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.IronGolem; +import net.minecraft.world.entity.animal.MushroomCow; +import net.minecraft.world.entity.animal.Ocelot; +import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.Parrot; +import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.entity.animal.PolarBear; +import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.Salmon; +import net.minecraft.world.entity.animal.Sheep; +import net.minecraft.world.entity.animal.SnowGolem; +import net.minecraft.world.entity.animal.Squid; +import net.minecraft.world.entity.animal.TropicalFish; +import net.minecraft.world.entity.animal.Turtle; +import net.minecraft.world.entity.animal.Wolf; +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import net.minecraft.world.entity.animal.goat.Goat; +import net.minecraft.world.entity.animal.horse.Donkey; +import net.minecraft.world.entity.animal.horse.Horse; +import net.minecraft.world.entity.animal.horse.Llama; +import net.minecraft.world.entity.animal.horse.Mule; +import net.minecraft.world.entity.animal.horse.SkeletonHorse; +import net.minecraft.world.entity.animal.horse.TraderLlama; +import net.minecraft.world.entity.animal.horse.ZombieHorse; +import net.minecraft.world.entity.boss.enderdragon.EndCrystal; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.entity.decoration.GlowItemFrame; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.entity.monster.Blaze; +import net.minecraft.world.entity.monster.CaveSpider; +import net.minecraft.world.entity.monster.Creeper; +import net.minecraft.world.entity.monster.Drowned; +import net.minecraft.world.entity.monster.ElderGuardian; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Endermite; +import net.minecraft.world.entity.monster.Evoker; +import net.minecraft.world.entity.monster.Ghast; +import net.minecraft.world.entity.monster.Giant; +import net.minecraft.world.entity.monster.Guardian; +import net.minecraft.world.entity.monster.Husk; +import net.minecraft.world.entity.monster.Illusioner; +import net.minecraft.world.entity.monster.MagmaCube; +import net.minecraft.world.entity.monster.Phantom; +import net.minecraft.world.entity.monster.Pillager; +import net.minecraft.world.entity.monster.Ravager; +import net.minecraft.world.entity.monster.Shulker; +import net.minecraft.world.entity.monster.Silverfish; +import net.minecraft.world.entity.monster.Skeleton; +import net.minecraft.world.entity.monster.Slime; +import net.minecraft.world.entity.monster.Spider; +import net.minecraft.world.entity.monster.Stray; +import net.minecraft.world.entity.monster.Strider; +import net.minecraft.world.entity.monster.Vex; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.monster.Witch; +import net.minecraft.world.entity.monster.WitherSkeleton; +import net.minecraft.world.entity.monster.Zoglin; +import net.minecraft.world.entity.monster.Zombie; +import net.minecraft.world.entity.monster.ZombieVillager; +import net.minecraft.world.entity.monster.ZombifiedPiglin; +import net.minecraft.world.entity.monster.hoglin.Hoglin; +import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.world.entity.monster.piglin.PiglinBrute; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.WanderingTrader; +import net.minecraft.world.entity.projectile.Arrow; +import net.minecraft.world.entity.projectile.DragonFireball; +import net.minecraft.world.entity.projectile.EvokerFangs; +import net.minecraft.world.entity.projectile.EyeOfEnder; +import net.minecraft.world.entity.projectile.FireworkRocketEntity; +import net.minecraft.world.entity.projectile.FishingHook; +import net.minecraft.world.entity.projectile.LargeFireball; +import net.minecraft.world.entity.projectile.LlamaSpit; +import net.minecraft.world.entity.projectile.ShulkerBullet; +import net.minecraft.world.entity.projectile.SmallFireball; +import net.minecraft.world.entity.projectile.Snowball; +import net.minecraft.world.entity.projectile.SpectralArrow; +import net.minecraft.world.entity.projectile.ThrownEgg; +import net.minecraft.world.entity.projectile.ThrownEnderpearl; +import net.minecraft.world.entity.projectile.ThrownExperienceBottle; +import net.minecraft.world.entity.projectile.ThrownPotion; +import net.minecraft.world.entity.projectile.ThrownTrident; +import net.minecraft.world.entity.projectile.WitherSkull; +import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.Minecart; +import net.minecraft.world.entity.vehicle.MinecartChest; +import net.minecraft.world.entity.vehicle.MinecartCommandBlock; +import net.minecraft.world.entity.vehicle.MinecartFurnace; +import net.minecraft.world.entity.vehicle.MinecartHopper; +import net.minecraft.world.entity.vehicle.MinecartSpawner; +import net.minecraft.world.entity.vehicle.MinecartTNT; + +@SuppressWarnings("rawtypes") +public class CustomEntityRegistry extends DefaultedRegistry { + private final BiMap entities = HashBiMap.create(); + private final BiMap entityClasses = this.entities.inverse(); + private final Map entityIds = Maps.newHashMap(); + private final MappedRegistry> wrapped; + + @SuppressWarnings("unchecked") + public CustomEntityRegistry(DefaultedRegistry> original) throws Throwable { + super(original.getDefaultKey().getNamespace(), + (ResourceKey>>) IREGISTRY_RESOURCE_KEY.invoke(original), + (Lifecycle) IREGISTRY_LIFECYCLE.invoke(original)); + this.wrapped = original; + } + + @Override + public Object byId(int var0) { + return this.wrapped.byId(var0); + } + + public EntityType findType(Class search) { + return minecraftClassMap.inverse().get(search); + /* + for (Object type : wrapped) { + if (minecraftClassMap.get(type) == search) { + return (EntityTypes) type; + } + } + return null; + */ + } + + @Override + public EntityType get(ResourceLocation key) { + if (entities.containsKey(key)) { + return entities.get(key); + } + + return wrapped.get(key); + } + + @Override + public int getId(Object key) { + if (entityIds.containsKey(key)) { + return entityIds.get(key); + } + + return wrapped.getId((EntityType) key); + } + + @Override + public ResourceLocation getKey(Object value) { + if (entityClasses.containsKey(value)) { + return entityClasses.get(value); + } + + return wrapped.getKey((EntityType) value); + } + + @Override + public Optional getOptional(ResourceLocation var0) { + if (entities.containsKey(var0)) { + return Optional.of(entities.get(var0)); + } + + return this.wrapped.getOptional(var0); + } + + @Override + public Object getRandom(Random paramRandom) { + return wrapped.getRandom(paramRandom); + } + + public MappedRegistry> getWrapped() { + return wrapped; + } + + @Override + public Iterator iterator() { + return (Iterator) wrapped.iterator(); + } + + @Override + public Set keySet() { + return (Set) wrapped.keySet(); + } + + public void put(int entityId, ResourceLocation key, EntityType entityClass) { + entities.put(key, entityClass); + entityIds.put(entityClass, entityId); + } + + private static final MethodHandle IREGISTRY_LIFECYCLE = NMS.getGetter(Registry.class, "bv"); + // replace regex + // .*?> ([A-Z_]+).*?of\((.*?)::new.*?$ + // minecraftClassMap.put(EntityType.\1, \2.class); + private static final MethodHandle IREGISTRY_RESOURCE_KEY = NMS.getGetter(Registry.class, "b"); + private static final BiMap> minecraftClassMap = HashBiMap.create(); + static { + + minecraftClassMap.put(EntityType.AREA_EFFECT_CLOUD, AreaEffectCloud.class); + minecraftClassMap.put(EntityType.ARMOR_STAND, ArmorStand.class); + minecraftClassMap.put(EntityType.ARROW, Arrow.class); + minecraftClassMap.put(EntityType.AXOLOTL, Axolotl.class); + minecraftClassMap.put(EntityType.BAT, Bat.class); + minecraftClassMap.put(EntityType.BEE, Bee.class); + minecraftClassMap.put(EntityType.BLAZE, Blaze.class); + minecraftClassMap.put(EntityType.BOAT, Boat.class); + minecraftClassMap.put(EntityType.CAT, Cat.class); + minecraftClassMap.put(EntityType.CAVE_SPIDER, CaveSpider.class); + minecraftClassMap.put(EntityType.CHICKEN, Chicken.class); + minecraftClassMap.put(EntityType.COD, Cod.class); + minecraftClassMap.put(EntityType.COW, Cow.class); + minecraftClassMap.put(EntityType.CREEPER, Creeper.class); + minecraftClassMap.put(EntityType.DOLPHIN, Dolphin.class); + minecraftClassMap.put(EntityType.DONKEY, Donkey.class); + minecraftClassMap.put(EntityType.DRAGON_FIREBALL, DragonFireball.class); + minecraftClassMap.put(EntityType.DROWNED, Drowned.class); + minecraftClassMap.put(EntityType.ELDER_GUARDIAN, ElderGuardian.class); + minecraftClassMap.put(EntityType.END_CRYSTAL, EndCrystal.class); + minecraftClassMap.put(EntityType.ENDER_DRAGON, EnderDragon.class); + minecraftClassMap.put(EntityType.ENDERMAN, EnderMan.class); + minecraftClassMap.put(EntityType.ENDERMITE, Endermite.class); + minecraftClassMap.put(EntityType.EVOKER, Evoker.class); + minecraftClassMap.put(EntityType.EVOKER_FANGS, EvokerFangs.class); + minecraftClassMap.put(EntityType.EXPERIENCE_ORB, ExperienceOrb.class); + minecraftClassMap.put(EntityType.EYE_OF_ENDER, EyeOfEnder.class); + minecraftClassMap.put(EntityType.FALLING_BLOCK, FallingBlockEntity.class); + minecraftClassMap.put(EntityType.FIREWORK_ROCKET, FireworkRocketEntity.class); + minecraftClassMap.put(EntityType.FOX, Fox.class); + minecraftClassMap.put(EntityType.GHAST, Ghast.class); + minecraftClassMap.put(EntityType.GIANT, Giant.class); + minecraftClassMap.put(EntityType.GLOW_ITEM_FRAME, GlowItemFrame.class); + minecraftClassMap.put(EntityType.GLOW_SQUID, GlowSquid.class); + minecraftClassMap.put(EntityType.GOAT, Goat.class); + minecraftClassMap.put(EntityType.GUARDIAN, Guardian.class); + minecraftClassMap.put(EntityType.HOGLIN, Hoglin.class); + minecraftClassMap.put(EntityType.HORSE, Horse.class); + minecraftClassMap.put(EntityType.HUSK, Husk.class); + minecraftClassMap.put(EntityType.ILLUSIONER, Illusioner.class); + minecraftClassMap.put(EntityType.IRON_GOLEM, IronGolem.class); + minecraftClassMap.put(EntityType.ITEM, ItemEntity.class); + minecraftClassMap.put(EntityType.ITEM_FRAME, ItemFrame.class); + minecraftClassMap.put(EntityType.FIREBALL, LargeFireball.class); + minecraftClassMap.put(EntityType.LEASH_KNOT, LeashFenceKnotEntity.class); + minecraftClassMap.put(EntityType.LIGHTNING_BOLT, LightningBolt.class); + minecraftClassMap.put(EntityType.LLAMA, Llama.class); + minecraftClassMap.put(EntityType.LLAMA_SPIT, LlamaSpit.class); + minecraftClassMap.put(EntityType.MAGMA_CUBE, MagmaCube.class); + minecraftClassMap.put(EntityType.MARKER, Marker.class); + minecraftClassMap.put(EntityType.MINECART, Minecart.class); + minecraftClassMap.put(EntityType.CHEST_MINECART, MinecartChest.class); + minecraftClassMap.put(EntityType.COMMAND_BLOCK_MINECART, MinecartCommandBlock.class); + minecraftClassMap.put(EntityType.FURNACE_MINECART, MinecartFurnace.class); + minecraftClassMap.put(EntityType.HOPPER_MINECART, MinecartHopper.class); + minecraftClassMap.put(EntityType.SPAWNER_MINECART, MinecartSpawner.class); + minecraftClassMap.put(EntityType.TNT_MINECART, MinecartTNT.class); + minecraftClassMap.put(EntityType.MULE, Mule.class); + minecraftClassMap.put(EntityType.MOOSHROOM, MushroomCow.class); + minecraftClassMap.put(EntityType.OCELOT, Ocelot.class); + minecraftClassMap.put(EntityType.PAINTING, Painting.class); + minecraftClassMap.put(EntityType.PANDA, Panda.class); + minecraftClassMap.put(EntityType.PARROT, Parrot.class); + minecraftClassMap.put(EntityType.PHANTOM, Phantom.class); + minecraftClassMap.put(EntityType.PIG, Pig.class); + minecraftClassMap.put(EntityType.PIGLIN, Piglin.class); + minecraftClassMap.put(EntityType.PIGLIN_BRUTE, PiglinBrute.class); + minecraftClassMap.put(EntityType.PILLAGER, Pillager.class); + minecraftClassMap.put(EntityType.POLAR_BEAR, PolarBear.class); + minecraftClassMap.put(EntityType.TNT, PrimedTnt.class); + minecraftClassMap.put(EntityType.PUFFERFISH, Pufferfish.class); + minecraftClassMap.put(EntityType.RABBIT, Rabbit.class); + minecraftClassMap.put(EntityType.RAVAGER, Ravager.class); + minecraftClassMap.put(EntityType.SALMON, Salmon.class); + minecraftClassMap.put(EntityType.SHEEP, Sheep.class); + minecraftClassMap.put(EntityType.SHULKER, Shulker.class); + minecraftClassMap.put(EntityType.SHULKER_BULLET, ShulkerBullet.class); + minecraftClassMap.put(EntityType.SILVERFISH, Silverfish.class); + minecraftClassMap.put(EntityType.SKELETON, Skeleton.class); + minecraftClassMap.put(EntityType.SKELETON_HORSE, SkeletonHorse.class); + minecraftClassMap.put(EntityType.SLIME, Slime.class); + minecraftClassMap.put(EntityType.SMALL_FIREBALL, SmallFireball.class); + minecraftClassMap.put(EntityType.SNOW_GOLEM, SnowGolem.class); + minecraftClassMap.put(EntityType.SNOWBALL, Snowball.class); + minecraftClassMap.put(EntityType.SPECTRAL_ARROW, SpectralArrow.class); + minecraftClassMap.put(EntityType.SPIDER, Spider.class); + minecraftClassMap.put(EntityType.SQUID, Squid.class); + minecraftClassMap.put(EntityType.STRAY, Stray.class); + minecraftClassMap.put(EntityType.STRIDER, Strider.class); + minecraftClassMap.put(EntityType.EGG, ThrownEgg.class); + minecraftClassMap.put(EntityType.ENDER_PEARL, ThrownEnderpearl.class); + minecraftClassMap.put(EntityType.EXPERIENCE_BOTTLE, ThrownExperienceBottle.class); + minecraftClassMap.put(EntityType.POTION, ThrownPotion.class); + minecraftClassMap.put(EntityType.TRIDENT, ThrownTrident.class); + minecraftClassMap.put(EntityType.TRADER_LLAMA, TraderLlama.class); + minecraftClassMap.put(EntityType.TROPICAL_FISH, TropicalFish.class); + minecraftClassMap.put(EntityType.TURTLE, Turtle.class); + minecraftClassMap.put(EntityType.VEX, Vex.class); + minecraftClassMap.put(EntityType.VILLAGER, Villager.class); + minecraftClassMap.put(EntityType.VINDICATOR, Vindicator.class); + minecraftClassMap.put(EntityType.WANDERING_TRADER, WanderingTrader.class); + minecraftClassMap.put(EntityType.WITCH, Witch.class); + minecraftClassMap.put(EntityType.WITHER, WitherBoss.class); + minecraftClassMap.put(EntityType.WITHER_SKELETON, WitherSkeleton.class); + minecraftClassMap.put(EntityType.WITHER_SKULL, WitherSkull.class); + minecraftClassMap.put(EntityType.WOLF, Wolf.class); + minecraftClassMap.put(EntityType.ZOGLIN, Zoglin.class); + minecraftClassMap.put(EntityType.ZOMBIE, Zombie.class); + minecraftClassMap.put(EntityType.ZOMBIE_HORSE, ZombieHorse.class); + minecraftClassMap.put(EntityType.ZOMBIE_VILLAGER, ZombieVillager.class); + minecraftClassMap.put(EntityType.ZOMBIFIED_PIGLIN, ZombifiedPiglin.class); + minecraftClassMap.put(EntityType.FISHING_BOBBER, FishingHook.class); + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/EmptyAdvancementDataPlayer.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/EmptyAdvancementDataPlayer.java new file mode 100644 index 000000000..e911fb246 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/EmptyAdvancementDataPlayer.java @@ -0,0 +1,75 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.io.File; +import java.lang.invoke.MethodHandle; +import java.util.Set; + +import com.mojang.datafixers.DataFixer; + +import net.citizensnpcs.util.NMS; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementProgress; +import net.minecraft.server.PlayerAdvancements; +import net.minecraft.server.ServerAdvancementManager; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.PlayerList; + +public class EmptyAdvancementDataPlayer extends PlayerAdvancements { + public EmptyAdvancementDataPlayer(DataFixer datafixer, PlayerList playerlist, + ServerAdvancementManager advancementdataworld, File file, ServerPlayer entityplayer) { + super(datafixer, playerlist, advancementdataworld, file, entityplayer); + this.save(); + } + + @Override + public boolean award(Advancement advancement, String s) { + return false; + } + + @Override + public void flushDirty(ServerPlayer entityplayer) { + } + + @Override + public AdvancementProgress getOrStartProgress(Advancement advancement) { + return new AdvancementProgress(); + } + + @Override + public boolean revoke(Advancement advancement, String s) { + return false; + } + + @Override + public void save() { + clear(this); + } + + @Override + public void setPlayer(ServerPlayer entityplayer) { + } + + @Override + public void setSelectedTab(Advancement advancement) { + } + + @Override + public void stopListening() { + } + + public static void clear(PlayerAdvancements data) { + data.stopListening(); + data.advancements.clear(); + try { + ((Set) I.invoke(data)).clear(); + ((Set) J.invoke(data)).clear(); + ((Set) K.invoke(data)).clear(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static final MethodHandle I = NMS.getGetter(PlayerAdvancements.class, "i"); + private static final MethodHandle J = NMS.getGetter(PlayerAdvancements.class, "j"); + private static final MethodHandle K = NMS.getGetter(PlayerAdvancements.class, "k"); +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/ForwardingNPCHolder.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/ForwardingNPCHolder.java new file mode 100644 index 000000000..0e4154770 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/ForwardingNPCHolder.java @@ -0,0 +1,21 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import org.bukkit.entity.Entity; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.util.Messaging; +import net.citizensnpcs.npc.ai.NPCHolder; + +public interface ForwardingNPCHolder extends NPCHolder, Entity { + @Override + default NPC getNPC() { + net.minecraft.world.entity.Entity handle = NMSImpl.getHandle(this); + if (!(handle instanceof NPCHolder)) { + if (Messaging.isDebugging()) { + Messaging.debug("ForwardingNPCHolder with an improper bukkit entity", this, handle); + } + return null; + } + return ((NPCHolder) handle).getNPC(); + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSBoundingBox.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSBoundingBox.java new file mode 100644 index 000000000..417e0560b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSBoundingBox.java @@ -0,0 +1,20 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import net.citizensnpcs.api.util.BoundingBox; +import net.minecraft.world.phys.AABB; + +public class NMSBoundingBox { + private NMSBoundingBox() { + } + + public static BoundingBox wrap(AABB bb) { + double minX = 0, minY = 0, minZ = 0, maxX = 0, maxY = 0, maxZ = 0; + minX = bb.minX; + minY = bb.minY; + minZ = bb.minZ; + maxX = bb.maxX; + maxY = bb.maxY; + maxZ = bb.maxZ; + return new BoundingBox(minX, minY, minZ, maxX, maxY, maxZ); + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java new file mode 100644 index 000000000..10d4ed20d --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/NMSImpl.java @@ -0,0 +1,1963 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Field; +import java.net.SocketAddress; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.TreeMap; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.craftbukkit.v1_17_R1.CraftServer; +import org.bukkit.craftbukkit.v1_17_R1.CraftSound; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_17_R1.boss.CraftBossBar; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_17_R1.entity.CraftWither; +import org.bukkit.craftbukkit.v1_17_R1.event.CraftEventFactory; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Player; +import org.bukkit.entity.Tameable; +import org.bukkit.entity.Wither; +import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.plugin.PluginLoadOrder; +import org.bukkit.scoreboard.Team; +import org.bukkit.util.Vector; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.GameProfileRepository; +import com.mojang.authlib.HttpAuthenticationService; +import com.mojang.authlib.minecraft.MinecraftSessionService; +import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; +import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; +import com.mojang.authlib.yggdrasil.response.MinecraftProfilePropertiesResponse; +import com.mojang.util.UUIDTypeAdapter; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.ai.NavigatorParameters; +import net.citizensnpcs.api.ai.event.CancelReason; +import net.citizensnpcs.api.command.CommandManager; +import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.npc.BlockBreaker; +import net.citizensnpcs.api.npc.BlockBreaker.BlockBreakerConfiguration; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.npc.NPCRegistry; +import net.citizensnpcs.api.trait.TraitInfo; +import net.citizensnpcs.api.util.BoundingBox; +import net.citizensnpcs.api.util.Messaging; +import net.citizensnpcs.nms.v1_17_R1.entity.AxolotlController; +import net.citizensnpcs.nms.v1_17_R1.entity.BatController; +import net.citizensnpcs.nms.v1_17_R1.entity.BeeController; +import net.citizensnpcs.nms.v1_17_R1.entity.BlazeController; +import net.citizensnpcs.nms.v1_17_R1.entity.CatController; +import net.citizensnpcs.nms.v1_17_R1.entity.CaveSpiderController; +import net.citizensnpcs.nms.v1_17_R1.entity.ChickenController; +import net.citizensnpcs.nms.v1_17_R1.entity.CodController; +import net.citizensnpcs.nms.v1_17_R1.entity.CowController; +import net.citizensnpcs.nms.v1_17_R1.entity.CreeperController; +import net.citizensnpcs.nms.v1_17_R1.entity.DolphinController; +import net.citizensnpcs.nms.v1_17_R1.entity.DrownedController; +import net.citizensnpcs.nms.v1_17_R1.entity.EnderDragonController; +import net.citizensnpcs.nms.v1_17_R1.entity.EndermanController; +import net.citizensnpcs.nms.v1_17_R1.entity.EndermiteController; +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.citizensnpcs.nms.v1_17_R1.entity.EvokerController; +import net.citizensnpcs.nms.v1_17_R1.entity.FoxController; +import net.citizensnpcs.nms.v1_17_R1.entity.GhastController; +import net.citizensnpcs.nms.v1_17_R1.entity.GiantController; +import net.citizensnpcs.nms.v1_17_R1.entity.GlowSquidController; +import net.citizensnpcs.nms.v1_17_R1.entity.GoatController; +import net.citizensnpcs.nms.v1_17_R1.entity.GuardianController; +import net.citizensnpcs.nms.v1_17_R1.entity.GuardianElderController; +import net.citizensnpcs.nms.v1_17_R1.entity.HoglinController; +import net.citizensnpcs.nms.v1_17_R1.entity.HorseController; +import net.citizensnpcs.nms.v1_17_R1.entity.HorseDonkeyController; +import net.citizensnpcs.nms.v1_17_R1.entity.HorseMuleController; +import net.citizensnpcs.nms.v1_17_R1.entity.HorseSkeletonController; +import net.citizensnpcs.nms.v1_17_R1.entity.HorseZombieController; +import net.citizensnpcs.nms.v1_17_R1.entity.HumanController; +import net.citizensnpcs.nms.v1_17_R1.entity.IllusionerController; +import net.citizensnpcs.nms.v1_17_R1.entity.IronGolemController; +import net.citizensnpcs.nms.v1_17_R1.entity.LlamaController; +import net.citizensnpcs.nms.v1_17_R1.entity.MagmaCubeController; +import net.citizensnpcs.nms.v1_17_R1.entity.MushroomCowController; +import net.citizensnpcs.nms.v1_17_R1.entity.OcelotController; +import net.citizensnpcs.nms.v1_17_R1.entity.PandaController; +import net.citizensnpcs.nms.v1_17_R1.entity.ParrotController; +import net.citizensnpcs.nms.v1_17_R1.entity.PhantomController; +import net.citizensnpcs.nms.v1_17_R1.entity.PigController; +import net.citizensnpcs.nms.v1_17_R1.entity.PigZombieController; +import net.citizensnpcs.nms.v1_17_R1.entity.PiglinBruteController; +import net.citizensnpcs.nms.v1_17_R1.entity.PiglinController; +import net.citizensnpcs.nms.v1_17_R1.entity.PillagerController; +import net.citizensnpcs.nms.v1_17_R1.entity.PolarBearController; +import net.citizensnpcs.nms.v1_17_R1.entity.PufferFishController; +import net.citizensnpcs.nms.v1_17_R1.entity.RabbitController; +import net.citizensnpcs.nms.v1_17_R1.entity.RavagerController; +import net.citizensnpcs.nms.v1_17_R1.entity.SalmonController; +import net.citizensnpcs.nms.v1_17_R1.entity.SheepController; +import net.citizensnpcs.nms.v1_17_R1.entity.ShulkerController; +import net.citizensnpcs.nms.v1_17_R1.entity.SilverfishController; +import net.citizensnpcs.nms.v1_17_R1.entity.SkeletonController; +import net.citizensnpcs.nms.v1_17_R1.entity.SkeletonStrayController; +import net.citizensnpcs.nms.v1_17_R1.entity.SkeletonWitherController; +import net.citizensnpcs.nms.v1_17_R1.entity.SlimeController; +import net.citizensnpcs.nms.v1_17_R1.entity.SnowmanController; +import net.citizensnpcs.nms.v1_17_R1.entity.SpiderController; +import net.citizensnpcs.nms.v1_17_R1.entity.SquidController; +import net.citizensnpcs.nms.v1_17_R1.entity.StriderController; +import net.citizensnpcs.nms.v1_17_R1.entity.TraderLlamaController; +import net.citizensnpcs.nms.v1_17_R1.entity.TropicalFishController; +import net.citizensnpcs.nms.v1_17_R1.entity.TurtleController; +import net.citizensnpcs.nms.v1_17_R1.entity.VexController; +import net.citizensnpcs.nms.v1_17_R1.entity.VillagerController; +import net.citizensnpcs.nms.v1_17_R1.entity.VindicatorController; +import net.citizensnpcs.nms.v1_17_R1.entity.WanderingTraderController; +import net.citizensnpcs.nms.v1_17_R1.entity.WitchController; +import net.citizensnpcs.nms.v1_17_R1.entity.WitherController; +import net.citizensnpcs.nms.v1_17_R1.entity.WolfController; +import net.citizensnpcs.nms.v1_17_R1.entity.ZoglinController; +import net.citizensnpcs.nms.v1_17_R1.entity.ZombieController; +import net.citizensnpcs.nms.v1_17_R1.entity.ZombieHuskController; +import net.citizensnpcs.nms.v1_17_R1.entity.ZombieVillagerController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.AreaEffectCloudController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ArmorStandController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.BoatController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.DragonFireballController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.EggController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.EnderCrystalController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.EnderPearlController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.EnderSignalController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.EvokerFangsController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.FallingBlockController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.FireworkController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.FishingHookController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.GlowItemFrameController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ItemController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ItemFrameController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.LargeFireballController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.LeashController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.LlamaSpitController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MarkerController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartChestController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartCommandController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartFurnaceController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartHopperController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartRideableController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.MinecartTNTController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.PaintingController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ShulkerBulletController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.SmallFireballController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.SnowballController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.SpectralArrowController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.TNTPrimedController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ThrownExpBottleController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ThrownPotionController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.ThrownTridentController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.TippedArrowController; +import net.citizensnpcs.nms.v1_17_R1.entity.nonliving.WitherSkullController; +import net.citizensnpcs.nms.v1_17_R1.network.EmptyChannel; +import net.citizensnpcs.nms.v1_17_R1.trait.Commands; +import net.citizensnpcs.npc.EntityControllers; +import net.citizensnpcs.npc.ai.MCNavigationStrategy.MCNavigator; +import net.citizensnpcs.npc.ai.MCTargetStrategy.TargetNavigator; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.npc.skin.SkinnableEntity; +import net.citizensnpcs.trait.versioned.BeeTrait; +import net.citizensnpcs.trait.versioned.BossBarTrait; +import net.citizensnpcs.trait.versioned.CatTrait; +import net.citizensnpcs.trait.versioned.FoxTrait; +import net.citizensnpcs.trait.versioned.LlamaTrait; +import net.citizensnpcs.trait.versioned.MushroomCowTrait; +import net.citizensnpcs.trait.versioned.PandaTrait; +import net.citizensnpcs.trait.versioned.ParrotTrait; +import net.citizensnpcs.trait.versioned.PhantomTrait; +import net.citizensnpcs.trait.versioned.PolarBearTrait; +import net.citizensnpcs.trait.versioned.PufferFishTrait; +import net.citizensnpcs.trait.versioned.ShulkerTrait; +import net.citizensnpcs.trait.versioned.SnowmanTrait; +import net.citizensnpcs.trait.versioned.TropicalFishTrait; +import net.citizensnpcs.trait.versioned.VillagerTrait; +import net.citizensnpcs.util.Messages; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.NMSBridge; +import net.citizensnpcs.util.PlayerAnimation; +import net.citizensnpcs.util.Util; +import net.minecraft.CrashReport; +import net.minecraft.CrashReportCategory; +import net.minecraft.ReportedException; +import net.minecraft.core.BlockPos; +import net.minecraft.core.DefaultedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.network.Connection; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; +import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; +import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.PlayerAdvancements; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap.TrackedEntity; +import net.minecraft.server.level.ServerBossEvent; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Entity.RemovalReason; +import net.minecraft.world.entity.EntityDimensions; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MoverType; +import net.minecraft.world.entity.Pose; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.ai.Brain; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.JumpControl; +import net.minecraft.world.entity.ai.goal.GoalSelector; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.entity.animal.AbstractFish; +import net.minecraft.world.entity.animal.AbstractSchoolingFish; +import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.animal.Panda; +import net.minecraft.world.entity.animal.PolarBear; +import net.minecraft.world.entity.animal.Pufferfish; +import net.minecraft.world.entity.animal.Rabbit; +import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.animal.horse.TraderLlama; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Shulker; +import net.minecraft.world.entity.projectile.FishingHook; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; +import net.minecraft.world.scores.PlayerTeam; + +@SuppressWarnings("unchecked") +public class NMSImpl implements NMSBridge { + public NMSImpl() { + loadEntityTypes(); + } + + @SuppressWarnings("resource") + @Override + public boolean addEntityToWorld(org.bukkit.entity.Entity entity, SpawnReason custom) { + int viewDistance = -1; + ChunkMap chunkMap = null; + try { + if (entity instanceof Player) { + chunkMap = ((ServerChunkCache) getHandle(entity).level.getChunkSource()).chunkMap; + viewDistance = (int) PLAYER_CHUNK_MAP_VIEW_DISTANCE_GETTER.invoke(chunkMap); + PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER.invoke(chunkMap, -1); + } + } catch (Throwable e) { + e.printStackTrace(); + } + boolean success = getHandle(entity).level.addEntity(getHandle(entity), custom); + try { + if (chunkMap != null) { + PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER.invoke(chunkMap, viewDistance); + } + } catch (Throwable e) { + e.printStackTrace(); + } + return success; + } + + @Override + public void addOrRemoveFromPlayerList(org.bukkit.entity.Entity entity, boolean remove) { + if (entity == null) + return; + ServerPlayer handle = (ServerPlayer) getHandle(entity); + if (handle.level == null) + return; + if (remove) { + handle.level.players().remove(handle); + } else if (!handle.level.players().contains(handle)) { + ((List) handle.level.players()).add(handle); + } + // PlayerUpdateTask.addOrRemove(entity, remove); + } + + @Override + public void attack(org.bukkit.entity.LivingEntity attacker, org.bukkit.entity.LivingEntity btarget) { + LivingEntity handle = getHandle(attacker); + LivingEntity target = getHandle(btarget); + if (handle instanceof ServerPlayer) { + ((ServerPlayer) handle).attack(target); + PlayerAnimation.ARM_SWING.play((Player) handle.getBukkitEntity()); + return; + } + if (handle instanceof Mob) { + ((Mob) handle).doHurtTarget(target); + return; + } + AttributeInstance attackDamage = handle.getAttribute(Attributes.ATTACK_DAMAGE); + float f = (float) (attackDamage == null ? 1 : attackDamage.getValue()); + int i = 0; + + if (target instanceof LivingEntity) { + f += EnchantmentHelper.getDamageBonus(handle.getMainHandItem(), target.getMobType()); + i += EnchantmentHelper.getKnockbackBonus(handle); + } + + boolean flag = target.hurt(DamageSource.mobAttack(handle), f); + + if (!flag) + return; + + if (i > 0) { + target.knockback(-Math.sin(handle.getYRot() * Math.PI / 180.0F) * i * 0.5F, 0.1D, + Math.cos(handle.getYRot() * Math.PI / 180.0F) * i * 0.5F); + handle.setDeltaMovement(handle.getDeltaMovement().multiply(0.6, 1, 0.6)); + } + + int fireAspectLevel = EnchantmentHelper.getFireAspect(handle); + if (fireAspectLevel > 0) { + target.setOnFire(fireAspectLevel * 4, false); + } + + if (target instanceof ServerPlayer) { + ServerPlayer entityhuman = (ServerPlayer) target; + ItemStack itemstack = handle.getMainHandItem(); + ItemStack itemstack1 = entityhuman.isUsingItem() ? entityhuman.getUseItem() : ItemStack.EMPTY; + if (!itemstack.isEmpty() && !itemstack1.isEmpty() + && itemstack.getItem() instanceof net.minecraft.world.item.AxeItem && itemstack1.is(Items.SHIELD)) { + float f2 = 0.25F + EnchantmentHelper.getBlockEfficiency(handle) * 0.05F; + if (new Random().nextFloat() < f2) { + entityhuman.getCooldowns().addCooldown(Items.SHIELD, 100); + handle.level.broadcastEntityEvent(entityhuman, (byte) 30); + } + } + } + + EnchantmentHelper.doPostHurtEffects(handle, target); + EnchantmentHelper.doPostDamageEffects(target, handle); + } + + @Override + public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) throws Throwable { + if (Bukkit.isPrimaryThread()) + throw new IllegalStateException("NMS.fillProfileProperties cannot be invoked from the main thread."); + + MinecraftSessionService sessionService = ((CraftServer) Bukkit.getServer()).getServer().getSessionService(); + if (!(sessionService instanceof YggdrasilMinecraftSessionService)) { + return sessionService.fillProfileProperties(profile, requireSecure); + } + YggdrasilAuthenticationService auth = ((YggdrasilMinecraftSessionService) sessionService) + .getAuthenticationService(); + + URL url = HttpAuthenticationService + .constantURL(getAuthServerBaseUrl() + UUIDTypeAdapter.fromUUID(profile.getId())); + + url = HttpAuthenticationService.concatenateURL(url, "unsigned=" + !requireSecure); + + MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) MAKE_REQUEST.invoke(auth, + url, null, MinecraftProfilePropertiesResponse.class); + if (response == null) + return profile; + + GameProfile result = new GameProfile(response.getId(), response.getName()); + result.getProperties().putAll(response.getProperties()); + profile.getProperties().putAll(response.getProperties()); + + return result; + } + + public String getAuthServerBaseUrl() { + return Setting.AUTH_SERVER_URL.asString(); + } + + @Override + public BlockBreaker getBlockBreaker(org.bukkit.entity.Entity entity, org.bukkit.block.Block targetBlock, + BlockBreakerConfiguration config) { + return new CitizensBlockBreaker(entity, targetBlock, config); + } + + @Override + public BossBar getBossBar(org.bukkit.entity.Entity entity) { + ServerBossEvent bserver = null; + try { + if (entity.getType() == EntityType.WITHER) { + bserver = ((WitherBoss) NMSImpl.getHandle(entity)).bossEvent; + } else if (entity.getType() == EntityType.ENDER_DRAGON) { + bserver = ((EnderDragon) NMSImpl.getHandle(entity)).getDragonFight().dragonEvent; + } + } catch (Throwable e) { + e.printStackTrace(); + } + if (bserver == null) { + return null; + } + BossBar ret = Bukkit.createBossBar("", BarColor.BLUE, BarStyle.SEGMENTED_10); + try { + CRAFT_BOSSBAR_HANDLE_FIELD.invoke(ret, bserver); + } catch (Throwable e) { + e.printStackTrace(); + } + return ret; + } + + @Override + public BoundingBox getBoundingBox(org.bukkit.entity.Entity handle) { + return NMSBoundingBox.wrap(NMSImpl.getHandle(handle).getBoundingBox()); + } + + @Override + public BoundingBox getCollisionBox(org.bukkit.block.Block block) { + ServerLevel world = ((CraftWorld) block.getWorld()).getHandle(); + VoxelShape shape = ((CraftBlock) block).getNMS().getCollisionShape(world, ((CraftBlock) block).getPosition()); + AABB aabb = shape.isEmpty() + ? ((CraftBlock) block).getNMS().getShape(world, ((CraftBlock) block).getPosition()).bounds() + : shape.bounds(); + return aabb == null ? BoundingBox.convert(block.getBoundingBox()) : NMSBoundingBox.wrap(aabb); + } + + private float getDragonYaw(Entity handle, double tX, double tZ) { + if (handle.getZ() > tZ) + return (float) (-Math.toDegrees(Math.atan((handle.getX() - tX) / (handle.getZ() - tZ)))); + if (handle.getZ() < tZ) { + return (float) (-Math.toDegrees(Math.atan((handle.getX() - tX) / (handle.getZ() - tZ)))) + 180.0F; + } + return handle.getYRot(); + } + + @Override + public GameProfileRepository getGameProfileRepository() { + return ((CraftServer) Bukkit.getServer()).getServer().getProfileRepository(); + } + + @Override + public float getHeadYaw(org.bukkit.entity.Entity entity) { + if (!(entity instanceof org.bukkit.entity.LivingEntity)) { + return entity.getLocation().getYaw(); + } + return getHandle((org.bukkit.entity.LivingEntity) entity).getYHeadRot(); + } + + @Override + public double getHeight(org.bukkit.entity.Entity entity) { + return entity.getHeight(); + } + + @Override + public float getHorizontalMovement(org.bukkit.entity.Entity entity) { + if (!entity.getType().isAlive()) + return Float.NaN; + LivingEntity handle = NMSImpl.getHandle((org.bukkit.entity.LivingEntity) entity); + return handle.zza; + } + + @Override + public NPC getNPC(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + return handle instanceof NPCHolder ? ((NPCHolder) handle).getNPC() : null; + } + + @Override + public List getPassengers(org.bukkit.entity.Entity entity) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null || handle.passengers == null) + return Lists.newArrayList(); + return Lists.transform(handle.passengers, new Function() { + @Override + public org.bukkit.entity.Entity apply(Entity input) { + return input.getBukkitEntity(); + } + }); + } + + @Override + public GameProfile getProfile(SkullMeta meta) { + if (SKULL_PROFILE_FIELD == null) { + SKULL_PROFILE_FIELD = NMS.getField(meta.getClass(), "profile", false); + if (SKULL_PROFILE_FIELD == null) { + return null; + } + } + try { + return (GameProfile) SKULL_PROFILE_FIELD.get(meta); + } catch (Exception e) { + return null; + } + } + + @Override + public String getSound(String flag) throws CommandException { + try { + Sound sound = Sound.valueOf(flag.toUpperCase()); + if (CRAFTSOUND_GETSOUND != null) { + String ret = (String) CRAFTSOUND_GETSOUND.invoke(sound); + if (ret == null) + throw new CommandException(Messages.INVALID_SOUND); + return ret; + } else { + SoundEvent effect = CraftSound.getSoundEffect(sound); + if (effect == null) + throw new CommandException(Messages.INVALID_SOUND); + ResourceLocation key = (ResourceLocation) SOUNDEFFECT_LOCATION.invoke(effect); + return key.getPath(); + } + } catch (Throwable e) { + throw new CommandException(Messages.INVALID_SOUND); + } + } + + @Override + public float getSpeedFor(NPC npc) { + if (!npc.isSpawned() || !(npc.getEntity() instanceof org.bukkit.entity.LivingEntity)) + return DEFAULT_SPEED; + LivingEntity handle = NMSImpl.getHandle((org.bukkit.entity.LivingEntity) npc.getEntity()); + if (handle == null) + return DEFAULT_SPEED; + return DEFAULT_SPEED; + // return (float) + // handle.getAttribute(Attributes.d).getValue(); + } + + @Override + public float getStepHeight(org.bukkit.entity.Entity entity) { + return NMSImpl.getHandle(entity).maxUpStep; + } + + @Override + public MCNavigator getTargetNavigator(org.bukkit.entity.Entity entity, Iterable dest, + final NavigatorParameters params) { + List list = Lists. newArrayList(Iterables. transform(dest, (input) -> { + return new Node(input.getBlockX(), input.getBlockY(), input.getBlockZ()); + })); + Node last = list.size() > 0 ? list.get(list.size() - 1) : null; + final Path path = new Path(list, last != null ? new BlockPos(last.x, last.y, last.z) : null, true); + return getTargetNavigator(entity, params, new Function() { + @Override + public Boolean apply(PathNavigation input) { + return input.moveTo(path, params.speed()); + } + }); + } + + @Override + public MCNavigator getTargetNavigator(final org.bukkit.entity.Entity entity, final Location dest, + final NavigatorParameters params) { + return getTargetNavigator(entity, params, new Function() { + @Override + public Boolean apply(PathNavigation input) { + return input.moveTo(dest.getX(), dest.getY(), dest.getZ(), params.speed()); + } + }); + } + + private MCNavigator getTargetNavigator(final org.bukkit.entity.Entity entity, final NavigatorParameters params, + final Function function) { + net.minecraft.world.entity.Entity raw = getHandle(entity); + raw.setOnGround(true); + // not sure of a better way around this - if onGround is false, then + // navigation won't execute, and calling entity.move doesn't + // entirely fix the problem. + final PathNavigation navigation = NMSImpl.getNavigation(entity); + final float oldWater = raw instanceof ServerPlayer + ? ((EntityHumanNPC) raw).getPathfindingMalus(BlockPathTypes.WATER) + : ((Mob) raw).getPathfindingMalus(BlockPathTypes.WATER); + if (params.avoidWater() && oldWater >= 0) { + if (raw instanceof ServerPlayer) { + ((EntityHumanNPC) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater + 1F); + } else { + ((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater + 1F); + } + } + return new MCNavigator() { + float lastSpeed; + CancelReason reason; + + @Override + public CancelReason getCancelReason() { + return reason; + } + + @Override + public Iterable getPath() { + return new NavigationIterable(navigation); + } + + @Override + public void stop() { + if (params.debug() && navigation.getPath() != null) { + for (Player player : Bukkit.getOnlinePlayers()) { + for (int i = 0; i < navigation.getPath().getNodeCount(); i++) { + Node pp = navigation.getPath().getNode(i); + org.bukkit.block.Block block = new Vector(pp.x, pp.y, pp.z).toLocation(player.getWorld()) + .getBlock(); + player.sendBlockChange(block.getLocation(), block.getBlockData()); + } + } + } + if (oldWater >= 0) { + if (raw instanceof ServerPlayer) { + ((EntityHumanNPC) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater); + } else { + ((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater); + } + } + stopNavigation(navigation); + } + + @Override + public boolean update() { + if (params.speed() != lastSpeed) { + if (Messaging.isDebugging() && lastSpeed > 0) { + Messaging.debug( + "Repathfinding " + ((NPCHolder) entity).getNPC().getId() + " due to speed change from", + lastSpeed, "to", params.speed()); + } + Entity handle = getHandle(entity); + EntityDimensions size = null; + try { + size = (EntityDimensions) SIZE_FIELD_GETTER.invoke(handle); + + if (handle instanceof AbstractHorse) { + SIZE_FIELD_SETTER.invoke(handle, + new EntityDimensions(Math.min(0.99F, size.width), size.height, false)); + } + } catch (Throwable e) { + e.printStackTrace(); + } + if (!function.apply(navigation)) { + reason = CancelReason.STUCK; + } + try { + SIZE_FIELD_SETTER.invoke(handle, size); + } catch (Throwable e) { + e.printStackTrace(); + // minecraft requires that an entity fit onto both blocks if width >= 1f, but we'd prefer to + // make it just fit on 1 so hack around it a bit. + } + lastSpeed = params.speed(); + } + if (params.debug() && !NMSImpl.isNavigationFinished(navigation)) { + BlockData data = Material.DANDELION.createBlockData(); + for (Player player : Bukkit.getOnlinePlayers()) { + for (int i = 0; i < navigation.getPath().getNodeCount(); i++) { + Node pp = navigation.getPath().getNode(i); + player.sendBlockChange(new Vector(pp.x, pp.y, pp.z).toLocation(player.getWorld()), data); + } + } + } + navigation.setSpeedModifier(params.speed()); + return NMSImpl.isNavigationFinished(navigation); + } + }; + } + + @Override + public TargetNavigator getTargetNavigator(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity target, + NavigatorParameters parameters) { + PathNavigation navigation = getNavigation(entity); + return navigation == null ? null : new NavigationFieldWrapper(navigation, target, parameters); + } + + @Override + public org.bukkit.entity.Entity getVehicle(org.bukkit.entity.Entity entity) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null) { + return null; + } + Entity e = handle.getVehicle(); + return (e == handle || e == null) ? null : e.getBukkitEntity(); + } + + @Override + public float getVerticalMovement(org.bukkit.entity.Entity entity) { + if (!entity.getType().isAlive()) + return Float.NaN; + LivingEntity handle = NMSImpl.getHandle((org.bukkit.entity.LivingEntity) entity); + return handle.xxa; + } + + @Override + public double getWidth(org.bukkit.entity.Entity entity) { + return entity.getWidth(); + } + + @Override + public float getYaw(org.bukkit.entity.Entity entity) { + return getHandle(entity).getYRot(); + } + + @Override + public boolean isOnGround(org.bukkit.entity.Entity entity) { + return NMSImpl.getHandle(entity).isOnGround(); + } + + @Override + public boolean isSolid(org.bukkit.block.Block in) { + BlockState data = ((CraftBlock) in).getNMS(); + return data.isSuffocating(((CraftWorld) in.getWorld()).getHandle(), + new BlockPos(in.getX(), in.getY(), in.getZ())); + } + + @Override + public boolean isValid(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + return handle.valid && handle.isAlive(); + } + + @Override + public void load(CommandManager manager) { + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(BeeTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(BossBarTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(CatTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(FoxTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(LlamaTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(MushroomCowTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(ParrotTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(PandaTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(PhantomTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(PolarBearTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(PufferFishTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(ShulkerTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(SnowmanTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(TropicalFishTrait.class)); + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(VillagerTrait.class)); + manager.register(Commands.class); + } + + private void loadEntityTypes() { + EntityControllers.setEntityControllerForType(EntityType.AREA_EFFECT_CLOUD, AreaEffectCloudController.class); + EntityControllers.setEntityControllerForType(EntityType.ARROW, TippedArrowController.class); + EntityControllers.setEntityControllerForType(EntityType.ARMOR_STAND, ArmorStandController.class); + EntityControllers.setEntityControllerForType(EntityType.AXOLOTL, AxolotlController.class); + EntityControllers.setEntityControllerForType(EntityType.BAT, BatController.class); + EntityControllers.setEntityControllerForType(EntityType.BEE, BeeController.class); + EntityControllers.setEntityControllerForType(EntityType.BLAZE, BlazeController.class); + EntityControllers.setEntityControllerForType(EntityType.BOAT, BoatController.class); + EntityControllers.setEntityControllerForType(EntityType.CAT, CatController.class); + EntityControllers.setEntityControllerForType(EntityType.CAVE_SPIDER, CaveSpiderController.class); + EntityControllers.setEntityControllerForType(EntityType.CHICKEN, ChickenController.class); + EntityControllers.setEntityControllerForType(EntityType.COD, CodController.class); + EntityControllers.setEntityControllerForType(EntityType.COW, CowController.class); + EntityControllers.setEntityControllerForType(EntityType.CREEPER, CreeperController.class); + EntityControllers.setEntityControllerForType(EntityType.DOLPHIN, DolphinController.class); + EntityControllers.setEntityControllerForType(EntityType.DRAGON_FIREBALL, DragonFireballController.class); + EntityControllers.setEntityControllerForType(EntityType.DROPPED_ITEM, ItemController.class); + EntityControllers.setEntityControllerForType(EntityType.DROWNED, DrownedController.class); + EntityControllers.setEntityControllerForType(EntityType.EGG, EggController.class); + EntityControllers.setEntityControllerForType(EntityType.ELDER_GUARDIAN, GuardianElderController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDER_CRYSTAL, EnderCrystalController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDER_DRAGON, EnderDragonController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDER_PEARL, EnderPearlController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDER_SIGNAL, EnderSignalController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDERMAN, EndermanController.class); + EntityControllers.setEntityControllerForType(EntityType.ENDERMITE, EndermiteController.class); + EntityControllers.setEntityControllerForType(EntityType.EVOKER, EvokerController.class); + EntityControllers.setEntityControllerForType(EntityType.EVOKER_FANGS, EvokerFangsController.class); + EntityControllers.setEntityControllerForType(EntityType.FALLING_BLOCK, FallingBlockController.class); + EntityControllers.setEntityControllerForType(EntityType.FIREWORK, FireworkController.class); + EntityControllers.setEntityControllerForType(EntityType.FIREBALL, LargeFireballController.class); + EntityControllers.setEntityControllerForType(EntityType.FISHING_HOOK, FishingHookController.class); + EntityControllers.setEntityControllerForType(EntityType.FOX, FoxController.class); + EntityControllers.setEntityControllerForType(EntityType.GHAST, GhastController.class); + EntityControllers.setEntityControllerForType(EntityType.GIANT, GiantController.class); + EntityControllers.setEntityControllerForType(EntityType.GOAT, GoatController.class); + EntityControllers.setEntityControllerForType(EntityType.GUARDIAN, GuardianController.class); + EntityControllers.setEntityControllerForType(EntityType.HORSE, HorseController.class); + EntityControllers.setEntityControllerForType(EntityType.DONKEY, HorseDonkeyController.class); + EntityControllers.setEntityControllerForType(EntityType.MULE, HorseMuleController.class); + EntityControllers.setEntityControllerForType(EntityType.SKELETON_HORSE, HorseSkeletonController.class); + EntityControllers.setEntityControllerForType(EntityType.ZOMBIE_HORSE, HorseZombieController.class); + EntityControllers.setEntityControllerForType(EntityType.HUSK, ZombieHuskController.class); + EntityControllers.setEntityControllerForType(EntityType.IRON_GOLEM, IronGolemController.class); + EntityControllers.setEntityControllerForType(EntityType.ILLUSIONER, IllusionerController.class); + EntityControllers.setEntityControllerForType(EntityType.ITEM_FRAME, ItemFrameController.class); + EntityControllers.setEntityControllerForType(EntityType.GLOW_ITEM_FRAME, GlowItemFrameController.class); + EntityControllers.setEntityControllerForType(EntityType.LEASH_HITCH, LeashController.class); + EntityControllers.setEntityControllerForType(EntityType.LLAMA, LlamaController.class); + EntityControllers.setEntityControllerForType(EntityType.TRADER_LLAMA, TraderLlamaController.class); + EntityControllers.setEntityControllerForType(EntityType.WANDERING_TRADER, WanderingTraderController.class); + EntityControllers.setEntityControllerForType(EntityType.LLAMA_SPIT, LlamaSpitController.class); + EntityControllers.setEntityControllerForType(EntityType.SPLASH_POTION, ThrownPotionController.class); + EntityControllers.setEntityControllerForType(EntityType.MARKER, MarkerController.class); + EntityControllers.setEntityControllerForType(EntityType.MAGMA_CUBE, MagmaCubeController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART, MinecartRideableController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART_CHEST, MinecartChestController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART_COMMAND, MinecartCommandController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART_FURNACE, MinecartFurnaceController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART_HOPPER, MinecartHopperController.class); + EntityControllers.setEntityControllerForType(EntityType.MINECART_TNT, MinecartTNTController.class); + EntityControllers.setEntityControllerForType(EntityType.MUSHROOM_COW, MushroomCowController.class); + EntityControllers.setEntityControllerForType(EntityType.OCELOT, OcelotController.class); + EntityControllers.setEntityControllerForType(EntityType.PANDA, PandaController.class); + EntityControllers.setEntityControllerForType(EntityType.PAINTING, PaintingController.class); + EntityControllers.setEntityControllerForType(EntityType.PARROT, ParrotController.class); + EntityControllers.setEntityControllerForType(EntityType.PHANTOM, PhantomController.class); + EntityControllers.setEntityControllerForType(EntityType.PILLAGER, PillagerController.class); + EntityControllers.setEntityControllerForType(EntityType.PIG, PigController.class); + EntityControllers.setEntityControllerForType(EntityType.PIGLIN, PiglinController.class); + EntityControllers.setEntityControllerForType(EntityType.PIGLIN_BRUTE, PiglinBruteController.class); + EntityControllers.setEntityControllerForType(EntityType.HOGLIN, HoglinController.class); + EntityControllers.setEntityControllerForType(EntityType.ZOMBIFIED_PIGLIN, PigZombieController.class); + EntityControllers.setEntityControllerForType(EntityType.ZOGLIN, ZoglinController.class); + EntityControllers.setEntityControllerForType(EntityType.POLAR_BEAR, PolarBearController.class); + EntityControllers.setEntityControllerForType(EntityType.PLAYER, HumanController.class); + EntityControllers.setEntityControllerForType(EntityType.PUFFERFISH, PufferFishController.class); + EntityControllers.setEntityControllerForType(EntityType.RABBIT, RabbitController.class); + EntityControllers.setEntityControllerForType(EntityType.RAVAGER, RavagerController.class); + EntityControllers.setEntityControllerForType(EntityType.SALMON, SalmonController.class); + EntityControllers.setEntityControllerForType(EntityType.SHEEP, SheepController.class); + EntityControllers.setEntityControllerForType(EntityType.SHULKER, ShulkerController.class); + EntityControllers.setEntityControllerForType(EntityType.SHULKER_BULLET, ShulkerBulletController.class); + EntityControllers.setEntityControllerForType(EntityType.SILVERFISH, SilverfishController.class); + EntityControllers.setEntityControllerForType(EntityType.SKELETON, SkeletonController.class); + EntityControllers.setEntityControllerForType(EntityType.STRAY, SkeletonStrayController.class); + EntityControllers.setEntityControllerForType(EntityType.STRIDER, StriderController.class); + EntityControllers.setEntityControllerForType(EntityType.SLIME, SlimeController.class); + EntityControllers.setEntityControllerForType(EntityType.SMALL_FIREBALL, SmallFireballController.class); + EntityControllers.setEntityControllerForType(EntityType.SNOWBALL, SnowballController.class); + EntityControllers.setEntityControllerForType(EntityType.SNOWMAN, SnowmanController.class); + EntityControllers.setEntityControllerForType(EntityType.SPECTRAL_ARROW, SpectralArrowController.class); + EntityControllers.setEntityControllerForType(EntityType.SPIDER, SpiderController.class); + EntityControllers.setEntityControllerForType(EntityType.SPLASH_POTION, ThrownPotionController.class); + EntityControllers.setEntityControllerForType(EntityType.SQUID, SquidController.class); + EntityControllers.setEntityControllerForType(EntityType.GLOW_SQUID, GlowSquidController.class); + EntityControllers.setEntityControllerForType(EntityType.SPECTRAL_ARROW, TippedArrowController.class); + EntityControllers.setEntityControllerForType(EntityType.THROWN_EXP_BOTTLE, ThrownExpBottleController.class); + EntityControllers.setEntityControllerForType(EntityType.TRIDENT, ThrownTridentController.class); + EntityControllers.setEntityControllerForType(EntityType.TROPICAL_FISH, TropicalFishController.class); + EntityControllers.setEntityControllerForType(EntityType.TURTLE, TurtleController.class); + EntityControllers.setEntityControllerForType(EntityType.PRIMED_TNT, TNTPrimedController.class); + EntityControllers.setEntityControllerForType(EntityType.VEX, VexController.class); + EntityControllers.setEntityControllerForType(EntityType.VILLAGER, VillagerController.class); + EntityControllers.setEntityControllerForType(EntityType.VINDICATOR, VindicatorController.class); + EntityControllers.setEntityControllerForType(EntityType.WOLF, WolfController.class); + EntityControllers.setEntityControllerForType(EntityType.WITCH, WitchController.class); + EntityControllers.setEntityControllerForType(EntityType.WITHER, WitherController.class); + EntityControllers.setEntityControllerForType(EntityType.WITHER_SKULL, WitherSkullController.class); + EntityControllers.setEntityControllerForType(EntityType.WITHER_SKELETON, SkeletonWitherController.class); + EntityControllers.setEntityControllerForType(EntityType.ZOMBIE, ZombieController.class); + EntityControllers.setEntityControllerForType(EntityType.ZOMBIE_VILLAGER, ZombieVillagerController.class); + } + + @Override + public void loadPlugins() { + ((CraftServer) Bukkit.getServer()).enablePlugins(PluginLoadOrder.POSTWORLD); + } + + @Override + public void look(org.bukkit.entity.Entity entity, float yaw, float pitch) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null) + return; + yaw = Util.clampYaw(yaw); + handle.setYRot(yaw); + setHeadYaw(entity, yaw); + handle.setXRot(pitch); + } + + @Override + public void look(org.bukkit.entity.Entity entity, Location to, boolean headOnly, boolean immediate) { + Entity handle = NMSImpl.getHandle(entity); + if (immediate || headOnly || BAD_CONTROLLER_LOOK.contains(handle.getBukkitEntity().getType()) + || (!(handle instanceof Mob) && !(handle instanceof EntityHumanNPC))) { + Location fromLocation = entity.getLocation(FROM_LOCATION); + double xDiff, yDiff, zDiff; + xDiff = to.getX() - fromLocation.getX(); + yDiff = to.getY() - fromLocation.getY(); + zDiff = to.getZ() - fromLocation.getZ(); + + double distanceXZ = Math.sqrt(xDiff * xDiff + zDiff * zDiff); + double distanceY = Math.sqrt(distanceXZ * distanceXZ + yDiff * yDiff); + + double yaw = Math.toDegrees(Math.acos(xDiff / distanceXZ)); + double pitch = Math.toDegrees(Math.acos(yDiff / distanceY)) + - (handle.getBukkitEntity().getType() == EntityType.PHANTOM ? 45 : 90); + if (zDiff < 0.0) + yaw += Math.abs(180 - yaw) * 2; + if (handle.getBukkitEntity().getType() == EntityType.ENDER_DRAGON) { + yaw = getDragonYaw(handle, to.getX(), to.getZ()); + } else { + yaw = yaw - 90; + } + if (headOnly) { + setHeadYaw(entity, (float) yaw); + } else { + look(entity, (float) yaw, (float) pitch); + } + return; + } + if (handle instanceof Mob) { + ((Mob) handle).getLookControl().setLookAt(to.getX(), to.getY(), to.getZ(), ((Mob) handle).getHeadRotSpeed(), + ((Mob) handle).getMaxHeadXRot()); + + while (((LivingEntity) handle).yHeadRot >= 180F) { + ((LivingEntity) handle).yHeadRot -= 360F; + } + while (((LivingEntity) handle).yHeadRot < -180F) { + ((LivingEntity) handle).yHeadRot += 360F; + } + } else if (handle instanceof EntityHumanNPC) { + ((EntityHumanNPC) handle).setTargetLook(to); + } + } + + @Override + public void look(org.bukkit.entity.Entity from, org.bukkit.entity.Entity to) { + Entity handle = NMSImpl.getHandle(from), target = NMSImpl.getHandle(to); + if (BAD_CONTROLLER_LOOK.contains(handle.getBukkitEntity().getType())) { + if (to instanceof org.bukkit.entity.LivingEntity) { + look(from, ((org.bukkit.entity.LivingEntity) to).getEyeLocation(), false, true); + } else { + look(from, to.getLocation(), false, true); + } + } else if (handle instanceof Mob) { + ((Mob) handle).getLookControl().setLookAt(target, ((Mob) handle).getHeadRotSpeed(), + ((Mob) handle).getMaxHeadXRot()); + while (((LivingEntity) handle).yHeadRot >= 180F) { + ((LivingEntity) handle).yHeadRot -= 360F; + } + while (((LivingEntity) handle).yHeadRot < -180F) { + ((LivingEntity) handle).yHeadRot += 360F; + } + } else if (handle instanceof EntityHumanNPC) { + ((EntityHumanNPC) handle).setTargetLook(target, 10F, 40F); + } + } + + @Override + public void mount(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity passenger) { + if (NMSImpl.getHandle(passenger) == null) + return; + NMSImpl.getHandle(passenger).startRiding(NMSImpl.getHandle(entity)); + } + + @Override + public void openHorseScreen(Tameable horse, Player equipper) { + LivingEntity handle = NMSImpl.getHandle(horse); + ServerPlayer equipperHandle = (ServerPlayer) NMSImpl.getHandle(equipper); + if (handle == null || equipperHandle == null) + return; + boolean wasTamed = horse.isTamed(); + horse.setTamed(true); + ((AbstractHorse) handle).openInventory(equipperHandle); + horse.setTamed(wasTamed); + } + + @Override + public void playAnimation(PlayerAnimation animation, Player player, int radius) { + PlayerAnimationImpl.play(animation, player, radius); + } + + @Override + public void playerTick(Player entity) { + ((ServerPlayer) getHandle(entity)).doTick(); + } + + @Override + public void registerEntityClass(Class clazz) { + if (ENTITY_REGISTRY == null) + return; + + Class search = clazz; + while ((search = search.getSuperclass()) != null && Entity.class.isAssignableFrom(search)) { + net.minecraft.world.entity.EntityType type = ENTITY_REGISTRY.findType(search); + ResourceLocation key = ENTITY_REGISTRY.getKey(type); + if (key == null || type == null) + continue; + CITIZENS_ENTITY_TYPES.put(clazz, type); + int code = ENTITY_REGISTRY.getId(type); + ENTITY_REGISTRY.put(code, key, type); + return; + } + throw new IllegalArgumentException("unable to find valid entity superclass for class " + clazz.toString()); + } + + @Override + public void remove(org.bukkit.entity.Entity entity) { + NMSImpl.getHandle(entity).remove(RemovalReason.KILLED); + } + + @Override + public void removeFromServerPlayerList(Player player) { + ServerPlayer handle = (ServerPlayer) NMSImpl.getHandle(player); + ((CraftServer) Bukkit.getServer()).getHandle().players.remove(handle); + } + + @Override + public void removeFromWorld(org.bukkit.entity.Entity entity) { + Preconditions.checkNotNull(entity); + + Entity nmsEntity = ((CraftEntity) entity).getHandle(); + ((ServerLevel) nmsEntity.level).getChunkProvider().removeEntity(nmsEntity); + } + + @Override + public void removeHookIfNecessary(NPCRegistry npcRegistry, FishHook entity) { + if (FISHING_HOOK_HOOKED == null) + return; + FishingHook hook = (FishingHook) NMSImpl.getHandle(entity); + Entity hooked = null; + try { + hooked = (Entity) FISHING_HOOK_HOOKED.invoke(hook); + } catch (Throwable e) { + e.printStackTrace(); + } + if (hooked == null) + return; + NPC npc = npcRegistry.getNPC(hooked.getBukkitEntity()); + if (npc == null) + return; + if (npc.isProtected()) { + try { + FISHING_HOOK_HOOKED_SETTER.invoke(hook, null); + } catch (Throwable e) { + e.printStackTrace(); + } + hook.setRemoved(RemovalReason.KILLED); + } + } + + @Override + public void replaceTrackerEntry(Player player) { + ServerLevel server = (ServerLevel) NMSImpl.getHandle(player).level; + + TrackedEntity entry = server.getChunkProvider().chunkMap.G.get(player.getEntityId()); + if (entry == null) + return; + PlayerlistTracker replace = new PlayerlistTracker(server.getChunkProvider().chunkMap, entry); + server.getChunkProvider().chunkMap.G.put(player.getEntityId(), replace); + if (getHandle(player) instanceof EntityHumanNPC) { + ((EntityHumanNPC) getHandle(player)).setTracked(replace); + } + } + + @Override + public void sendPositionUpdate(Player excluding, org.bukkit.entity.Entity from, Location storedLocation) { + sendPacketNearby(excluding, storedLocation, new ClientboundTeleportEntityPacket(getHandle(from))); + } + + @Override + public void sendTabListAdd(Player recipient, Player listPlayer) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(listPlayer); + + ServerPlayer entity = ((CraftPlayer) listPlayer).getHandle(); + + NMSImpl.sendPacket(recipient, + new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, entity)); + } + + @Override + public void sendTabListRemove(Player recipient, Collection skinnableNPCs) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(skinnableNPCs); + + ServerPlayer[] entities = new ServerPlayer[skinnableNPCs.size()]; + int i = 0; + for (SkinnableEntity skinnable : skinnableNPCs) { + entities[i] = (ServerPlayer) skinnable; + i++; + } + + NMSImpl.sendPacket(recipient, + new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, entities)); + } + + @Override + public void sendTabListRemove(Player recipient, Player listPlayer) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(listPlayer); + + ServerPlayer entity = ((CraftPlayer) listPlayer).getHandle(); + + NMSImpl.sendPacket(recipient, + new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, entity)); + } + + @Override + public void sendTeamPacket(Player recipient, Team team, int mode) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(team); + + if (TEAM_FIELD == null) { + TEAM_FIELD = NMS.getGetter(team.getClass(), "team"); + } + + try { + PlayerTeam nmsTeam = (PlayerTeam) TEAM_FIELD.invoke(team); + if (mode == 1) { + sendPacket(recipient, ClientboundSetPlayerTeamPacket.createRemovePacket(nmsTeam)); + } else { + sendPacket(recipient, + ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(nmsTeam, mode == 0 ? true : false)); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void setBodyYaw(org.bukkit.entity.Entity entity, float yaw) { + getHandle(entity).setYBodyRot(yaw); + } + + @Override + public void setDestination(org.bukkit.entity.Entity entity, double x, double y, double z, float speed) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null) + return; + if (handle instanceof Mob) { + ((Mob) handle).getMoveControl().setWantedPosition(x, y, z, speed); + } else if (handle instanceof EntityHumanNPC) { + ((EntityHumanNPC) handle).setMoveDestination(x, y, z, speed); + } + } + + @Override + public void setEndermanAngry(org.bukkit.entity.Enderman enderman, boolean angry) { + if (ENDERMAN_ANGRY == null) + return; + getHandle(enderman).getEntityData().set(ENDERMAN_ANGRY, angry); + } + + @Override + public void setHeadYaw(org.bukkit.entity.Entity entity, float yaw) { + if (!(entity instanceof org.bukkit.entity.LivingEntity)) + return; + LivingEntity handle = (LivingEntity) getHandle(entity); + yaw = Util.clampYaw(yaw); + handle.yBodyRot = yaw; + if (!(handle instanceof ServerPlayer)) { + handle.yHeadRot = yaw; // TODO: why this + } + handle.setYHeadRot(yaw); + } + + @Override + public void setKnockbackResistance(org.bukkit.entity.LivingEntity entity, double d) { + LivingEntity handle = NMSImpl.getHandle(entity); + handle.getAttribute(Attributes.KNOCKBACK_RESISTANCE).setBaseValue(d); + } + + @Override + public void setLyingDown(org.bukkit.entity.Entity cat, boolean lying) { + ((Cat) getHandle(cat)).setLying(lying); + } + + @Override + public void setNavigationTarget(org.bukkit.entity.Entity handle, org.bukkit.entity.Entity target, float speed) { + NMSImpl.getNavigation(handle).moveTo(NMSImpl.getHandle(target), speed); + } + + @Override + public void setNoGravity(org.bukkit.entity.Entity entity, boolean enabled) { + getHandle(entity).setNoGravity(enabled); + } + + @Override + public void setPandaSitting(org.bukkit.entity.Entity entity, boolean sitting) { + ((Panda) getHandle(entity)).sit(sitting); + } + + @Override + public void setPeekShulker(org.bukkit.entity.Entity shulker, int peek) { + ((Shulker) getHandle(shulker)).setRawPeekAmount(peek); + } + + @Override + public void setPolarBearRearing(org.bukkit.entity.Entity entity, boolean rearing) { + ((PolarBear) getHandle(entity)).setStanding(rearing); + } + + @Override + public void setProfile(SkullMeta meta, GameProfile profile) { + if (SKULL_PROFILE_FIELD == null) { + SKULL_PROFILE_FIELD = NMS.getField(meta.getClass(), "profile", false); + if (SKULL_PROFILE_FIELD == null) { + return; + } + } + try { + SKULL_PROFILE_FIELD.set(meta, profile); + } catch (Exception e) { + } + } + + @Override + public void setShouldJump(org.bukkit.entity.Entity entity) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null) + return; + if (handle instanceof Mob) { + JumpControl controller = ((Mob) handle).getJumpControl(); + controller.jump(); + } else if (handle instanceof EntityHumanNPC) { + ((EntityHumanNPC) handle).setShouldJump(); + } + } + + @Override + public void setSitting(org.bukkit.entity.Ocelot ocelot, boolean sitting) { + Pose pose = sitting ? Pose.CROUCHING : Pose.STANDING; + getHandle(ocelot).setPose(pose); + } + + @Override + public void setSitting(Tameable tameable, boolean sitting) { + ((TamableAnimal) NMSImpl.getHandle(tameable)).setInSittingPose(sitting); + } + + @Override + public void setStepHeight(org.bukkit.entity.Entity entity, float height) { + NMSImpl.getHandle(entity).maxUpStep = height; + } + + @Override + public void setTeamNameTagVisible(Team team, boolean visible) { + team.setOption(Team.Option.NAME_TAG_VISIBILITY, visible ? Team.OptionStatus.ALWAYS : Team.OptionStatus.NEVER); + } + + @Override + public void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) { + if (!bukkitEntity.getType().isAlive()) + return; + LivingEntity handle = NMSImpl.getHandle((org.bukkit.entity.LivingEntity) bukkitEntity); + handle.xxa = (float) d; + } + + @Override + public void setWitherCharged(Wither wither, boolean charged) { + WitherBoss handle = ((CraftWither) wither).getHandle(); + handle.setInvulnerableTicks(charged ? 20 : 0); + } + + @Override + public boolean shouldJump(org.bukkit.entity.Entity entity) { + if (JUMP_FIELD == null || !(entity instanceof LivingEntity)) + return false; + try { + return (boolean) JUMP_FIELD.invoke(NMSImpl.getHandle(entity)); + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + @Override + public void shutdown() { + if (ENTITY_REGISTRY == null) + return; + try { + ENTITY_REGISTRY_SETTER.invoke(null, ENTITY_REGISTRY.getWrapped()); + } catch (Throwable e) { + } + } + + @Override + public boolean tick(org.bukkit.entity.Entity next) { + Entity entity = NMSImpl.getHandle(next); + Entity entity1 = entity.getVehicle(); + if (entity1 != null) { + if ((!entity1.isAlive()) || (!entity1.hasPassenger(entity))) { + entity.stopRiding(); + } + } else { + if (entity.isAlive()) { + try { + ((ServerLevel) entity.level).tickNonPassenger(entity); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking player"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Player being ticked"); + entity.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + } + } + boolean removeFromPlayerList = ((NPCHolder) entity).getNPC().data().get("removefromplayerlist", + Setting.REMOVE_PLAYERS_FROM_PLAYER_LIST.asBoolean()); + if (!entity.isAlive()) { + ((ServerLevel) entity.level).getChunkProvider().removeEntity(entity); + return true; + } else if (!removeFromPlayerList) { + if (!entity.level.players().contains(entity)) { + List list = entity.level.players(); + list.add(entity); + } + return true; + } else { + entity.level.players().remove(entity); + } + } + return false; + } + + @Override + public void trySwim(org.bukkit.entity.Entity entity) { + trySwim(entity, 0.04F); + } + + @Override + public void trySwim(org.bukkit.entity.Entity entity, float power) { + Entity handle = NMSImpl.getHandle(entity); + if (handle == null) + return; + if (RANDOM.nextFloat() < 0.8F && handle.isInWater()) { + handle.setDeltaMovement(handle.getDeltaMovement().x, handle.getDeltaMovement().y + power, + handle.getDeltaMovement().z); + } + } + + @Override + public void updateNavigationWorld(org.bukkit.entity.Entity entity, World world) { + if (NAVIGATION_WORLD_FIELD == null) + return; + Entity en = NMSImpl.getHandle(entity); + if (en == null || !(en instanceof Mob)) + return; + Mob handle = (Mob) en; + ServerLevel worldHandle = ((CraftWorld) world).getHandle(); + try { + NAVIGATION_WORLD_FIELD.invoke(handle.getNavigation(), worldHandle); + } catch (Exception e) { + Messaging.logTr(Messages.ERROR_UPDATING_NAVIGATION_WORLD, e.getMessage()); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void updatePathfindingRange(NPC npc, float pathfindingRange) { + if (!npc.isSpawned() || !npc.getEntity().getType().isAlive()) + return; + LivingEntity en = NMSImpl.getHandle((org.bukkit.entity.LivingEntity) npc.getEntity()); + if (!(en instanceof Mob)) { + if (en instanceof EntityHumanNPC) { + ((EntityHumanNPC) en).updatePathfindingRange(pathfindingRange); + } + return; + } + if (NAVIGATION_S == null) + return; + PathNavigation navigation = ((Mob) en).getNavigation(); + AttributeInstance inst = en.getAttribute(Attributes.FOLLOW_RANGE); + inst.setBaseValue(pathfindingRange); + int mc = Mth.floor(en.getAttributeBaseValue(Attributes.FOLLOW_RANGE) * 16.0D); + try { + NAVIGATION_S.invoke(navigation, NAVIGATION_A.invoke(navigation, mc)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static class NavigationFieldWrapper implements TargetNavigator { + private final PathNavigation navigation; + private final NavigatorParameters parameters; + private final org.bukkit.entity.Entity target; + + private NavigationFieldWrapper(PathNavigation navigation, org.bukkit.entity.Entity target, + NavigatorParameters parameters) { + this.navigation = navigation; + this.target = target; + this.parameters = parameters; + } + + @Override + public Iterable getPath() { + return new NavigationIterable(navigation); + } + + @Override + public void setPath() { + Location location = parameters.entityTargetLocationMapper().apply(target); + if (location == null) { + throw new IllegalStateException("mapper should not return null"); + } + navigation.moveTo(location.getX(), location.getY(), location.getZ(), parameters.speed()); + } + + @Override + public void stop() { + stopNavigation(navigation); + } + + @Override + public void update() { + updateNavigation(navigation); + } + } + + private static class NavigationIterable implements Iterable { + private final PathNavigation navigation; + + public NavigationIterable(PathNavigation nav) { + this.navigation = nav; + } + + @Override + public Iterator iterator() { + final int npoints = navigation.getPath() == null ? 0 : navigation.getPath().getNodeCount(); + return new Iterator() { + Node curr = npoints > 0 ? navigation.getPath().getNode(0) : null; + int i = 0; + + @Override + public boolean hasNext() { + return curr != null; + } + + @Override + public Vector next() { + Node old = curr; + curr = i + 1 < npoints ? navigation.getPath().getNode(++i) : null; + return new Vector(old.x, old.y, old.z); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + } + + public static void checkAndUpdateHeight(LivingEntity living, EntityDataAccessor datawatcherobject) { + EntityDimensions size; + try { + size = (EntityDimensions) SIZE_FIELD_GETTER.invoke(living); + } catch (Throwable e) { + e.printStackTrace(); + living.onSyncedDataUpdated(datawatcherobject); + return; + } + float oldw = size.width; + float oldl = size.height; + living.onSyncedDataUpdated(datawatcherobject); + if (oldw != size.width || size.height != oldl) { + living.setPos(living.getX() - 0.01, living.getY(), living.getZ() - 0.01); + living.setPos(living.getX() + 0.01, living.getY(), living.getZ() + 0.01); + } + } + + public static void clearGoals(NPC npc, GoalSelector... goalSelectors) { + if (GOAL_SET_FIELD == null || goalSelectors == null) + return; + int i = 0; + for (GoalSelector selector : goalSelectors) { + try { + Collection list = (Collection) GOAL_SET_FIELD.invoke(selector); + if (!list.isEmpty()) { + npc.data().set("selector" + i, Lists.newArrayList(list)); + } + list.clear(); + } catch (Exception e) { + Messaging.logTr(Messages.ERROR_CLEARING_GOALS, e.getLocalizedMessage()); + } catch (Throwable e) { + Messaging.logTr(Messages.ERROR_CLEARING_GOALS, e.getLocalizedMessage()); + } + i++; + } + } + + public static void flyingMoveLogic(LivingEntity entity, Vec3 vec3d) { + if (entity.isEffectiveAi() || entity.isControlledByLocalInstance()) { + double d0 = 0.08D; + boolean flag = ((entity.getDeltaMovement()).y <= 0.0D); + if (flag && entity.hasEffect(MobEffects.SLOW_FALLING)) { + d0 = 0.01D; + entity.fallDistance = 0.0F; + } + FluidState fluid = entity.level.getFluidState(entity.blockPosition()); + if (entity.isInWater() && !entity.canStandOnFluid(fluid.getType())) { + double d1 = entity.getY(); + float f = entity.isSprinting() ? 0.9F : 0.8F; + float f1 = 0.02F; + float f2 = EnchantmentHelper.getDepthStrider(entity); + if (f2 > 3.0F) + f2 = 3.0F; + if (!entity.isOnGround()) + f2 *= 0.5F; + if (f2 > 0.0F) { + f += (0.54600006F - f) * f2 / 3.0F; + f1 += (entity.getSpeed() - f1) * f2 / 3.0F; + } + if (entity.hasEffect(MobEffects.DOLPHINS_GRACE)) + f = 0.96F; + entity.moveRelative(f1, vec3d); + entity.move(MoverType.SELF, entity.getDeltaMovement()); + Vec3 vec3d1 = entity.getDeltaMovement(); + if (entity.horizontalCollision && entity.onClimbable()) + vec3d1 = new Vec3(vec3d1.x, 0.2D, vec3d1.z); + entity.setDeltaMovement(vec3d1.multiply(f, 0.800000011920929D, f)); + Vec3 vec3d2 = entity.getFluidFallingAdjustedMovement(d0, flag, entity.getDeltaMovement()); + entity.setDeltaMovement(vec3d2); + if (entity.horizontalCollision + && entity.isFree(vec3d2.x, vec3d2.y + 0.6000000238418579D - entity.getY() + d1, vec3d2.z)) + entity.setDeltaMovement(vec3d2.x, 0.30000001192092896D, vec3d2.z); + } else if (entity.isInLava() && !entity.canStandOnFluid(fluid.getType())) { + double d1 = entity.getY(); + entity.moveRelative(0.02F, vec3d); + entity.move(MoverType.SELF, entity.getDeltaMovement()); + if (entity.getFluidHeight(FluidTags.LAVA) <= entity.getFluidJumpThreshold()) { + entity.setDeltaMovement(entity.getDeltaMovement().multiply(0.5D, 0.800000011920929D, 0.5D)); + Vec3 vec3 = entity.getFluidFallingAdjustedMovement(d0, flag, entity.getDeltaMovement()); + entity.setDeltaMovement(vec3); + } else { + entity.setDeltaMovement(entity.getDeltaMovement().scale(0.5D)); + } + if (!entity.isNoGravity()) + entity.setDeltaMovement(entity.getDeltaMovement().add(0.0D, -d0 / 4.0D, 0.0D)); + Vec3 vec3d3 = entity.getDeltaMovement(); + if (entity.horizontalCollision + && entity.isFree(vec3d3.x, vec3d3.y + 0.6000000238418579D - entity.getY() + d1, vec3d3.z)) + entity.setDeltaMovement(vec3d3.x, 0.30000001192092896D, vec3d3.z); + } else if (entity.isFallFlying()) { + Vec3 vec3d4 = entity.getDeltaMovement(); + if (vec3d4.y > -0.5D) + entity.fallDistance = 1.0F; + Vec3 vec3d5 = entity.getLookAngle(); + float f = entity.getXRot() * 0.017453292F; + double d2 = Math.sqrt(vec3d5.x * vec3d5.x + vec3d5.z * vec3d5.z); + double d3 = vec3d4.horizontalDistance(); + double d4 = vec3d5.length(); + float f3 = Mth.cos(f); + f3 = (float) (f3 * f3 * Math.min(1.0D, d4 / 0.4D)); + vec3d4 = entity.getDeltaMovement().add(0.0D, d0 * (-1.0D + f3 * 0.75D), 0.0D); + if (vec3d4.y < 0.0D && d2 > 0.0D) { + double d5 = vec3d4.y * -0.1D * f3; + vec3d4 = vec3d4.add(vec3d5.x * d5 / d2, d5, vec3d5.z * d5 / d2); + } + if (f < 0.0F && d2 > 0.0D) { + double d5 = d3 * -Mth.sin(f) * 0.04D; + vec3d4 = vec3d4.add(-vec3d5.x * d5 / d2, d5 * 3.2D, -vec3d5.z * d5 / d2); + } + if (d2 > 0.0D) + vec3d4 = vec3d4.add((vec3d5.x / d2 * d3 - vec3d4.x) * 0.1D, 0.0D, + (vec3d5.z / d2 * d3 - vec3d4.z) * 0.1D); + entity.setDeltaMovement(vec3d4.multiply(0.9900000095367432D, 0.9800000190734863D, 0.9900000095367432D)); + entity.move(MoverType.SELF, entity.getDeltaMovement()); + if (entity.horizontalCollision && !entity.level.isClientSide) { + double d5 = entity.getDeltaMovement().horizontalDistance(); + double d6 = d3 - d5; + float f4 = (float) (d6 * 10.0D - 3.0D); + if (f4 > 0.0F) { + try { + entity.playSound((SoundEvent) ENTITY_GET_SOUND_FALL.invoke(entity, (int) f4), 1.0F, 1.0F); + } catch (Throwable e) { + e.printStackTrace(); + } + entity.hurt(DamageSource.FLY_INTO_WALL, f4); + } + } + if (entity.isOnGround() && !entity.level.isClientSide && entity.getSharedFlag(7) + && !CraftEventFactory.callToggleGlideEvent(entity, false).isCancelled()) + entity.setSharedFlag(7, false); + } else { + BlockPos blockposition = new BlockPos(entity.getX(), (entity.getBoundingBox()).minY - 0.5000001D, + entity.getZ()); + float f5 = entity.level.getBlockState(blockposition).getBlock().getFriction(); + float f = entity.isOnGround() ? (f5 * 0.91F) : 0.91F; + Vec3 vec3d6 = entity.handleRelativeFrictionAndCalculateMovement(vec3d, f5); + double d7 = vec3d6.y; + if (entity.hasEffect(MobEffects.LEVITATION)) { + d7 += (0.05D * (entity.getEffect(MobEffects.LEVITATION).getAmplifier() + 1) - vec3d6.y) * 0.2D; + entity.fallDistance = 0.0F; + } else if (entity.level.isClientSide && !entity.level.hasChunkAt(blockposition)) { + if (entity.getY() > entity.level.getMinBuildHeight()) { + d7 = -0.1D; + } else { + d7 = 0.0D; + } + } else if (!entity.isNoGravity()) { + d7 -= d0; + } + if (entity.shouldDiscardFriction()) { + entity.setDeltaMovement(vec3d6.x, d7, vec3d6.z); + } else { + entity.setDeltaMovement(vec3d6.x * f, d7 * 0.9800000190734863D, vec3d6.z * f); + } + } + } + entity.calculateEntityAnimation(entity, entity instanceof net.minecraft.world.entity.animal.FlyingAnimal); + } + + public static TreeMap getBehaviorMap(LivingEntity entity) { + try { + return (TreeMap) BEHAVIOR_MAP.invoke(entity.getBrain()); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + public static net.minecraft.world.entity.EntityType getEntityType(Class clazz) { + return (net.minecraft.world.entity.EntityType) CITIZENS_ENTITY_TYPES.get(clazz); + } + + public static Entity getHandle(org.bukkit.entity.Entity entity) { + if (!(entity instanceof CraftEntity)) + return null; + return ((CraftEntity) entity).getHandle(); + } + + private static LivingEntity getHandle(org.bukkit.entity.LivingEntity entity) { + return (LivingEntity) NMSImpl.getHandle((org.bukkit.entity.Entity) entity); + } + + private static LivingEntity getHandle(Tameable entity) { + return (LivingEntity) NMSImpl.getHandle((org.bukkit.entity.Entity) entity); + } + + public static float getHeadYaw(LivingEntity handle) { + return handle.getYHeadRot(); + } + + public static PathNavigation getNavigation(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + return handle instanceof Mob ? ((Mob) handle).getNavigation() + : handle instanceof EntityHumanNPC ? ((EntityHumanNPC) handle).getNavigation() : null; + } + + public static EntityDataAccessor getRabbitTypeField() { + if (RABBIT_DATAWATCHER_FIELD == null) + return null; + try { + return (EntityDataAccessor) RABBIT_DATAWATCHER_FIELD.invoke(); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + public static EntityDimensions getSize(Entity entity) { + try { + return (EntityDimensions) SIZE_FIELD_GETTER.invoke(entity); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + public static SoundEvent getSoundEffect(NPC npc, SoundEvent snd, String meta) { + return npc == null || !npc.data().has(meta) ? snd + : Registry.SOUND_EVENT + .get(new ResourceLocation(npc.data().get(meta, snd == null ? "" : snd.toString()))); + } + + public static void initNetworkManager(Connection network) { + network.channel = new EmptyChannel(null); + SocketAddress socketAddress = new SocketAddress() { + private static final long serialVersionUID = 8207338859896320185L; + }; + network.address = socketAddress; + } + + public static boolean isNavigationFinished(PathNavigation navigation) { + return navigation.isDone(); + } + + @SuppressWarnings("deprecation") + public static void minecartItemLogic(AbstractMinecart minecart) { + NPC npc = ((NPCHolder) minecart).getNPC(); + if (npc == null) + return; + Material mat = Material.getMaterial(npc.data().get(NPC.MINECART_ITEM_METADATA, "")); + int data = npc.data().get(NPC.MINECART_ITEM_DATA_METADATA, 0); // TODO: migration for this + int offset = npc.data().get(NPC.MINECART_OFFSET_METADATA, 0); + minecart.setCustomDisplay(mat != null); + if (mat != null) { + minecart.setDisplayBlockState(Registry.BLOCK.byId(mat.getId()).defaultBlockState()); + } + minecart.setDisplayOffset(offset); + } + + public static void resetPuffTicks(Pufferfish fish) { + try { + PUFFERFISH_C.invoke(fish, 0); + PUFFERFISH_D.invoke(fish, 0); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void restoreGoals(NPC npc, GoalSelector... goalSelectors) { + if (GOAL_SET_FIELD == null || goalSelectors == null) + return; + int i = 0; + for (GoalSelector selector : goalSelectors) { + try { + Collection list = (Collection) GOAL_SET_FIELD.invoke(selector); + list.clear(); + + Collection old = npc.data().get("selector" + i); + if (old != null) { + list.addAll(old); + } + } catch (Exception e) { + Messaging.logTr(Messages.ERROR_RESTORING_GOALS, e.getLocalizedMessage()); + } catch (Throwable e) { + Messaging.logTr(Messages.ERROR_RESTORING_GOALS, e.getLocalizedMessage()); + } + i++; + } + } + + public static void sendPacket(Player player, Packet packet) { + if (packet == null) + return; + ((ServerPlayer) NMSImpl.getHandle(player)).connection.send(packet); + } + + public static void sendPacketNearby(Player from, Location location, Packet packet) { + sendPacketNearby(from, location, packet, 64); + } + + public static void sendPacketNearby(Player from, Location location, Packet packet, double radius) { + List> list = new ArrayList>(); + list.add(packet); + sendPacketsNearby(from, location, list, radius); + } + + public static void sendPacketsNearby(Player from, Location location, Collection> packets, double radius) { + radius *= radius; + final org.bukkit.World world = location.getWorld(); + for (Player ply : Bukkit.getServer().getOnlinePlayers()) { + if (ply == null || world != ply.getWorld() || (from != null && !ply.canSee(from))) { + continue; + } + if (location.distanceSquared(ply.getLocation(PACKET_CACHE_LOCATION)) > radius) { + continue; + } + for (Packet packet : packets) { + NMSImpl.sendPacket(ply, packet); + } + } + } + + public static void sendPacketsNearby(Player from, Location location, Packet... packets) { + NMSImpl.sendPacketsNearby(from, location, Arrays.asList(packets), 64); + } + + public static void setAdvancement(Player entity, PlayerAdvancements instance) { + try { + ADVANCEMENTS_PLAYER_FIELD.invoke(getHandle(entity), instance); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setBukkitEntity(Entity entity, CraftEntity bukkitEntity) { + try { + BUKKITENTITY_FIELD_SETTER.invoke(entity, bukkitEntity); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setDespawnDelay(TraderLlama llama, int ticks) { + if (TRADER_DESPAWN_DELAY == null) + return; + try { + TRADER_DESPAWN_DELAY.invoke(llama, ticks); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setLife(FishingHook entity, int life) { + try { + FISHING_HOOK_LIFE.invoke(entity, life); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setNotInSchool(AbstractFish entity) { + try { + if (ENTITY_FISH_NUM_IN_SCHOOL != null) { + ENTITY_FISH_NUM_IN_SCHOOL.invoke(entity, 2); + } + } catch (Throwable ex) { + ex.printStackTrace(); + } + } + + public static void setSize(Entity entity, boolean justCreated) { + try { + EntityDimensions entitysize = (EntityDimensions) SIZE_FIELD_GETTER.invoke(entity); + Pose entitypose = entity.getPose(); + EntityDimensions entitysize1 = entity.getDimensions(entitypose); + SIZE_FIELD_SETTER.invoke(entity, entitysize1); + HEAD_HEIGHT.invoke(entity, HEAD_HEIGHT_METHOD.invoke(entity, entitypose, entitysize1)); + if (entitysize1.width < entitysize.width && false /* TODO: PREVIOUS CITIZENS ADDITION ?reason */) { + double d0 = entitysize1.width / 2.0D; + entity.setBoundingBox(new AABB(entity.getX() - d0, entity.getY(), entity.getZ() - d0, + entity.getX() + d0, entity.getY() + entitysize1.height, entity.getZ() + d0)); + } else { + AABB axisalignedbb = entity.getBoundingBox(); + entity.setBoundingBox(new AABB(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, + axisalignedbb.minX + entitysize1.width, axisalignedbb.minY + entitysize1.height, + axisalignedbb.minZ + entitysize1.width)); + if (entitysize1.width > entitysize.width && !justCreated && !entity.level.isClientSide) { + float f = entitysize.width - entitysize1.width; + entity.move(MoverType.SELF, new Vec3(f, 0.0D, f)); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setSize(Entity entity, EntityDimensions size) { + try { + SIZE_FIELD_SETTER.invoke(entity, size); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void stopNavigation(PathNavigation navigation) { + navigation.stop(); + } + + public static void updateAI(LivingEntity entity) { + if (entity instanceof Mob) { + Mob handle = (Mob) entity; + handle.getSensing().tick(); + NMSImpl.updateNavigation(handle.getNavigation()); + handle.getMoveControl().tick(); + handle.getLookControl().tick(); + handle.getJumpControl().tick(); + } else if (entity instanceof EntityHumanNPC) { + ((EntityHumanNPC) entity).updateAI(); + } + } + + public static void updateMinecraftAIState(NPC npc, Mob entity) { + if (npc == null) + return; + if (npc.useMinecraftAI()) { + NMSImpl.restoreGoals(npc, entity.goalSelector, entity.targetSelector); + if (npc.data().has("behavior-map")) { + TreeMap behavior = npc.data().get("behavior-map"); + getBehaviorMap(entity).putAll(behavior); + npc.data().remove("behavior-map"); + } + } else { + NMSImpl.clearGoals(npc, entity.goalSelector, entity.targetSelector); + TreeMap behaviorMap = getBehaviorMap(entity); + if (behaviorMap.size() > 0) { + npc.data().set("behavior-map", new TreeMap(behaviorMap)); + behaviorMap.clear(); + } + } + } + + public static void updateNavigation(PathNavigation navigation) { + navigation.tick(); + } + + private static final MethodHandle ADVANCEMENTS_PLAYER_FIELD = NMS.getFinalSetter(ServerPlayer.class, "cr"); + private static final Set BAD_CONTROLLER_LOOK = EnumSet.of(EntityType.POLAR_BEAR, EntityType.BEE, + EntityType.SILVERFISH, EntityType.SHULKER, EntityType.ENDERMITE, EntityType.ENDER_DRAGON, EntityType.BAT, + EntityType.SLIME, EntityType.DOLPHIN, EntityType.MAGMA_CUBE, EntityType.HORSE, EntityType.GHAST, + EntityType.SHULKER, EntityType.PHANTOM); + private static final MethodHandle BEHAVIOR_MAP = NMS.getGetter(Brain.class, "f"); + private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity"); + private static final Map, net.minecraft.world.entity.EntityType> CITIZENS_ENTITY_TYPES = Maps + .newHashMap(); + private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getSetter(CraftBossBar.class, "handle"); + private static MethodHandle CRAFTSOUND_GETSOUND = NMS.getMethodHandle(CraftSound.class, "getSound", false, + Sound.class); + private static final float DEFAULT_SPEED = 1F; + private static EntityDataAccessor ENDERMAN_ANGRY = null; + private static final MethodHandle ENTITY_FISH_NUM_IN_SCHOOL = NMS.getSetter(AbstractSchoolingFish.class, "c", + false); + private static final MethodHandle ENTITY_GET_SOUND_FALL = NMS.getMethodHandle(LivingEntity.class, "getSoundFall", + true, int.class); + private static CustomEntityRegistry ENTITY_REGISTRY; + private static MethodHandle ENTITY_REGISTRY_SETTER; + private static final MethodHandle FISHING_HOOK_HOOKED = NMS.getGetter(FishingHook.class, "av"); + private static final MethodHandle FISHING_HOOK_HOOKED_SETTER = NMS.getSetter(FishingHook.class, "av"); + private static final MethodHandle FISHING_HOOK_LIFE = NMS.getSetter(FishingHook.class, "ap"); + private static final Location FROM_LOCATION = new Location(null, 0, 0, 0); + private static final MethodHandle GOAL_SET_FIELD = NMS.getGetter(GoalSelector.class, "d"); + private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "aX"); + private static final MethodHandle HEAD_HEIGHT_METHOD = NMS.getFirstMethodHandle(Entity.class, true, Pose.class, + EntityDimensions.class); + private static final MethodHandle JUMP_FIELD = NMS.getGetter(LivingEntity.class, "bn"); + private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, + "makeRequest", true, URL.class, Object.class, Class.class); + private static final MethodHandle NAVIGATION_A = NMS.getMethodHandle(PathNavigation.class, "a", true, int.class); + private static final MethodHandle NAVIGATION_S = NMS.getFinalSetter(PathNavigation.class, "t"); + private static final MethodHandle NAVIGATION_WORLD_FIELD = NMS.getSetter(PathNavigation.class, "b"); + public static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0); + private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_GETTER = NMS.getGetter(ChunkMap.class, "J"); + private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER = NMS.getSetter(ChunkMap.class, "J"); + private static final MethodHandle PUFFERFISH_C = NMS.getSetter(Pufferfish.class, "bS"); + private static final MethodHandle PUFFERFISH_D = NMS.getSetter(Pufferfish.class, "bT"); + private static final MethodHandle RABBIT_DATAWATCHER_FIELD = NMS.getGetter(Rabbit.class, "ch"); + private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle SIZE_FIELD_GETTER = NMS.getGetter(Entity.class, "aW"); + private static final MethodHandle SIZE_FIELD_SETTER = NMS.getSetter(Entity.class, "aW"); + private static Field SKULL_PROFILE_FIELD; + private static MethodHandle SOUNDEFFECT_LOCATION = NMS.getGetter(SoundEvent.class, "b"); + private static MethodHandle TEAM_FIELD; + private static final MethodHandle TRADER_DESPAWN_DELAY = NMS.getSetter(TraderLlama.class, "ci"); + public static final MethodHandle UUID_FIELD = NMS.getSetter(net.minecraft.world.entity.Entity.class, "aj"); + static { + try { + ENTITY_REGISTRY = new CustomEntityRegistry((DefaultedRegistry>) NMS + .getGetter(Registry.class, "Y").invoke()); + ENTITY_REGISTRY_SETTER = NMS.getFinalSetter(Registry.class, "Y"); + ENTITY_REGISTRY_SETTER.invoke(ENTITY_REGISTRY); + } catch (Throwable e) { + Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); + } + try { + ENDERMAN_ANGRY = (EntityDataAccessor) NMS.getField(EnderMan.class, "bU").get(null); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerAnimationImpl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerAnimationImpl.java new file mode 100644 index 000000000..2be66e2c9 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerAnimationImpl.java @@ -0,0 +1,152 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.lang.invoke.MethodHandle; +import java.util.EnumMap; + +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.scheduler.BukkitRunnable; + +import com.google.common.collect.Maps; + +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.npc.MemoryNPCDataStore; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.npc.NPCRegistry; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.ArmorStandTrait; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.PlayerAnimation; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAnimatePacket; +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Pose; + +public class PlayerAnimationImpl { + public static void play(PlayerAnimation animation, Player bplayer, int radius) { + final ServerPlayer player = (ServerPlayer) NMSImpl.getHandle(bplayer); + if (DEFAULTS.containsKey(animation)) { + playDefaultAnimation(player, radius, DEFAULTS.get(animation)); + return; + } + switch (animation) { + case SIT: + player.getBukkitEntity().setMetadata("citizens.sitting", + new FixedMetadataValue(CitizensAPI.getPlugin(), true)); + NPCRegistry registry = CitizensAPI.getNamedNPCRegistry("PlayerAnimationImpl"); + if (registry == null) { + registry = CitizensAPI.createNamedNPCRegistry("PlayerAnimationImpl", new MemoryNPCDataStore()); + } + final NPC holder = registry.createNPC(EntityType.ARMOR_STAND, ""); + holder.spawn(player.getBukkitEntity().getLocation()); + ArmorStandTrait trait = holder.getOrAddTrait(ArmorStandTrait.class); + trait.setGravity(false); + trait.setHasArms(false); + trait.setHasBaseplate(false); + trait.setSmall(true); + trait.setMarker(true); + trait.setVisible(false); + holder.data().set(NPC.NAMEPLATE_VISIBLE_METADATA, false); + holder.data().set(NPC.DEFAULT_PROTECTED_METADATA, true); + new BukkitRunnable() { + @Override + public void cancel() { + super.cancel(); + holder.destroy(); + } + + @Override + public void run() { + if (player.isRemoved() || !player.valid + || !player.getBukkitEntity().hasMetadata("citizens.sitting") + || !player.getBukkitEntity().getMetadata("citizens.sitting").get(0).asBoolean()) { + cancel(); + return; + } + if (player instanceof NPCHolder && !((NPCHolder) player).getNPC().isSpawned()) { + cancel(); + return; + } + if (!NMS.getPassengers(holder.getEntity()).contains(player.getBukkitEntity())) { + NMS.mount(holder.getEntity(), player.getBukkitEntity()); + } + } + }.runTaskTimer(CitizensAPI.getPlugin(), 0, 1); + break; + case SLEEP: + try { + ENTITY_SETPOSE_METHOD.invoke(player, Pose.SLEEPING); + } catch (Throwable e) { + e.printStackTrace(); + } + break; + case SNEAK: + player.getBukkitEntity().setSneaking(true); + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true), + player, radius); + break; + case START_ELYTRA: + player.startFallFlying(); + break; + case START_USE_MAINHAND_ITEM: + player.swing(InteractionHand.MAIN_HAND); + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true), + player, radius); + break; + case START_USE_OFFHAND_ITEM: + player.swing(InteractionHand.OFF_HAND); + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true), + player, radius); + break; + case STOP_SITTING: + player.getBukkitEntity().setMetadata("citizens.sitting", + new FixedMetadataValue(CitizensAPI.getPlugin(), false)); + NMS.mount(player.getBukkitEntity(), null); + break; + case STOP_SLEEPING: + try { + ENTITY_SETPOSE_METHOD.invoke(player, Pose.STANDING); + } catch (Throwable e) { + e.printStackTrace(); + } + break; + case STOP_SNEAKING: + player.getBukkitEntity().setSneaking(false); + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true), + player, radius); + break; + case STOP_USE_ITEM: + player.stopUsingItem(); + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData(), true), + player, radius); + break; + default: + throw new UnsupportedOperationException(); + } + } + + protected static void playDefaultAnimation(ServerPlayer player, int radius, int code) { + ClientboundAnimatePacket packet = new ClientboundAnimatePacket(player, code); + sendPacketNearby(packet, player, radius); + } + + protected static void sendPacketNearby(Packet packet, ServerPlayer player, int radius) { + NMSImpl.sendPacketNearby(player.getBukkitEntity(), player.getBukkitEntity().getLocation(), packet, radius); + } + + private static EnumMap DEFAULTS = Maps.newEnumMap(PlayerAnimation.class); + private static final MethodHandle ENTITY_SETPOSE_METHOD = NMS.getMethodHandle(Entity.class, "setPose", true, + Pose.class); + static { + DEFAULTS.put(PlayerAnimation.ARM_SWING, 0); + DEFAULTS.put(PlayerAnimation.HURT, 1); + DEFAULTS.put(PlayerAnimation.EAT_FOOD, 2); + DEFAULTS.put(PlayerAnimation.ARM_SWING_OFFHAND, 3); + DEFAULTS.put(PlayerAnimation.CRIT, 4); + DEFAULTS.put(PlayerAnimation.MAGIC_CRIT, 5); + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerBodyControl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerBodyControl.java new file mode 100644 index 000000000..5817cac83 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerBodyControl.java @@ -0,0 +1,61 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Mob; + +public class PlayerBodyControl { + private int headStableTime; + private float lastStableYHeadRot; + private final EntityHumanNPC mob; + + public PlayerBodyControl(EntityHumanNPC var0) { + this.mob = var0; + } + + public void a() { + if (isMoving()) { + this.mob.yBodyRot = this.mob.getYRot(); + rotateHeadIfNecessary(); + this.lastStableYHeadRot = this.mob.yHeadRot; + this.headStableTime = 0; + return; + } + if (e()) + if (Math.abs(this.mob.yHeadRot - this.lastStableYHeadRot) > 15.0F) { + System.out.println("BIG DX"); + this.lastStableYHeadRot = 0; + this.lastStableYHeadRot = this.mob.yHeadRot; + rotateBodyIfNecessary(); + } else { + if (++this.lastStableYHeadRot > 10) { + rotateHeadTowardsFront(); + } + } + } + + private boolean e() { + return !(this.mob.getFirstPassenger() instanceof Mob); + } + + private boolean isMoving() { + double var0 = this.mob.getX() - this.mob.xo; + double var2 = this.mob.getZ() - this.mob.zo; + return (var0 * var0 + var2 * var2 > 2.500000277905201E-7D); + } + + private void rotateBodyIfNecessary() { + this.mob.yBodyRot = Mth.rotateIfNecessary(this.mob.yBodyRot, this.mob.yHeadRot, 40); + } + + private void rotateHeadIfNecessary() { + this.mob.yHeadRot = Mth.rotateIfNecessary(this.mob.yHeadRot, this.mob.yBodyRot, 40); + } + + private void rotateHeadTowardsFront() { + int var0 = this.headStableTime - 10; + float var1 = Mth.clamp(var0 / 10.0F, 0.0F, 1.0F); + float var2 = 40 * (1.0F - var1); + this.mob.yBodyRot = Mth.rotateIfNecessary(this.mob.yBodyRot, this.mob.yHeadRot, var2); + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerControllerJump.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerControllerJump.java new file mode 100644 index 000000000..de4d1fc2b --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerControllerJump.java @@ -0,0 +1,21 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; + +public class PlayerControllerJump { + private boolean a; + private final EntityHumanNPC b; + + public PlayerControllerJump(EntityHumanNPC entityinsentient) { + this.b = entityinsentient; + } + + public void b() { + this.b.setJumping(this.a); + this.a = false; + } + + public void jump() { + this.a = true; + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerLookControl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerLookControl.java new file mode 100644 index 000000000..b4d5a0f49 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerLookControl.java @@ -0,0 +1,141 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.phys.Vec3; + +public class PlayerLookControl { + private final EntityHumanNPC a; + protected float b; + protected float c; + private final PlayerBodyControl control; + protected boolean d; + protected double e; + protected double f; + protected double g; + + public PlayerLookControl(EntityHumanNPC entityinsentient) { + this.a = entityinsentient; + this.control = new PlayerBodyControl(this.a); + } + + public void a() { + if (!NMSImpl.isNavigationFinished(this.a.getNavigation())) + return; + if (this.b()) { + // this.a.setXRot(0.0F); + } + if (this.d) { + this.d = false; + this.a.setXRot(this.a(this.a.getXRot(), this.g(), this.c)); + this.a.yHeadRot = this.a(this.a.yHeadRot, this.h(), this.b); + while (this.a.yHeadRot >= 180F) { + this.a.yHeadRot -= 360F; + } + while (this.a.yHeadRot < -180F) { + this.a.yHeadRot += 360F; + } + double d = this.a.yHeadRot - 40; + while (d >= 180F) { + d -= 360F; + } + while (d < -180F) { + d += 360F; + } + if (d > this.a.getYRot()) { + this.a.setYRot((float) d); + } + if (d != this.a.getYRot()) { + d = this.a.yHeadRot + 40; + while (d >= 180F) { + d -= 360F; + } + while (d < -180F) { + d += 360F; + } + if (d < this.a.yHeadRot) { + this.a.yHeadRot = (float) d; + } + } + // this.a.setYRot(this.a(this.a.yHeadRot, this.h(), this.b)); + } else { + // this.a.setYRot(MathHelper.b(this.a.getYRot(), this.a.yHeadRot, 40F)); + // this.a.aK = this.a(this.a.yHeadRot, this.a.aA, 10.0F); + } + if (!this.a.getNavigation().isDone()) { // TODO: use Citizens AI? + this.a.yHeadRot = Mth.rotateIfNecessary(this.a.yHeadRot, this.a.yBodyRot, 75); + } + } + + public void a(double var0, double var2, double var4) { + this.a(var0, var2, var4, 10, 40); + } + + public void a(double var0, double var2, double var4, float var6, float var7) { + double d = Math.pow(this.e - var0, 2) + Math.pow(this.f - var2, 2) + Math.pow(this.g - var4, 2); + if (d < 0.01) { + // return; + } + this.e = var0; + this.f = var2; + this.g = var4; + this.b = var6; + this.c = var7; + this.d = true; + } + + public void a(Entity var0, float var1, float var2) { + this.a(var0.getX(), b(var0), var0.getZ(), var1, var2); + } + + protected float a(float var0, float var1, float var2) { + float var3 = Mth.degreesDifference(var0, var1); + float var4 = Mth.clamp(var3, -var2, var2); + return var0 + var4; + } + + public void a(Vec3 var0) { + this.a(var0.x, var0.y, var0.z); + } + + protected boolean b() { + return true; + } + + public boolean c() { + return this.d; + } + + public double d() { + return this.e; + } + + public double e() { + return this.f; + } + + public double f() { + return this.g; + } + + protected float g() { + double var0 = this.e - this.a.getX(); + double var2 = this.f - (this.a.getY() + this.a.getEyeY()); + double var4 = this.g - this.a.getZ(); + double var6 = Mth.sqrt((float) (var0 * var0 + var4 * var4)); + return (float) (-(Mth.atan2(var2, var6) * 57.2957763671875D)); + } + + protected float h() { + double var0 = this.e - this.a.getX(); + double var2 = this.g - this.a.getZ(); + return (float) (Mth.atan2(var2, var0) * 57.2957763671875D) - 90.0F; + } + + private static double b(Entity var0) { + return var0 instanceof LivingEntity ? var0.getY() + var0.getEyeY() + : (var0.getBoundingBox().minY + var0.getBoundingBox().maxY) / 2.0D; + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerMoveControl.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerMoveControl.java new file mode 100644 index 000000000..cb84584b4 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerMoveControl.java @@ -0,0 +1,138 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.util.Random; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.citizensnpcs.util.NMS; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.monster.Slime; + +public class PlayerMoveControl extends MoveControl { + protected LivingEntity a; + protected double b; + protected double c; + protected double d; + protected double e; + protected boolean f; + private int h; + + public PlayerMoveControl(LivingEntity entityinsentient) { + super(entityinsentient instanceof Mob ? (Mob) entityinsentient + : new Slime(EntityType.SLIME, entityinsentient.level)); + this.a = entityinsentient; + this.b = entityinsentient.getX(); + this.c = entityinsentient.getY(); + this.d = entityinsentient.getZ(); + } + + protected int cg() { + return new Random().nextInt(20) + 10; + } + + @Override + public double getSpeedModifier() { + return this.e; + } + + @Override + public double getWantedX() { + return this.b; + } + + @Override + public double getWantedY() { + return this.c; + } + + @Override + public double getWantedZ() { + return this.d; + } + + @Override + public boolean hasWanted() { + return this.f; + } + + @Override + protected float rotlerp(float f, float f1, float f2) { + float f3 = Mth.wrapDegrees(f1 - f); + + if (f3 > f2) { + f3 = f2; + } + + if (f3 < -f2) { + f3 = -f2; + } + + float f4 = f + f3; + + if (f4 < 0.0F) + f4 += 360.0F; + else if (f4 > 360.0F) { + f4 -= 360.0F; + } + + return f4; + } + + @Override + public void setWantedPosition(double d0, double d1, double d2, double d3) { + this.b = d0; + this.c = d1; + this.d = d2; + this.e = d3; + this.f = true; + } + + private boolean shouldSlimeJump() { + if (!(this.a instanceof Slime)) { + return false; + } + if (this.h-- <= 0) { + return true; + } + return false; + } + + @Override + public void tick() { + this.a.zza = 0; + if (this.f) { + this.f = false; + int i = Mth.floor(this.a.getBoundingBox().minY + 0.5D); + double d0 = this.b - this.a.getX(); + double d1 = this.d - this.a.getZ(); + double d2 = this.c - i; + double d3 = d0 * d0 + d2 * d2 + d1 * d1; + if (d3 < 2.500000277905201E-007D) { + this.a.zza = 0.0F; + return; + } + float f = (float) Math.toDegrees(Math.atan2(d1, d0)) - 90.0F; + this.a.setYRot(rotlerp(this.a.getYRot(), f, 90.0F)); + NMS.setHeadYaw(a.getBukkitEntity(), this.a.getYRot()); + AttributeInstance speed = this.a.getAttribute(Attributes.MOVEMENT_SPEED); + speed.setBaseValue(0.3D * this.e); + float movement = (float) (this.e * speed.getValue()); + this.a.setSpeed(movement); + this.a.zza = movement; + if (shouldSlimeJump() || (d2 >= NMS.getStepHeight(a.getBukkitEntity()) && (d0 * d0 + d1 * d1) < 1.0D)) { + this.h = cg(); + this.h /= 3; + if (this.a instanceof EntityHumanNPC) { + ((EntityHumanNPC) this.a).getControllerJump().jump(); + } else { + ((Mob) this.a).getJumpControl().jump(); + } + } + } + } +} \ No newline at end of file diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNavigation.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNavigation.java new file mode 100644 index 000000000..a3d184afa --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNavigation.java @@ -0,0 +1,563 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.ImmutableSet; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Vec3i; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.PathNavigationRegion; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.NodeEvaluator; +import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.level.pathfinder.PathFinder; +import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; +import net.minecraft.world.phys.Vec3; + +public class PlayerNavigation extends PathNavigation { + private boolean avoidSun; + private final AttributeInstance followRange; + protected boolean hasDelayedRecomputation; + private boolean isStuck; + protected int lastStuckCheck; + protected Vec3 lastStuckCheckPos = Vec3.ZERO; + protected long lastTimeoutCheck; + protected final Level level; + protected float maxDistanceToWaypoint = 0.5F; + private float maxVisitedNodesMultiplier = 1.0F; + protected final EntityHumanNPC mob; + protected PlayerNodeEvaluator nodeEvaluator; + protected Path path; + private final PlayerPathfinder pathFinder; + private int reachRange; + protected double speedModifier; + private BlockPos targetPos; + protected int tick; + protected long timeLastRecompute; + protected Vec3i timeoutCachedNode = Vec3i.ZERO; + protected double timeoutLimit; + protected long timeoutTimer; + + public PlayerNavigation(EntityHumanNPC entityinsentient, Level world) { + super(getDummyInsentient(entityinsentient, world), world); + this.mob = entityinsentient; + this.level = world; + this.followRange = entityinsentient.getAttribute(Attributes.FOLLOW_RANGE); + this.nodeEvaluator = new PlayerNodeEvaluator(); + this.nodeEvaluator.setCanPassDoors(true); + this.pathFinder = new PlayerPathfinder(this.nodeEvaluator, 768); + this.setRange(24); + } + + @Override + public boolean canFloat() { + return this.nodeEvaluator.canFloat(); + } + + @Override + protected boolean canMoveDirectly(Vec3 var0, Vec3 var1, int var2, int var3, int var4) { + int var5 = Mth.floor(var0.x); + int var6 = Mth.floor(var0.z); + double var7 = var1.x - var0.x; + double var9 = var1.z - var0.z; + double var11 = var7 * var7 + var9 * var9; + if (var11 < 1.0E-8D) + return false; + double var13 = 1.0D / Math.sqrt(var11); + var7 *= var13; + var9 *= var13; + var2 += 2; + var4 += 2; + if (!canWalkOn(var5, Mth.floor(var0.y), var6, var2, var3, var4, var0, var7, var9)) + return false; + var2 -= 2; + var4 -= 2; + double var15 = 1.0D / Math.abs(var7); + double var17 = 1.0D / Math.abs(var9); + double var19 = var5 - var0.x; + double var21 = var6 - var0.z; + if (var7 >= 0.0D) + var19++; + if (var9 >= 0.0D) + var21++; + var19 /= var7; + var21 /= var9; + int var23 = (var7 < 0.0D) ? -1 : 1; + int var24 = (var9 < 0.0D) ? -1 : 1; + int var25 = Mth.floor(var1.x); + int var26 = Mth.floor(var1.z); + int var27 = var25 - var5; + int var28 = var26 - var6; + while (var27 * var23 > 0 || var28 * var24 > 0) { + if (var19 < var21) { + var19 += var15; + var5 += var23; + var27 = var25 - var5; + } else { + var21 += var17; + var6 += var24; + var28 = var26 - var6; + } + if (!canWalkOn(var5, Mth.floor(var0.y), var6, var2, var3, var4, var0, var7, var9)) + return false; + } + return true; + } + + public boolean canOpenDoors() { + return this.nodeEvaluator.canPassDoors(); + } + + public boolean canPassDoors() { + return this.nodeEvaluator.canPassDoors(); + } + + @Override + protected boolean canUpdatePath() { + return (this.mob.isOnGround() || isInLiquid() || this.mob.isPassenger()); + } + + private boolean canWalkAbove(int var0, int var1, int var2, int var3, int var4, int var5, Vec3 var6, double var7, + double var9) { + for (BlockPos var12 : BlockPos.betweenClosed(new BlockPos(var0, var1, var2), + new BlockPos(var0 + var3 - 1, var1 + var4 - 1, var2 + var5 - 1))) { + double var13 = var12.getX() + 0.5D - var6.x; + double var15 = var12.getZ() + 0.5D - var6.z; + if (var13 * var7 + var15 * var9 < 0.0D) + continue; + if (!this.level.getBlockState(var12).isPathfindable(this.level, var12, PathComputationType.LAND)) + return false; + } + return true; + } + + private boolean canWalkOn(int var0, int var1, int var2, int var3, int var4, int var5, Vec3 var6, double var7, + double var9) { + int var11 = var0 - var3 / 2; + int var12 = var2 - var5 / 2; + if (!canWalkAbove(var11, var1, var12, var3, var4, var5, var6, var7, var9)) + return false; + for (int var13 = var11; var13 < var11 + var3; var13++) { + for (int var14 = var12; var14 < var12 + var5; var14++) { + double var15 = var13 + 0.5D - var6.x; + double var17 = var14 + 0.5D - var6.z; + if (var15 * var7 + var17 * var9 >= 0.0D) { + BlockPathTypes var19 = this.nodeEvaluator.getBlockPathType(this.level, var13, var1 - 1, var14, + this.mob, var3, var4, var5, true, true); + if (!hasValidPathType(var19)) + return false; + var19 = this.nodeEvaluator.getBlockPathType(this.level, var13, var1, var14, this.mob, var3, var4, + var5, true, true); + float var20 = this.mob.getPathfindingMalus(var19); + if (var20 < 0.0F || var20 >= 8.0F) + return false; + if (var19 == BlockPathTypes.DAMAGE_FIRE || var19 == BlockPathTypes.DANGER_FIRE + || var19 == BlockPathTypes.DAMAGE_OTHER) + return false; + } + } + } + return true; + } + + @Override + public Path createPath(BlockPos var0, int var1) { + if (this.level.getBlockState(var0).isAir()) { + BlockPos var2 = var0.down(); + while (var2.getY() > this.level.getMinBuildHeight() && this.level.getBlockState(var2).isAir()) + var2 = var2.down(); + if (var2.getY() > this.level.getMinBuildHeight()) + return supercreatePath(var2.up(), var1); + while (var2.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(var2).isAir()) + var2 = var2.up(); + var0 = var2; + } + if (this.level.getBlockState(var0).getMaterial().isSolid()) { + BlockPos var2 = var0.up(); + while (var2.getY() < this.level.getMaxBuildHeight() + && this.level.getBlockState(var2).getMaterial().isSolid()) + var2 = var2.up(); + return supercreatePath(var2, var1); + } + return supercreatePath(var0, var1); + } + + @Override + public Path createPath(BlockPos var0, int var1, int var2) { + return createPath(ImmutableSet.of(var0), 8, false, var1, var2); + } + + @Override + public Path createPath(Entity var0, int var1) { + return createPath(var0.blockPosition(), var1); + } + + @Override + public Path createPath(Set var0, int var1) { + return createPath(var0, 8, false, var1); + } + + @Override + protected Path createPath(Set var0, int var1, boolean var2, int var3) { + return createPath(var0, var1, var2, var3, (float) this.mob.getAttributeValue(Attributes.FOLLOW_RANGE)); + } + + @Override + protected Path createPath(Set var0, int var1, boolean var2, int var3, float var4) { + if (var0.isEmpty()) + return null; + if (this.mob.getY() < this.level.getMinBuildHeight()) + return null; + if (!canUpdatePath()) + return null; + if (this.path != null && !this.path.isDone() && var0.contains(this.targetPos)) + return this.path; + this.level.getProfiler().push("pathfind"); + BlockPos var5 = var2 ? this.mob.blockPosition().up() : this.mob.blockPosition(); + int var6 = (int) (var4 + var1); + PathNavigationRegion var7 = new PathNavigationRegion(this.level, var5.c(-var6, -var6, -var6), + var5.c(var6, var6, var6)); + Path var8 = this.pathFinder.findPath(var7, this.mob, var0, var4, var3, this.maxVisitedNodesMultiplier); + this.level.getProfiler().pop(); + if (var8 != null && var8.getTarget() != null) { + this.targetPos = var8.getTarget(); + this.reachRange = var3; + resetStuckTimeout(); + } + return var8; + } + + @Override + public Path createPath(Stream var0, int var1) { + return createPath(var0.collect(Collectors. toSet()), 8, false, var1); + } + + @Override + protected PathFinder createPathFinder(int paramInt) { + return null; + } + + @Override + protected void doStuckDetection(Vec3 var0) { + if (this.tick - this.lastStuckCheck > 100) { + if (var0.distanceToSqr(this.lastStuckCheckPos) < 2.25D) { + this.isStuck = true; + stop(); + } else { + this.isStuck = false; + } + this.lastStuckCheck = this.tick; + this.lastStuckCheckPos = var0; + } + if (this.path != null && !this.path.isDone()) { + BlockPos blockPos = this.path.getNextNodePos(); + if (blockPos.equals(this.timeoutCachedNode)) { + this.timeoutTimer += System.currentTimeMillis() - this.lastTimeoutCheck; + } else { + this.timeoutCachedNode = blockPos; + double var2 = var0.distanceTo(Vec3.atBottomCenterOf(this.timeoutCachedNode)); + this.timeoutLimit = (this.mob.getSpeed() > 0.0F) ? (var2 / this.mob.getSpeed() * 1000.0D) : 0.0D; + } + if (this.timeoutLimit > 0.0D && this.timeoutTimer > this.timeoutLimit * 3.0D) + timeoutPath(); + this.lastTimeoutCheck = System.currentTimeMillis(); + } + } + + @Override + protected void followThePath() { + Vec3 var0 = getTempMobPos(); + this.maxDistanceToWaypoint = (this.mob.getBbWidth() > 0.75F) ? (this.mob.getBbWidth() / 2.0F) + : (0.75F - this.mob.getBbWidth() / 2.0F); + BlockPos blockPos = this.path.getNextNodePos(); + double var2 = Math.abs(this.mob.getX() - blockPos.getX() + 0.5D); + double var4 = Math.abs(this.mob.getY() - blockPos.getY()); + double var6 = Math.abs(this.mob.getZ() - blockPos.getZ() + 0.5D); + boolean var8 = (var2 < this.maxDistanceToWaypoint && var6 < this.maxDistanceToWaypoint && var4 < 1.0D); + if (var8 || (this.mob.canCutCorner((this.path.getNextNode()).type) && shouldTargetNextNodeInDirection(var0))) + this.path.advance(); + doStuckDetection(var0); + } + + @Override + public float getMaxDistanceToWaypoint() { + return this.maxDistanceToWaypoint; + } + + @Override + public NodeEvaluator getNodeEvaluator() { + return this.nodeEvaluator; + } + + @Override + public Path getPath() { + return this.path; + } + + private int getSurfaceY() { + if (!this.mob.isInWater() || !canFloat()) + return Mth.floor(this.mob.getY() + 0.5D); + int var0 = this.mob.getBlockY(); + BlockState var1 = this.level.getBlockState(new BlockPos(this.mob.getX(), var0, this.mob.getZ())); + int var2 = 0; + while (var1.is(Blocks.WATER)) { + var0++; + var1 = this.level.getBlockState(new BlockPos(this.mob.getX(), var0, this.mob.getZ())); + if (++var2 > 16) + return this.mob.getBlockY(); + } + return var0; + } + + @Override + public BlockPos getTargetPos() { + return this.targetPos; + } + + @Override + protected Vec3 getTempMobPos() { + return new Vec3(this.mob.getX(), getSurfaceY(), this.mob.getZ()); + } + + @Override + public boolean hasDelayedRecomputation() { + return this.hasDelayedRecomputation; + } + + protected boolean hasValidPathType(BlockPathTypes var0) { + if (var0 == BlockPathTypes.WATER) + return false; + if (var0 == BlockPathTypes.LAVA) + return false; + if (var0 == BlockPathTypes.OPEN) + return false; + return true; + } + + @Override + public boolean isDone() { + return (this.path == null || this.path.isDone()); + } + + @Override + protected boolean isInLiquid() { + return (this.mob.isInWaterOrBubble() || this.mob.isInLava()); + } + + @Override + public boolean isInProgress() { + return !isDone(); + } + + @Override + public boolean isStableDestination(BlockPos var0) { + BlockPos var1 = var0.down(); + return this.level.getBlockState(var1).isSolidRender(this.level, var1); + } + + @Override + public boolean isStuck() { + return this.isStuck; + } + + @Override + public boolean moveTo(double var0, double var2, double var4, double var6) { + return moveTo(createPath(var0, var2, var4, 1), var6); + } + + @Override + public boolean moveTo(Entity var0, double var1) { + Path var3 = createPath(var0, 1); + return (var3 != null && moveTo(var3, var1)); + } + + @Override + public boolean moveTo(Path var0, double var1) { + if (var0 == null) { + this.path = null; + return false; + } + if (!var0.sameAs(this.path)) + this.path = var0; + if (isDone()) + return false; + trimPath(); + if (this.path.getNodeCount() <= 0) + return false; + this.speedModifier = var1; + Vec3 var3 = getTempMobPos(); + this.lastStuckCheck = this.tick; + this.lastStuckCheckPos = var3; + return true; + } + + @Override + public void recomputePath() { + if (this.level.getGameTime() - this.timeLastRecompute > 20L) { + if (this.targetPos != null) { + this.path = null; + this.path = createPath(this.targetPos, this.reachRange); + this.timeLastRecompute = this.level.getGameTime(); + this.hasDelayedRecomputation = false; + } + } else { + this.hasDelayedRecomputation = true; + } + } + + @Override + public void recomputePath(BlockPos var0) { + if (this.path == null || this.path.isDone() || this.path.getNodeCount() == 0) + return; + Node var1 = this.path.getEndNode(); + Vec3 var2 = new Vec3((var1.x + this.mob.getX()) / 2.0D, (var1.y + this.mob.getY()) / 2.0D, + (var1.z + this.mob.getZ()) / 2.0D); + if (var0.closerThan(var2, (this.path.getNodeCount() - this.path.getNextNodeIndex()))) + recomputePath(); + } + + @Override + public void resetMaxVisitedNodesMultiplier() { + this.maxVisitedNodesMultiplier = 1.0F; + } + + private void resetStuckTimeout() { + this.timeoutCachedNode = Vec3i.ZERO; + this.timeoutTimer = 0L; + this.timeoutLimit = 0.0D; + this.isStuck = false; + } + + public void setAvoidSun(boolean var0) { + this.avoidSun = var0; + } + + @Override + public void setCanFloat(boolean var0) { + this.nodeEvaluator.setCanFloat(var0); + } + + public void setCanOpenDoors(boolean var0) { + this.nodeEvaluator.setCanOpenDoors(var0); + } + + public void setCanPassDoors(boolean var0) { + this.nodeEvaluator.setCanPassDoors(var0); + } + + @Override + public void setMaxVisitedNodesMultiplier(float var0) { + this.maxVisitedNodesMultiplier = var0; + } + + public void setRange(float pathfindingRange) { + this.followRange.setBaseValue(pathfindingRange); + } + + @Override + public void setSpeedModifier(double var0) { + this.speedModifier = var0; + } + + private boolean shouldTargetNextNodeInDirection(Vec3 var0) { + if (this.path.getNextNodeIndex() + 1 >= this.path.getNodeCount()) + return false; + Vec3 var1 = Vec3.atBottomCenterOf(this.path.getNextNodePos()); + if (!var0.closerThan(var1, 2.0D)) + return false; + Vec3 var2 = Vec3.atBottomCenterOf(this.path.getNodePos(this.path.getNextNodeIndex() + 1)); + Vec3 var3 = var2.subtract(var1); + Vec3 var4 = var0.subtract(var1); + return (var3.dot(var4) > 0.0D); + } + + @Override + public void stop() { + this.path = null; + } + + public Path supercreatePath(BlockPos var0, int var1) { + return createPath(ImmutableSet.of(var0), 8, false, var1); + } + + protected void supertrimPath() { + if (this.path == null) + return; + for (int var0 = 0; var0 < this.path.getNodeCount(); var0++) { + Node var1 = this.path.getNode(var0); + Node var2 = (var0 + 1 < this.path.getNodeCount()) ? this.path.getNode(var0 + 1) : null; + BlockState var3 = this.level.getBlockState(new BlockPos(var1.x, var1.y, var1.z)); + if (var3.is(BlockTags.CAULDRONS)) { + this.path.replaceNode(var0, var1.cloneAndMove(var1.x, var1.y + 1, var1.z)); + if (var2 != null && var1.y >= var2.y) + this.path.replaceNode(var0 + 1, var1.cloneAndMove(var2.x, var1.y + 1, var2.z)); + } + } + } + + @Override + public void tick() { + this.tick++; + if (this.hasDelayedRecomputation) + recomputePath(); + if (isDone()) + return; + if (canUpdatePath()) { + followThePath(); + } else if (this.path != null && !this.path.isDone()) { + Vec3 vec31 = getTempMobPos(); + Vec3 vec32 = this.path.getNextEntityPos(this.mob); + if (vec31.y > vec32.y && !this.mob.isOnGround() && Mth.floor(vec31.x) == Mth.floor(vec32.x) + && Mth.floor(vec31.z) == Mth.floor(vec32.z)) + this.path.advance(); + } + if (isDone()) + return; + Vec3 var0 = this.path.getNextEntityPos(this.mob); + BlockPos var1 = new BlockPos(var0); + this.mob.getMoveControl().setWantedPosition(var0.x, this.level.getBlockState(var1.down()).isAir() ? var0.y + : WalkNodeEvaluator.getFloorLevel(this.level, var1), var0.z, this.speedModifier); + } + + private void timeoutPath() { + resetStuckTimeout(); + stop(); + } + + @Override + protected void trimPath() { + supertrimPath(); + if (this.avoidSun) { + if (this.level.canSeeSky(new BlockPos(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()))) + return; + for (int var0 = 0; var0 < this.path.getNodeCount(); var0++) { + Node var1 = this.path.getNode(var0); + if (this.level.canSeeSky(new BlockPos(var1.x, var1.y, var1.z))) { + this.path.truncateNodes(var0); + return; + } + } + } + } + + private static Mob getDummyInsentient(EntityHumanNPC from, Level world) { + return new Mob(EntityType.VILLAGER, world) { + }; + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluator.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluator.java new file mode 100644 index 000000000..4624e5dc5 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluator.java @@ -0,0 +1,517 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.util.EnumSet; + +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.PathNavigationRegion; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.CampfireBlock; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Property; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import net.minecraft.world.level.material.Material; +import net.minecraft.world.level.pathfinder.BlockPathTypes; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.PathComputationType; +import net.minecraft.world.level.pathfinder.Target; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.minecraft.world.phys.shapes.VoxelShape; + +public class PlayerNodeEvaluator extends PlayerNodeEvaluatorBase { + private final Long2ObjectMap l = new Long2ObjectOpenHashMap(); + private final Object2BooleanMap m = new Object2BooleanOpenHashMap(); + protected float oldWaterCost; + + private boolean canReachWithoutCollision(Node var0) { + Vec3 var1 = new Vec3(var0.x - this.mob.getX(), var0.y - this.mob.getY(), var0.z - this.mob.getZ()); + AABB var2 = this.mob.getBoundingBox(); + int var3 = Mth.ceil(var1.length() / var2.getSize()); + var1 = var1.scale((1.0F / var3)); + for (int var4 = 1; var4 <= var3; var4++) { + var2 = var2.move(var1); + if (hasCollisions(var2)) + return false; + } + return true; + } + + @Override + public void done() { + this.mob.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost); + this.l.clear(); + this.m.clear(); + super.done(); + } + + protected BlockPathTypes evaluateBlockPathType(BlockGetter var0, boolean var1, boolean var2, BlockPos var3, + BlockPathTypes var4) { + if (var4 == BlockPathTypes.DOOR_WOOD_CLOSED && var1 && var2) + var4 = BlockPathTypes.WALKABLE_DOOR; + if (var4 == BlockPathTypes.DOOR_OPEN && !var2) + var4 = BlockPathTypes.BLOCKED; + if (var4 == BlockPathTypes.RAIL + && !(var0.getBlockState(var3).getBlock() instanceof net.minecraft.world.level.block.BaseRailBlock) + && !(var0.getBlockState(var3.down()) + .getBlock() instanceof net.minecraft.world.level.block.BaseRailBlock)) + var4 = BlockPathTypes.UNPASSABLE_RAIL; + if (var4 == BlockPathTypes.LEAVES) + var4 = BlockPathTypes.BLOCKED; + return var4; + } + + protected Node findAcceptedNode(int var0, int var1, int var2, int var3, double var4, Direction var6, + BlockPathTypes var7) { + Node var8 = null; + BlockPos.MutableBlockPos var9 = new BlockPos.MutableBlockPos(); + double var10 = getFloorLevel(var9.set(var0, var1, var2)); + if (var10 - var4 > 1.125D) + return null; + BlockPathTypes var12 = getCachedBlockType(this.mob, var0, var1, var2); + float var13 = this.mob.getPathfindingMalus(var12); + double var14 = this.mob.getBbWidth() / 2.0D; + if (var13 >= 0.0F) { + var8 = getNode(var0, var1, var2); + var8.type = var12; + var8.costMalus = Math.max(var8.costMalus, var13); + } + if (var7 == BlockPathTypes.FENCE && var8 != null && var8.costMalus >= 0.0F && !canReachWithoutCollision(var8)) + var8 = null; + if (var12 == BlockPathTypes.WALKABLE || (isAmphibious() && var12 == BlockPathTypes.WATER)) + return var8; + if ((var8 == null || var8.costMalus < 0.0F) && var3 > 0 && var12 != BlockPathTypes.FENCE + && var12 != BlockPathTypes.UNPASSABLE_RAIL && var12 != BlockPathTypes.TRAPDOOR + && var12 != BlockPathTypes.POWDER_SNOW) { + var8 = findAcceptedNode(var0, var1 + 1, var2, var3 - 1, var4, var6, var7); + if (var8 != null && (var8.type == BlockPathTypes.OPEN || var8.type == BlockPathTypes.WALKABLE) + && this.mob.getBbWidth() < 1.0F) { + double var16 = (var0 - var6.getStepX()) + 0.5D; + double var18 = (var2 - var6.getStepZ()) + 0.5D; + AABB var20 = new AABB(var16 - var14, + getFloorLevel(this.level, var9.set(var16, (var1 + 1), var18)) + 0.001D, var18 - var14, + var16 + var14, + this.mob.getBbHeight() + getFloorLevel(this.level, var9.set(var8.x, var8.y, var8.z)) - 0.002D, + var18 + var14); + if (hasCollisions(var20)) + var8 = null; + } + } + if (!isAmphibious() && var12 == BlockPathTypes.WATER && !canFloat()) { + if (getCachedBlockType(this.mob, var0, var1 - 1, var2) != BlockPathTypes.WATER) + return var8; + while (var1 > this.mob.level.getMinBuildHeight()) { + var1--; + var12 = getCachedBlockType(this.mob, var0, var1, var2); + if (var12 == BlockPathTypes.WATER) { + var8 = getNode(var0, var1, var2); + var8.type = var12; + var8.costMalus = Math.max(var8.costMalus, this.mob.getPathfindingMalus(var12)); + continue; + } + return var8; + } + } + if (var12 == BlockPathTypes.OPEN) { + int var16 = 0; + int var17 = var1; + while (var12 == BlockPathTypes.OPEN) { + var1--; + if (var1 < this.mob.level.getMinBuildHeight()) { + Node var18 = getNode(var0, var17, var2); + var18.type = BlockPathTypes.BLOCKED; + var18.costMalus = -1.0F; + return var18; + } + if (var16++ >= Setting.MC_NAVIGATION_MAX_FALL_DISTANCE.asInt() + || var16++ >= this.mob.getMaxFallDistance()) { + Node var18 = getNode(var0, var1, var2); + var18.type = BlockPathTypes.BLOCKED; + var18.costMalus = -1.0F; + return var18; + } + var12 = getCachedBlockType(this.mob, var0, var1, var2); + var13 = this.mob.getPathfindingMalus(var12); + if (var12 != BlockPathTypes.OPEN && var13 >= 0.0F) { + var8 = getNode(var0, var1, var2); + var8.type = var12; + var8.costMalus = Math.max(var8.costMalus, var13); + break; + } + if (var13 < 0.0F) { + Node var18 = getNode(var0, var1, var2); + var18.type = BlockPathTypes.BLOCKED; + var18.costMalus = -1.0F; + return var18; + } + } + } + if (var12 == BlockPathTypes.FENCE) { + var8 = getNode(var0, var1, var2); + var8.closed = true; + var8.type = var12; + var8.costMalus = var12.getMalus(); + } + return var8; + } + + @Override + public BlockPathTypes getBlockPathType(BlockGetter var0, int var1, int var2, int var3) { + return getBlockPathTypeStatic(var0, new BlockPos.MutableBlockPos(var1, var2, var3)); + } + + public BlockPathTypes getBlockPathType(BlockGetter var0, int var1, int var2, int var3, EntityHumanNPC var4, + int var5, int var6, int var7, boolean var8, boolean var9) { + EnumSet var10 = EnumSet.noneOf(BlockPathTypes.class); + BlockPathTypes var11 = BlockPathTypes.BLOCKED; + BlockPos var12 = var4.blockPosition(); + var11 = getBlockPathTypes(var0, var1, var2, var3, var5, var6, var7, var8, var9, var10, var11, var12); + if (var10.contains(BlockPathTypes.FENCE)) + return BlockPathTypes.FENCE; + if (var10.contains(BlockPathTypes.UNPASSABLE_RAIL)) + return BlockPathTypes.UNPASSABLE_RAIL; + BlockPathTypes var13 = BlockPathTypes.BLOCKED; + for (BlockPathTypes var15 : var10) { + if (var4.getPathfindingMalus(var15) < 0.0F) + return var15; + if (var4.getPathfindingMalus(var15) >= var4.getPathfindingMalus(var13)) + var13 = var15; + } + if (var11 == BlockPathTypes.OPEN && var4.getPathfindingMalus(var13) == 0.0F && var5 <= 1) + return BlockPathTypes.OPEN; + return var13; + } + + @Override + public BlockPathTypes getBlockPathType(BlockGetter var0, int var1, int var2, int var3, Mob var4, int var5, int var6, + int var7, boolean var8, boolean var9) { + EnumSet var10 = EnumSet.noneOf(BlockPathTypes.class); + BlockPathTypes var11 = BlockPathTypes.BLOCKED; + BlockPos var12 = var4.blockPosition(); + var11 = getBlockPathTypes(var0, var1, var2, var3, var5, var6, var7, var8, var9, var10, var11, var12); + if (var10.contains(BlockPathTypes.FENCE)) + return BlockPathTypes.FENCE; + if (var10.contains(BlockPathTypes.UNPASSABLE_RAIL)) + return BlockPathTypes.UNPASSABLE_RAIL; + BlockPathTypes var13 = BlockPathTypes.BLOCKED; + for (BlockPathTypes var15 : var10) { + if (var4.getPathfindingMalus(var15) < 0.0F) + return var15; + if (var4.getPathfindingMalus(var15) >= var4.getPathfindingMalus(var13)) + var13 = var15; + } + if (var11 == BlockPathTypes.OPEN && var4.getPathfindingMalus(var13) == 0.0F && var5 <= 1) + return BlockPathTypes.OPEN; + return var13; + } + + private BlockPathTypes getBlockPathType(EntityHumanNPC var0, BlockPos var1) { + return getCachedBlockType(var0, var1.getX(), var1.getY(), var1.getZ()); + } + + public BlockPathTypes getBlockPathTypee(BlockGetter var0, int var1, int var2, int var3, EntityHumanNPC var4, + int var5, int var6, int var7, boolean var8, boolean var9) { + EnumSet var10 = EnumSet.noneOf(BlockPathTypes.class); + BlockPathTypes var11 = BlockPathTypes.BLOCKED; + BlockPos var12 = var4.blockPosition(); + var11 = getBlockPathTypes(var0, var1, var2, var3, var5, var6, var7, var8, var9, var10, var11, var12); + if (var10.contains(BlockPathTypes.FENCE)) + return BlockPathTypes.FENCE; + if (var10.contains(BlockPathTypes.UNPASSABLE_RAIL)) + return BlockPathTypes.UNPASSABLE_RAIL; + BlockPathTypes var13 = BlockPathTypes.BLOCKED; + for (BlockPathTypes var15 : var10) { + if (var4.getPathfindingMalus(var15) < 0.0F) + return var15; + if (var4.getPathfindingMalus(var15) >= var4.getPathfindingMalus(var13)) + var13 = var15; + } + if (var11 == BlockPathTypes.OPEN && var4.getPathfindingMalus(var13) == 0.0F && var5 <= 1) + return BlockPathTypes.OPEN; + return var13; + } + + public BlockPathTypes getBlockPathTypes(BlockGetter var0, int var1, int var2, int var3, int var4, int var5, + int var6, boolean var7, boolean var8, EnumSet var9, BlockPathTypes var10, BlockPos var11) { + for (int var12 = 0; var12 < var4; var12++) { + for (int var13 = 0; var13 < var5; var13++) { + for (int var14 = 0; var14 < var6; var14++) { + int var15 = var12 + var1; + int var16 = var13 + var2; + int var17 = var14 + var3; + BlockPathTypes var18 = getBlockPathType(var0, var15, var16, var17); + var18 = evaluateBlockPathType(var0, var7, var8, var11, var18); + if (var12 == 0 && var13 == 0 && var14 == 0) + var10 = var18; + var9.add(var18); + } + } + } + return var10; + } + + protected BlockPathTypes getCachedBlockType(EntityHumanNPC var0, int var1, int var2, int var3) { + return this.l.computeIfAbsent(BlockPos.asLong(var1, var2, var3), + var4 -> getBlockPathType(this.level, var1, var2, var3, var0, this.entityWidth, this.entityHeight, + this.entityDepth, canOpenDoors(), canPassDoors())); + } + + protected BlockPathTypes getCachedBlockType(Mob var0, int var1, int var2, int var3) { + return this.l.computeIfAbsent(BlockPos.asLong(var1, var2, var3), + var4 -> getBlockPathType(this.level, var1, var2, var3, var0, this.entityWidth, this.entityHeight, + this.entityDepth, canOpenDoors(), canPassDoors())); + } + + protected double getFloorLevel(BlockPos var0) { + return getFloorLevel(this.level, var0); + } + + @Override + public Target getGoal(double var0, double var2, double var4) { + return new Target(getNode(Mth.floor(var0), Mth.floor(var2), Mth.floor(var4))); + } + + @Override + public int getNeighbors(Node[] var0, Node var1) { + int var2 = 0; + int var3 = 0; + BlockPathTypes var4 = getCachedBlockType(this.mob, var1.x, var1.y + 1, var1.z); + BlockPathTypes var5 = getCachedBlockType(this.mob, var1.x, var1.y, var1.z); + if (this.mob.getPathfindingMalus(var4) >= 0.0F && var5 != BlockPathTypes.STICKY_HONEY) + var3 = Mth.floor(Math.max(1.0F, this.mob.maxUpStep)); + double var6 = getFloorLevel(new BlockPos(var1.x, var1.y, var1.z)); + Node var8 = findAcceptedNode(var1.x, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (isNeighborValid(var8, var1)) + var0[var2++] = var8; + Node var9 = findAcceptedNode(var1.x - 1, var1.y, var1.z, var3, var6, Direction.WEST, var5); + if (isNeighborValid(var9, var1)) + var0[var2++] = var9; + Node var10 = findAcceptedNode(var1.x + 1, var1.y, var1.z, var3, var6, Direction.EAST, var5); + if (isNeighborValid(var10, var1)) + var0[var2++] = var10; + Node var11 = findAcceptedNode(var1.x, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (isNeighborValid(var11, var1)) + var0[var2++] = var11; + Node var12 = findAcceptedNode(var1.x - 1, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (isDiagonalValid(var1, var9, var11, var12)) + var0[var2++] = var12; + Node var13 = findAcceptedNode(var1.x + 1, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (isDiagonalValid(var1, var10, var11, var13)) + var0[var2++] = var13; + Node var14 = findAcceptedNode(var1.x - 1, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (isDiagonalValid(var1, var9, var8, var14)) + var0[var2++] = var14; + Node var15 = findAcceptedNode(var1.x + 1, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (isDiagonalValid(var1, var10, var8, var15)) + var0[var2++] = var15; + return var2; + } + + @Override + public Node getStart() { + BlockPos.MutableBlockPos var1 = new BlockPos.MutableBlockPos(); + int var0 = this.mob.getBlockY(); + BlockState var2 = this.level.getBlockState(var1.set(this.mob.getX(), var0, this.mob.getZ())); + if (this.mob.canStandOnFluid(var2.getFluidState().getType())) { + while (this.mob.canStandOnFluid(var2.getFluidState().getType())) { + var0++; + var2 = this.level.getBlockState(var1.set(this.mob.getX(), var0, this.mob.getZ())); + } + var0--; + } else if (canFloat() && this.mob.isInWater()) { + while (var2.is(Blocks.WATER) || var2.getFluidState() == Fluids.WATER.getSource(false)) { + var0++; + var2 = this.level.getBlockState(var1.set(this.mob.getX(), var0, this.mob.getZ())); + } + var0--; + } else if (this.mob.isOnGround()) { + var0 = Mth.floor(this.mob.getY() + 0.5D); + } else { + BlockPos blockPos = this.mob.blockPosition(); + while ((this.level.getBlockState(blockPos).isAir() || this.level.getBlockState(blockPos) + .isPathfindable(this.level, blockPos, PathComputationType.LAND)) + && blockPos.getY() > this.mob.level.getMinBuildHeight()) + blockPos = blockPos.down(); + var0 = blockPos.up().getY(); + } + BlockPos var3 = this.mob.blockPosition(); + BlockPathTypes var4 = getCachedBlockType(this.mob, var3.getX(), var0, var3.getZ()); + if (this.mob.getPathfindingMalus(var4) < 0.0F) { + AABB aABB = this.mob.getBoundingBox(); + if (hasPositiveMalus(var1.set(aABB.minX, var0, aABB.minZ)) + || hasPositiveMalus(var1.set(aABB.minX, var0, aABB.maxZ)) + || hasPositiveMalus(var1.set(aABB.maxX, var0, aABB.minZ)) + || hasPositiveMalus(var1.set(aABB.maxX, var0, aABB.maxZ))) { + Node var6 = getNode(var1); + var6.type = getBlockPathType(this.mob, var6.asBlockPos()); + var6.costMalus = this.mob.getPathfindingMalus(var6.type); + return var6; + } + } + Node var5 = getNode(var3.getX(), var0, var3.getZ()); + var5.type = getBlockPathType(this.mob, var5.asBlockPos()); + var5.costMalus = this.mob.getPathfindingMalus(var5.type); + return var5; + } + + private boolean hasCollisions(AABB var0) { + return this.m.computeIfAbsent(var0, var1 -> Boolean.valueOf(!this.level.noCollision(this.mob, var0))) + .booleanValue(); + } + + private boolean hasPositiveMalus(BlockPos var0) { + BlockPathTypes var1 = getBlockPathType(this.mob, var0); + return (this.mob.getPathfindingMalus(var1) >= 0.0F); + } + + protected boolean isAmphibious() { + return false; + } + + protected boolean isDiagonalValid(Node var0, Node var1, Node var2, Node var3) { + if (var3 == null || var2 == null || var1 == null) + return false; + if (var3.closed) + return false; + if (var2.y > var0.y || var1.y > var0.y) + return false; + if (var1.type == BlockPathTypes.WALKABLE_DOOR || var2.type == BlockPathTypes.WALKABLE_DOOR + || var3.type == BlockPathTypes.WALKABLE_DOOR) + return false; + boolean var4 = (var2.type == BlockPathTypes.FENCE && var1.type == BlockPathTypes.FENCE + && this.mob.getBbWidth() < 0.5D); + return (var3.costMalus >= 0.0F && (var2.y < var0.y || var2.costMalus >= 0.0F || var4) + && (var1.y < var0.y || var1.costMalus >= 0.0F || var4)); + } + + protected boolean isNeighborValid(Node var0, Node var1) { + return (var0 != null && !var0.closed && (var0.costMalus >= 0.0F || var1.costMalus < 0.0F)); + } + + @Override + public void prepare(PathNavigationRegion var0, Mob var1) { + super.prepare(var0, var1); + this.oldWaterCost = var1.getPathfindingMalus(BlockPathTypes.WATER); + } + + public static BlockPathTypes checkNeighbourBlocks(BlockGetter var0, BlockPos.MutableBlockPos var1, + BlockPathTypes var2) { + int var3 = var1.getX(); + int var4 = var1.getY(); + int var5 = var1.getZ(); + for (int var6 = -1; var6 <= 1; var6++) { + for (int var7 = -1; var7 <= 1; var7++) { + for (int var8 = -1; var8 <= 1; var8++) { + if (var6 != 0 || var8 != 0) { + var1.set(var3 + var6, var4 + var7, var5 + var8); + BlockState var9 = var0.getBlockState(var1); + if (var9.is(Blocks.CACTUS)) + return BlockPathTypes.DANGER_CACTUS; + if (var9.is(Blocks.SWEET_BERRY_BUSH)) + return BlockPathTypes.DANGER_OTHER; + if (isBurningBlock(var9)) + return BlockPathTypes.DANGER_FIRE; + if (var0.getFluidState(var1).is(FluidTags.WATER)) + return BlockPathTypes.WATER_BORDER; + } + } + } + } + return var2; + } + + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter var0, BlockPos var1) { + BlockState var2 = var0.getBlockState(var1); + Block var3 = var2.getBlock(); + Material var4 = var2.getMaterial(); + if (var2.isAir()) + return BlockPathTypes.OPEN; + if (var2.is(BlockTags.TRAPDOORS) || var2.is(Blocks.LILY_PAD) || var2.is(Blocks.BIG_DRIPLEAF)) + return BlockPathTypes.TRAPDOOR; + if (var2.is(Blocks.POWDER_SNOW)) + return BlockPathTypes.POWDER_SNOW; + if (var2.is(Blocks.CACTUS)) + return BlockPathTypes.DAMAGE_CACTUS; + if (var2.is(Blocks.SWEET_BERRY_BUSH)) + return BlockPathTypes.DAMAGE_OTHER; + if (var2.is(Blocks.HONEY_BLOCK)) + return BlockPathTypes.STICKY_HONEY; + if (var2.is(Blocks.COCOA)) + return BlockPathTypes.COCOA; + FluidState var5 = var0.getFluidState(var1); + if (var5.is(FluidTags.LAVA)) + return BlockPathTypes.LAVA; + if (isBurningBlock(var2)) + return BlockPathTypes.DAMAGE_FIRE; + if (DoorBlock.isWoodenDoor(var2) && !((Boolean) var2.getValue((Property) DoorBlock.OPEN)).booleanValue()) + return BlockPathTypes.DOOR_WOOD_CLOSED; + if (var3 instanceof DoorBlock && var4 == Material.METAL + && !((Boolean) var2.getValue((Property) DoorBlock.OPEN)).booleanValue()) + return BlockPathTypes.DOOR_IRON_CLOSED; + if (var3 instanceof DoorBlock && ((Boolean) var2.getValue((Property) DoorBlock.OPEN)).booleanValue()) + return BlockPathTypes.DOOR_OPEN; + if (var3 instanceof net.minecraft.world.level.block.BaseRailBlock) + return BlockPathTypes.RAIL; + if (var3 instanceof net.minecraft.world.level.block.LeavesBlock) + return BlockPathTypes.LEAVES; + if (var2.is(BlockTags.FENCES) || var2.is(BlockTags.WALLS) || (var3 instanceof FenceGateBlock + && !((Boolean) var2.getValue((Property) FenceGateBlock.OPEN)).booleanValue())) + return BlockPathTypes.FENCE; + if (!var2.isPathfindable(var0, var1, PathComputationType.LAND)) + return BlockPathTypes.BLOCKED; + if (var5.is(FluidTags.WATER)) + return BlockPathTypes.WATER; + return BlockPathTypes.OPEN; + } + + public static BlockPathTypes getBlockPathTypeStatic(BlockGetter var0, BlockPos.MutableBlockPos var1) { + int var2 = var1.getX(); + int var3 = var1.getY(); + int var4 = var1.getZ(); + BlockPathTypes var5 = getBlockPathTypeRaw(var0, var1); + if (var5 == BlockPathTypes.OPEN && var3 >= var0.getMinBuildHeight() + 1) { + BlockPathTypes var6 = getBlockPathTypeRaw(var0, var1.set(var2, var3 - 1, var4)); + var5 = (var6 == BlockPathTypes.WALKABLE || var6 == BlockPathTypes.OPEN || var6 == BlockPathTypes.WATER + || var6 == BlockPathTypes.LAVA) ? BlockPathTypes.OPEN : BlockPathTypes.WALKABLE; + if (var6 == BlockPathTypes.DAMAGE_FIRE) + var5 = BlockPathTypes.DAMAGE_FIRE; + if (var6 == BlockPathTypes.DAMAGE_CACTUS) + var5 = BlockPathTypes.DAMAGE_CACTUS; + if (var6 == BlockPathTypes.DAMAGE_OTHER) + var5 = BlockPathTypes.DAMAGE_OTHER; + if (var6 == BlockPathTypes.STICKY_HONEY) + var5 = BlockPathTypes.STICKY_HONEY; + } + if (var5 == BlockPathTypes.WALKABLE) + var5 = checkNeighbourBlocks(var0, var1.set(var2, var3, var4), var5); + return var5; + } + + public static double getFloorLevel(BlockGetter var0, BlockPos var1) { + BlockPos var2 = var1.down(); + VoxelShape var3 = var0.getBlockState(var2).getCollisionShape(var0, var2); + return var2.getY() + (var3.isEmpty() ? 0.0D : var3.max(Direction.Axis.Y)); + } + + public static boolean isBurningBlock(BlockState var0) { + return (var0.is(BlockTags.FIRE) || var0.is(Blocks.LAVA) || var0.is(Blocks.MAGMA_BLOCK) + || CampfireBlock.isLitCampfire(var0) || var0.is(Blocks.LAVA_CAULDRON)); + } + +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluatorBase.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluatorBase.java new file mode 100644 index 000000000..a3c68866c --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerNodeEvaluatorBase.java @@ -0,0 +1,88 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.level.PathNavigationRegion; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.NodeEvaluator; + +public abstract class PlayerNodeEvaluatorBase extends NodeEvaluator { + protected final Int2ObjectMap c = new Int2ObjectOpenHashMap(); + protected boolean canFloat; + protected boolean canOpenDoors; + protected boolean canPassDoors; + protected int entityDepth; + protected int entityHeight; + protected int entityWidth; + protected PathNavigationRegion level; + protected EntityHumanNPC mob; + + @Override + public boolean canFloat() { + return this.canFloat; + } + + @Override + public boolean canOpenDoors() { + return this.canOpenDoors; + } + + @Override + public boolean canPassDoors() { + return this.canPassDoors; + } + + @Override + public void done() { + this.level = null; + this.mob = null; + } + + @Override + protected Node getNode(BlockPos var0) { + return getNode(var0.getX(), var0.getY(), var0.getZ()); + } + + @Override + protected Node getNode(int var0, int var1, int var2) { + return this.c.computeIfAbsent(Node.createHash(var0, var1, var2), var3 -> new Node(var0, var1, var2)); + } + + public void prepare(PathNavigationRegion var0, EntityHumanNPC var1) { + this.level = var0; + this.mob = var1; + this.c.clear(); + this.entityWidth = Mth.floor(var1.getBbWidth() + 1.0F); + this.entityHeight = Mth.floor(var1.getBbHeight() + 1.0F); + this.entityDepth = Mth.floor(var1.getBbWidth() + 1.0F); + } + + @Override + public void prepare(PathNavigationRegion var0, Mob var1) { + this.level = var0; + this.c.clear(); + this.entityWidth = Mth.floor(var1.getBbWidth() + 1.0F); + this.entityHeight = Mth.floor(var1.getBbHeight() + 1.0F); + this.entityDepth = Mth.floor(var1.getBbWidth() + 1.0F); + } + + @Override + public void setCanFloat(boolean var0) { + this.canFloat = var0; + } + + @Override + public void setCanOpenDoors(boolean var0) { + this.canOpenDoors = var0; + } + + @Override + public void setCanPassDoors(boolean var0) { + this.canPassDoors = var0; + } +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerPathfinder.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerPathfinder.java new file mode 100644 index 000000000..35852f743 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerPathfinder.java @@ -0,0 +1,152 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.minecraft.core.BlockPos; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.util.profiling.metrics.MetricCategory; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.level.PathNavigationRegion; +import net.minecraft.world.level.pathfinder.BinaryHeap; +import net.minecraft.world.level.pathfinder.Node; +import net.minecraft.world.level.pathfinder.Path; +import net.minecraft.world.level.pathfinder.PathFinder; +import net.minecraft.world.level.pathfinder.Target; + +public class PlayerPathfinder extends PathFinder { + private final int maxVisitedNodes; + private final Node[] neighbors = new Node[32]; + private final PlayerNodeEvaluator nodeEvaluator; + private final BinaryHeap openSet = new BinaryHeap(); + + public PlayerPathfinder(PlayerNodeEvaluator var0, int var1) { + super(var0, var1); + this.nodeEvaluator = var0; + this.maxVisitedNodes = var1; + } + + public Path findPath(PathNavigationRegion var0, EntityHumanNPC var1, Set var2, float var3, int var4, + float var5) { + this.openSet.clear(); + this.nodeEvaluator.prepare(var0, var1); + Node var6 = this.nodeEvaluator.getStart(); + Map var7 = var2.stream().collect( + Collectors.toMap(p -> this.nodeEvaluator.getGoal(p.getX(), p.getY(), p.getZ()), Function.identity())); + Path var8 = findPath(var0.getProfiler(), var6, var7, var3, var4, var5); + this.nodeEvaluator.done(); + return var8; + } + + @Override + public Path findPath(PathNavigationRegion var0, Mob var1, Set var2, float var3, int var4, float var5) { + this.openSet.clear(); + this.nodeEvaluator.prepare(var0, var1); + Node var6 = this.nodeEvaluator.getStart(); + Map var7 = var2.stream().collect( + Collectors.toMap(p -> this.nodeEvaluator.getGoal(p.getX(), p.getY(), p.getZ()), Function.identity())); + Path var8 = findPath(var0.getProfiler(), var6, var7, var3, var4, var5); + this.nodeEvaluator.done(); + return var8; + } + + private Path findPath(ProfilerFiller var0, Node var1, Map var2, float var3, int var4, + float var5) { + var0.push("find_path"); + var0.markForCharting(MetricCategory.PATH_FINDING); + Set var6 = var2.keySet(); + var1.g = 0.0F; + var1.h = getBestH(var1, var6); + var1.f = var1.h; + this.openSet.clear(); + this.openSet.insert(var1); + ImmutableSet immutableSet = ImmutableSet.of(); + int var8 = 0; + Set var9 = Sets.newHashSetWithExpectedSize(var6.size()); + int var10 = (int) (this.maxVisitedNodes * var5); + while (!this.openSet.isEmpty() && ++var8 < var10) { + Node node = this.openSet.pop(); + node.closed = true; + for (Target target : var6) { + if (node.distanceManhattan(target) <= var4) { + target.setReached(); + var9.add(target); + } + } + if (!var9.isEmpty()) + break; + if (node.distanceTo(var1) >= var3) + continue; + int i = this.nodeEvaluator.getNeighbors(this.neighbors, node); + for (int var13 = 0; var13 < i; var13++) { + Node var14 = this.neighbors[var13]; + float var15 = node.distanceTo(var14); + node.walkedDistance += var15; + float var16 = node.g + var15 + var14.costMalus; + if (var14.walkedDistance < var3 && (!var14.inOpenSet() || var16 < var14.g)) { + var14.cameFrom = node; + var14.g = var16; + var14.h = getBestH(var14, var6) * 1.5F; + if (var14.inOpenSet()) { + this.openSet.changeCost(var14, var14.g + var14.h); + } else { + var14.f = var14.g + var14.h; + this.openSet.insert(var14); + } + } + } + } + Optional var11 = !var9.isEmpty() + ? var9.stream().map(p -> reconstructPath(p.getBestNode(), var2.get(p), true)).min( + Comparator.comparingInt(Path::getNodeCount)) + : getFallbackDestinations(var2, var6).findFirst(); + var0.pop(); + if (!var11.isPresent()) + return null; + Path var12 = var11.get(); + return var12; + } + + private float getBestH(Node var0, Set var1) { + float var2 = Float.MAX_VALUE; + for (Target var4 : var1) { + float var5 = var0.distanceTo(var4); + var4.updateBest(var5, var0); + var2 = Math.min(var5, var2); + } + return var2; + } + + public Stream getFallbackDestinations(Map var1, Set var5) { + if (Setting.DISABLE_MC_NAVIGATION_FALLBACK.asBoolean()) { + return Stream.empty(); + } + return var5.stream().map((var1x) -> { + return this.reconstructPath(var1x.getBestNode(), var1.get(var1x), false); + }).sorted(Comparator.comparingDouble(Path::getDistToTarget).thenComparingInt(Path::getNodeCount)); + } + + private Path reconstructPath(Node var0, BlockPos var1, boolean var2) { + List var3 = Lists.newArrayList(); + Node var4 = var0; + var3.add(0, var4); + while (var4.cameFrom != null) { + var4 = var4.cameFrom; + var3.add(0, var4); + } + return new Path(var3, var1, var2); + } + +} diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java new file mode 100644 index 000000000..db61ec308 --- /dev/null +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java @@ -0,0 +1,100 @@ +package net.citizensnpcs.nms.v1_17_R1.util; + +import java.lang.invoke.MethodHandle; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.nms.v1_17_R1.entity.EntityHumanNPC; +import net.citizensnpcs.util.NMS; +import net.minecraft.network.protocol.game.ClientboundAnimatePacket; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkMap.TrackedEntity; +import net.minecraft.server.level.ServerEntity; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; + +public class PlayerlistTracker extends ChunkMap.TrackedEntity { + private ServerPlayer lastUpdatedPlayer; + private final Entity tracker; + + public PlayerlistTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) { + map.super(entity, i, j, flag); + this.tracker = entity; + } + + public PlayerlistTracker(ChunkMap map, TrackedEntity entry) { + this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry)); + } + + public void updateLastPlayer() { + if (tracker.isRemoved()) + return; + final ServerPlayer entityplayer = lastUpdatedPlayer; + if (entityplayer == null) + return; + NMS.sendTabListAdd(entityplayer.getBukkitEntity(), (Player) tracker.getBukkitEntity()); + if (!Setting.DISABLE_TABLIST.asBoolean()) + return; + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { + @Override + public void run() { + NMSImpl.sendPacket(entityplayer.getBukkitEntity(), new ClientboundAnimatePacket(tracker, 0)); + NMS.sendTabListRemove(entityplayer.getBukkitEntity(), (Player) tracker.getBukkitEntity()); + } + }, Setting.TABLIST_REMOVE_PACKET_DELAY.asInt()); + } + + @Override + public void updatePlayer(final ServerPlayer entityplayer) { + if (entityplayer instanceof EntityHumanNPC) // prevent updates to NPC "viewers" + return; + this.lastUpdatedPlayer = entityplayer; + super.updatePlayer(entityplayer); + + } + + private static int getE(TrackedEntity entry) { + try { + return (int) E.invoke(TRACKER_ENTRY.invoke(entry)); + } catch (Throwable e) { + e.printStackTrace(); + } + return 0; + } + + private static boolean getF(TrackedEntity entry) { + try { + return (boolean) F.invoke(TRACKER_ENTRY.invoke(entry)); + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + private static Entity getTracker(TrackedEntity entry) { + try { + return (Entity) TRACKER.invoke(entry); + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + private static int getTrackingDistance(TrackedEntity entry) { + try { + return (Integer) TRACKING_DISTANCE.invoke(entry); + } catch (Throwable e) { + e.printStackTrace(); + } + return 0; + } + + private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); + private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); + private static final MethodHandle TRACKER = NMS.getGetter(TrackedEntity.class, "c"); + private static final MethodHandle TRACKER_ENTRY = NMS.getGetter(TrackedEntity.class, "b"); + private static final MethodHandle TRACKING_DISTANCE = NMS.getGetter(TrackedEntity.class, "d"); +} diff --git a/v1_8_R3/pom.xml b/v1_8_R3/pom.xml index e69b82c6a..57b6f2aa4 100644 --- a/v1_8_R3/pom.xml +++ b/v1_8_R3/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.27-SNAPSHOT + 2.0.28-SNAPSHOT citizens-v1_8_R3