From 9facad1b2a781f5abfad6126fef53c57be57a672 Mon Sep 17 00:00:00 2001 From: fullwall Date: Thu, 8 Jun 2023 22:37:50 +0800 Subject: [PATCH] Initial 1.20 update --- dist/pom.xml | 9 +- main/pom.xml | 6 +- .../main/java/net/citizensnpcs/Citizens.java | 24 +- .../main/java/net/citizensnpcs/Settings.java | 2 +- .../citizensnpcs/commands/NPCCommands.java | 26 + .../net/citizensnpcs/npc/CitizensNPC.java | 1 + .../net/citizensnpcs/trait/FollowTrait.java | 2 +- .../net/citizensnpcs/trait/HologramTrait.java | 13 + .../java/net/citizensnpcs/util/Messages.java | 2 + .../main/java/net/citizensnpcs/util/Util.java | 26 +- .../src/main/resources/messages_en.properties | 4 +- 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_16_R3/pom.xml | 2 +- v1_17_R1/pom.xml | 2 +- .../nms/v1_17_R1/entity/EntityHumanNPC.java | 1 - .../nms/v1_17_R1/util/PlayerlistTracker.java | 8 +- v1_18_R2/pom.xml | 2 +- .../nms/v1_18_R2/util/PlayerlistTracker.java | 8 +- v1_19_R3/pom.xml | 2 +- .../v1_19_R3/util/CitizensEntityTracker.java | 7 +- v1_20_R1/pom.xml | 112 + .../nms/v1_20_R1/entity/AllayController.java | 242 ++ .../v1_20_R1/entity/ArmorStandController.java | 150 + .../v1_20_R1/entity/AxolotlController.java | 256 ++ .../nms/v1_20_R1/entity/BatController.java | 185 ++ .../nms/v1_20_R1/entity/BeeController.java | 180 ++ .../nms/v1_20_R1/entity/BlazeController.java | 175 ++ .../nms/v1_20_R1/entity/CamelController.java | 239 ++ .../nms/v1_20_R1/entity/CatController.java | 222 ++ .../v1_20_R1/entity/CaveSpiderController.java | 221 ++ .../v1_20_R1/entity/ChickenController.java | 230 ++ .../nms/v1_20_R1/entity/CodController.java | 261 ++ .../nms/v1_20_R1/entity/CowController.java | 238 ++ .../v1_20_R1/entity/CreeperController.java | 241 ++ .../v1_20_R1/entity/DolphinController.java | 240 ++ .../v1_20_R1/entity/DrownedController.java | 211 ++ .../entity/EnderDragonController.java | 274 ++ .../v1_20_R1/entity/EndermanController.java | 232 ++ .../v1_20_R1/entity/EndermiteController.java | 220 ++ .../nms/v1_20_R1/entity/EntityHumanNPC.java | 494 ++++ .../nms/v1_20_R1/entity/EvokerController.java | 212 ++ .../nms/v1_20_R1/entity/FoxController.java | 222 ++ .../nms/v1_20_R1/entity/FrogController.java | 225 ++ .../nms/v1_20_R1/entity/GhastController.java | 181 ++ .../nms/v1_20_R1/entity/GiantController.java | 220 ++ .../v1_20_R1/entity/GlowSquidController.java | 220 ++ .../nms/v1_20_R1/entity/GoatController.java | 222 ++ .../v1_20_R1/entity/GuardianController.java | 227 ++ .../entity/GuardianElderController.java | 227 ++ .../nms/v1_20_R1/entity/HoglinController.java | 215 ++ .../nms/v1_20_R1/entity/HorseController.java | 268 ++ .../entity/HorseDonkeyController.java | 268 ++ .../v1_20_R1/entity/HorseMuleController.java | 268 ++ .../entity/HorseSkeletonController.java | 268 ++ .../entity/HorseZombieController.java | 268 ++ .../nms/v1_20_R1/entity/HumanController.java | 70 + .../v1_20_R1/entity/IllusionerController.java | 212 ++ .../v1_20_R1/entity/IronGolemController.java | 220 ++ .../nms/v1_20_R1/entity/LlamaController.java | 239 ++ .../v1_20_R1/entity/MagmaCubeController.java | 243 ++ .../v1_20_R1/entity/MobEntityController.java | 82 + .../entity/MushroomCowController.java | 231 ++ .../nms/v1_20_R1/entity/OcelotController.java | 228 ++ .../nms/v1_20_R1/entity/PandaController.java | 222 ++ .../nms/v1_20_R1/entity/ParrotController.java | 190 ++ .../v1_20_R1/entity/PhantomController.java | 257 ++ .../nms/v1_20_R1/entity/PigController.java | 236 ++ .../v1_20_R1/entity/PigZombieController.java | 211 ++ .../entity/PiglinBruteController.java | 214 ++ .../nms/v1_20_R1/entity/PiglinController.java | 214 ++ .../v1_20_R1/entity/PillagerController.java | 222 ++ .../v1_20_R1/entity/PolarBearController.java | 186 ++ .../v1_20_R1/entity/PufferFishController.java | 293 ++ .../nms/v1_20_R1/entity/RabbitController.java | 242 ++ .../v1_20_R1/entity/RavagerController.java | 227 ++ .../nms/v1_20_R1/entity/SalmonController.java | 258 ++ .../nms/v1_20_R1/entity/SheepController.java | 221 ++ .../v1_20_R1/entity/ShulkerController.java | 237 ++ .../v1_20_R1/entity/SilverfishController.java | 221 ++ .../v1_20_R1/entity/SkeletonController.java | 220 ++ .../entity/SkeletonStrayController.java | 220 ++ .../entity/SkeletonWitherController.java | 220 ++ .../nms/v1_20_R1/entity/SlimeController.java | 244 ++ .../v1_20_R1/entity/SnifferController.java | 236 ++ .../v1_20_R1/entity/SnowmanController.java | 220 ++ .../nms/v1_20_R1/entity/SpiderController.java | 220 ++ .../nms/v1_20_R1/entity/SquidController.java | 220 ++ .../v1_20_R1/entity/StriderController.java | 211 ++ .../v1_20_R1/entity/TadpoleController.java | 258 ++ .../entity/TraderLlamaController.java | 240 ++ .../entity/TropicalFishController.java | 260 ++ .../nms/v1_20_R1/entity/TurtleController.java | 246 ++ .../nms/v1_20_R1/entity/VexController.java | 179 ++ .../v1_20_R1/entity/VillagerController.java | 263 ++ .../v1_20_R1/entity/VindicatorController.java | 222 ++ .../entity/WanderingTraderController.java | 269 ++ .../nms/v1_20_R1/entity/WardenController.java | 217 ++ .../nms/v1_20_R1/entity/WitchController.java | 220 ++ .../nms/v1_20_R1/entity/WitherController.java | 190 ++ .../nms/v1_20_R1/entity/WolfController.java | 234 ++ .../nms/v1_20_R1/entity/ZoglinController.java | 213 ++ .../nms/v1_20_R1/entity/ZombieController.java | 211 ++ .../v1_20_R1/entity/ZombieHuskController.java | 211 ++ .../entity/ZombieVillagerController.java | 212 ++ .../nonliving/AreaEffectCloudController.java | 124 + .../nonliving/BlockDisplayController.java | 123 + .../entity/nonliving/BoatController.java | 258 ++ .../entity/nonliving/ChestBoatController.java | 259 ++ .../nonliving/DragonFireballController.java | 136 + .../entity/nonliving/EggController.java | 141 + .../nonliving/EnderCrystalController.java | 124 + .../nonliving/EnderPearlController.java | 128 + .../nonliving/EnderSignalController.java | 125 + .../nonliving/EvokerFangsController.java | 139 + .../nonliving/ExperienceOrbController.java | 124 + .../nonliving/FallingBlockController.java | 166 ++ .../entity/nonliving/FireworkController.java | 125 + .../nonliving/FishingHookController.java | 159 + .../nonliving/GlowItemFrameController.java | 150 + .../nonliving/InteractionController.java | 124 + .../entity/nonliving/ItemController.java | 152 + .../nonliving/ItemDisplayController.java | 136 + .../entity/nonliving/ItemFrameController.java | 149 + .../nonliving/LargeFireballController.java | 136 + .../entity/nonliving/LeashController.java | 130 + .../entity/nonliving/LlamaSpitController.java | 144 + .../entity/nonliving/MarkerController.java | 124 + .../nonliving/MinecartChestController.java | 125 + .../nonliving/MinecartCommandController.java | 125 + .../nonliving/MinecartFurnaceController.java | 125 + .../nonliving/MinecartHopperController.java | 106 + .../nonliving/MinecartRideableController.java | 124 + .../nonliving/MinecartSpawnerController.java | 106 + .../nonliving/MinecartTNTController.java | 106 + .../entity/nonliving/PaintingController.java | 129 + .../nonliving/ShulkerBulletController.java | 124 + .../nonliving/SmallFireballController.java | 127 + .../entity/nonliving/SnowballController.java | 124 + .../nonliving/SpectralArrowController.java | 125 + .../entity/nonliving/TNTPrimedController.java | 125 + .../nonliving/TextDisplayController.java | 123 + .../nonliving/ThrownExpBottleController.java | 128 + .../nonliving/ThrownPotionController.java | 143 + .../nonliving/ThrownTridentController.java | 125 + .../nonliving/TippedArrowController.java | 124 + .../nonliving/WitherSkullController.java | 124 + .../nms/v1_20_R1/network/EmptyNetHandler.java | 17 + .../v1_20_R1/network/EmptyNetworkManager.java | 25 + .../v1_20_R1/util/CitizensBlockBreaker.java | 99 + .../v1_20_R1/util/CitizensEntityTracker.java | 151 + .../v1_20_R1/util/CustomEntityRegistry.java | 477 +++ .../util/EmptyAdvancementDataPlayer.java | 77 + .../util/EmptyServerStatsCounter.java | 42 + .../nms/v1_20_R1/util/EntityJumpControl.java | 27 + .../nms/v1_20_R1/util/EntityMoveControl.java | 126 + .../nms/v1_20_R1/util/EntityNavigation.java | 538 ++++ .../v1_20_R1/util/EntityNodeEvaluator.java | 624 ++++ .../util/EntityNodeEvaluatorBase.java | 108 + .../nms/v1_20_R1/util/EntityPathfinder.java | 146 + .../v1_20_R1/util/ForwardingNPCHolder.java | 22 + .../citizensnpcs/nms/v1_20_R1/util/MobAI.java | 176 ++ .../nms/v1_20_R1/util/NMSBoundingBox.java | 26 + .../nms/v1_20_R1/util/NMSImpl.java | 2625 +++++++++++++++++ .../v1_20_R1/util/PitchableLookControl.java | 27 + .../v1_20_R1/util/PlayerAnimationImpl.java | 89 + v1_8_R3/pom.xml | 2 +- 172 files changed, 30208 insertions(+), 60 deletions(-) create mode 100644 v1_20_R1/pom.xml create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AllayController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ArmorStandController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AxolotlController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BeeController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BlazeController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CamelController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CatController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CaveSpiderController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ChickenController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CodController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CowController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CreeperController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DolphinController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DrownedController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EnderDragonController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermanController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermiteController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EntityHumanNPC.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EvokerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FoxController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FrogController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GhastController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GiantController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GlowSquidController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GoatController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianElderController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HoglinController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseDonkeyController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseMuleController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseZombieController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HumanController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IllusionerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IronGolemController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/LlamaController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MagmaCubeController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MobEntityController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MushroomCowController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/OcelotController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PandaController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ParrotController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PhantomController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigZombieController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinBruteController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PillagerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PolarBearController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PufferFishController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RabbitController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RavagerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SalmonController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SheepController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ShulkerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SilverfishController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonStrayController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonWitherController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SlimeController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnifferController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnowmanController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SpiderController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SquidController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/StriderController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TadpoleController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TraderLlamaController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TropicalFishController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TurtleController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VexController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VillagerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VindicatorController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WanderingTraderController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WardenController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitchController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitherController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WolfController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZoglinController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieHuskController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieVillagerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/AreaEffectCloudController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BlockDisplayController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BoatController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ChestBoatController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/DragonFireballController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EggController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderCrystalController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderPearlController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderSignalController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EvokerFangsController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ExperienceOrbController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FallingBlockController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FireworkController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FishingHookController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/GlowItemFrameController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/InteractionController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemDisplayController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemFrameController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LargeFireballController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LeashController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LlamaSpitController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MarkerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartChestController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartCommandController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartFurnaceController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartHopperController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartRideableController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartSpawnerController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartTNTController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/PaintingController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ShulkerBulletController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SmallFireballController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SnowballController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SpectralArrowController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TNTPrimedController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TextDisplayController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownExpBottleController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownPotionController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownTridentController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TippedArrowController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/WitherSkullController.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetHandler.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetworkManager.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensBlockBreaker.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CustomEntityRegistry.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyAdvancementDataPlayer.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyServerStatsCounter.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityJumpControl.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityMoveControl.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNavigation.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluator.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluatorBase.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityPathfinder.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/ForwardingNPCHolder.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/MobAI.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSBoundingBox.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PitchableLookControl.java create mode 100644 v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PlayerAnimationImpl.java diff --git a/dist/pom.xml b/dist/pom.xml index 7e3e0d3f1..11ecd4fd2 100644 --- a/dist/pom.xml +++ b/dist/pom.xml @@ -5,7 +5,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens pom @@ -92,5 +92,12 @@ jar compile + + ${project.groupId} + citizens-v1_20_R1 + ${project.version} + jar + compile + \ No newline at end of file diff --git a/main/pom.xml b/main/pom.xml index d03c0f563..44d2dfc82 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -4,7 +4,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-main @@ -131,13 +131,13 @@ net.kyori adventure-text-minimessage - 4.11.0 + 4.14.0 provided net.kyori adventure-platform-bukkit - 4.1.2 + 4.3.0 provided diff --git a/main/src/main/java/net/citizensnpcs/Citizens.java b/main/src/main/java/net/citizensnpcs/Citizens.java index 7170e9653..ae787b6b6 100644 --- a/main/src/main/java/net/citizensnpcs/Citizens.java +++ b/main/src/main/java/net/citizensnpcs/Citizens.java @@ -305,28 +305,28 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { lib.loadLibrary(Library.builder().groupId("net{}sf{}trove4j").artifactId("trove4j").version("3.0.3") .relocate("gnu{}trove", "clib{}trove").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-minimessage") - .version("4.12.0").relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-bukkit").version("4.2.0") + .version("4.14.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-bukkit").version("4.3.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-api").version("4.2.0") + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-api").version("4.3.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-facet").version("4.2.0") + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-facet").version("4.3.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-platform-viaversion") - .version("4.2.0").relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-api").version("4.12.0") + .version("4.3.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-api").version("4.14.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-bungeecord") - .version("4.2.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + .version("4.3.0").relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-legacy") - .version("4.12.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + .version("4.13.0").relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-gson") - .version("4.12.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + .version("4.13.0").relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-text-serializer-gson-legacy-impl") - .version("4.12.0").relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-nbt").version("4.12.0") + .version("4.13.0").relocate("net{}kyori", "clib{}net{}kyori").build()); + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-nbt").version("4.13.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); - lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-key").version("4.12.0") + lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("adventure-key").version("4.14.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); lib.loadLibrary(Library.builder().groupId("net{}kyori").artifactId("examination-api").version("1.3.0") .relocate("net{}kyori", "clib{}net{}kyori").build()); diff --git a/main/src/main/java/net/citizensnpcs/Settings.java b/main/src/main/java/net/citizensnpcs/Settings.java index e5e7a3b01..c2266acd0 100644 --- a/main/src/main/java/net/citizensnpcs/Settings.java +++ b/main/src/main/java/net/citizensnpcs/Settings.java @@ -141,7 +141,7 @@ public class Settings { "npc.pathfinding.straight-line-targeting-distance", 5), DEFAULT_STUCK_ACTION( "The default action to perform when NPCs are unable to find a path or are stuck in the same block for too long. Supported options are: 'teleport to destination' or 'none'", - "npc.pathfinding.default-stuck-action", "teleport to destination"), + "npc.pathfinding.default-stuck-action", "none"), DEFAULT_TALK_CLOSE("npc.default.talk-close.enabled", false), DEFAULT_TALK_CLOSE_RANGE("Default talk close range in blocks", "npc.default.talk-close.range", 5), DEFAULT_TEXT("npc.default.talk-close.text.0", "Hi, I'm !") { diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index 01861832f..4a1683f94 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -133,6 +133,7 @@ import net.citizensnpcs.trait.ScriptTrait; import net.citizensnpcs.trait.SheepTrait; import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.trait.ShopTrait.NPCShop; +import net.citizensnpcs.trait.SitTrait; import net.citizensnpcs.trait.SkinLayers; import net.citizensnpcs.trait.SkinLayers.Layer; import net.citizensnpcs.trait.SkinTrait; @@ -2647,6 +2648,31 @@ public class NPCCommands { } } + @Command( + aliases = { "npc" }, + usage = "sitting (--explicit [true|false]) (--at [at])", + desc = "Sets the NPC sitting", + modifiers = { "sitting" }, + min = 1, + max = 2, + permission = "citizens.npc.sitting") + @Requirements(selected = true, ownership = true) + public void sitting(CommandContext args, CommandSender sender, NPC npc, @Flag("explicit") Boolean explicit, + @Flag("at") Location at) { + SitTrait trait = npc.getOrAddTrait(SitTrait.class); + boolean toSit = explicit != null ? explicit : !trait.isSitting(); + if (!toSit) { + trait.setSitting(null); + Messaging.sendTr(sender, Messages.SITTING_UNSET, npc.getName()); + return; + } + if (at == null) { + at = npc.getStoredLocation(); + } + trait.setSitting(at); + Messaging.sendTr(sender, Messages.SITTING_SET, npc.getName(), at); + } + @Command( aliases = { "npc" }, usage = "skin (-c(lear) -l(atest)) [name] (or --url [url] --file [file] (-s(lim)) or -t [uuid/name] [data] [signature])", diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index 7afce364d..99b798651 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -301,6 +301,7 @@ public class CitizensNPC extends AbstractNPC { getOrAddTrait(CurrentLocation.class).setLocation(at); entityController.create(at.clone(), this); getEntity().setMetadata("NPC", new FixedMetadataValue(CitizensAPI.getPlugin(), true)); + getEntity().setMetadata("NPC-ID", new FixedMetadataValue(CitizensAPI.getPlugin(), getId())); if (getEntity() instanceof SkinnableEntity && !hasTrait(SkinLayers.class)) { ((SkinnableEntity) getEntity()).setSkinFlags(EnumSet.allOf(SkinLayers.Layer.class)); diff --git a/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java b/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java index 987188912..07275636b 100644 --- a/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/FollowTrait.java @@ -97,7 +97,6 @@ public class FollowTrait extends Trait { if (entity == null) return; } - if (!isActive()) return; @@ -107,6 +106,7 @@ public class FollowTrait extends Trait { } return; } + if (!npc.getNavigator().isNavigating()) { npc.getNavigator().setTarget(entity, false); } else { diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index 6d9201197..eea97c430 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -44,6 +44,8 @@ public class HologramTrait extends Trait { private BiFunction customHologramSupplier; @Persist private HologramDirection direction = HologramDirection.BOTTOM_UP; + @Persist(reify = true) + private HologramFilter filter; private double lastEntityHeight = 0; private boolean lastNameplateVisible; @Persist @@ -417,6 +419,17 @@ public class HologramTrait extends Trait { TOP_DOWN; } + public static class HologramFilter { + private HologramFilter() { + } + + public static class Builder { + public HologramFilter build() { + return new HologramFilter(); + } + } + } + private class HologramLine implements Function { NPC hologram; double mb, mt; diff --git a/main/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java index f8b49bd90..a4caced69 100644 --- a/main/src/main/java/net/citizensnpcs/util/Messages.java +++ b/main/src/main/java/net/citizensnpcs/util/Messages.java @@ -361,6 +361,8 @@ public class Messages { public static final String SHEEP_COLOR_SET = "citizens.commands.npc.sheep.color-set"; public static final String SHULKER_COLOR_SET = "citizens.commands.npc.shulker.color-set"; public static final String SHULKER_PEEK_SET = "citizens.commands.npc.shulker.peek-set"; + public static final String SITTING_SET = "citizens.commands.npc.sitting.set"; + public static final String SITTING_UNSET = "citizens.commands.npc.sitting.unset"; public static final String SIZE_DESCRIPTION = "citizens.commands.npc.size.description"; public static final String SIZE_SET = "citizens.commands.npc.size.set"; public static final String SKELETON_TYPE_SET = "citizens.commands.npc.skeletontype.set"; diff --git a/main/src/main/java/net/citizensnpcs/util/Util.java b/main/src/main/java/net/citizensnpcs/util/Util.java index 9eb0a4c7a..ddd14f47a 100644 --- a/main/src/main/java/net/citizensnpcs/util/Util.java +++ b/main/src/main/java/net/citizensnpcs/util/Util.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Random; import java.util.Set; import java.util.UUID; -import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -60,20 +60,26 @@ public class Util { } } - public static void callPossiblyAsyncEvent(Event event, boolean sync) { + public static boolean callEventPossiblySync(Event event, boolean sync) { + if (!sync) { + try { + Bukkit.getPluginManager().callEvent(event); + return false; + } catch (IllegalStateException ex) { + // sync method called + } + } try { - Callable callable = () -> { + Bukkit.getScheduler().callSyncMethod(CitizensAPI.getPlugin(), () -> { Bukkit.getPluginManager().callEvent(event); return null; - }; - if (sync) { - Bukkit.getScheduler().callSyncMethod(CitizensAPI.getPlugin(), callable).get(); - } else { - callable.call(); - } - } catch (Exception e) { + }).get(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { e.printStackTrace(); } + return true; } public static Vector callPushEvent(NPC npc, double x, double y, double z) { diff --git a/main/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties index 926bec78f..c1a3844b8 100644 --- a/main/src/main/resources/messages_en.properties +++ b/main/src/main/resources/messages_en.properties @@ -278,12 +278,14 @@ citizens.commands.npc.script.current-scripts=[[{0}]]''s current scripts are [[{1 citizens.commands.npc.shulker.peek-set=[[{0}]]''s peek amount set to [[{1}]]. citizens.commands.npc.shulker.color-set=[[{0}]]''s color set to [[{1}]]. citizens.commands.npc.shulker.invalid-color=Invalid shulker color given. Valid colors are: [[{0}]]. +citizens.commands.npc.sitting.set=[[{0}]] is now sitting at [[{1}]]. +citizens.commands.npc.sitting.unset=[[{0}]] is no longer sitting. citizens.commands.npc.skin.error-setting-url=Error downloading skin texture from [[{0}]]. Are you sure the URL is valid? citizens.commands.npc.skin.skin-url-set=Downloaded [[{0}]]''s skin from [[{1}]]. citizens.commands.npc.skin.set=[[{0}]]''s skin name set to [[{1}]]. citizens.commands.npc.skin.missing-skin=A skin name is required. citizens.commands.npc.skin.fetching=Attempting to generate skin using https://mineskin.org -citizens.commands.npc.skin.invalid-file=Skin file [[{0}]] not found. Must be a file under plugins/Citizens2/skins/ +citizens.commands.npc.skin.invalid-file=Skin file [[{0}]] not found. Must be a file under plugins/Citizens/skins/ citizens.commands.npc.skin.cleared=[[{0}]]''s skin name was cleared. citizens.commands.npc.skin.layers-set=[[{0}]]''s skin layers: cape - [[{1}]], hat - [[{2}]], jacket - [[{3}]], sleeves - [[{4}]], pants - [[{5}]]. citizens.commands.npc.size.description=[[{0}]]''s size is [[{1}]]. diff --git a/pom.xml b/pom.xml index 3cef1f8a5..833f27202 100644 --- a/pom.xml +++ b/pom.xml @@ -4,10 +4,10 @@ pom net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT Unknown - 2.0.31 + 2.0.32 3.5.0 3.5.0 3.1.1 @@ -37,6 +37,7 @@ v1_16_R3 v1_18_R2 v1_19_R3 + v1_20_R1 dist \ No newline at end of file diff --git a/v1_10_R1/pom.xml b/v1_10_R1/pom.xml index e59367f66..d6ec0e482 100644 --- a/v1_10_R1/pom.xml +++ b/v1_10_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_10_R1 diff --git a/v1_11_R1/pom.xml b/v1_11_R1/pom.xml index 0a01a3e52..d6827c7bf 100644 --- a/v1_11_R1/pom.xml +++ b/v1_11_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_11_R1 diff --git a/v1_12_R1/pom.xml b/v1_12_R1/pom.xml index 94fcb9db3..4b45b6c3c 100644 --- a/v1_12_R1/pom.xml +++ b/v1_12_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_12_R1 diff --git a/v1_13_R2/pom.xml b/v1_13_R2/pom.xml index 0c87e946e..a2bac48d0 100644 --- a/v1_13_R2/pom.xml +++ b/v1_13_R2/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_13_R2 diff --git a/v1_14_R1/pom.xml b/v1_14_R1/pom.xml index 480ecd6f7..b60821802 100644 --- a/v1_14_R1/pom.xml +++ b/v1_14_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_14_R1 diff --git a/v1_15_R1/pom.xml b/v1_15_R1/pom.xml index 158a96ebc..3136f8f6f 100644 --- a/v1_15_R1/pom.xml +++ b/v1_15_R1/pom.xml @@ -4,7 +4,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_15_R1 diff --git a/v1_16_R3/pom.xml b/v1_16_R3/pom.xml index efc50a1a5..b37bc939e 100644 --- a/v1_16_R3/pom.xml +++ b/v1_16_R3/pom.xml @@ -4,7 +4,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_16_R3 diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index b983368a5..c226712a3 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_17_R1 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 index d98079430..e6cb4796d 100644 --- 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 @@ -480,6 +480,5 @@ public class EntityHumanNPC extends ServerPlayer implements NPCHolder, Skinnable private static final float EPSILON = 0.003F; 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/util/PlayerlistTracker.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java index 3ff33e155..a2e6cd951 100644 --- 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 @@ -54,11 +54,8 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { public void updatePlayer(final ServerPlayer entityplayer) { if (tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - if (REQUIRES_SYNC == null) { - REQUIRES_SYNC = !Bukkit.isPrimaryThread(); - } NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - Util.callPossiblyAsyncEvent(event, REQUIRES_SYNC); + REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); if (event.isCancelled()) return; Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); @@ -117,9 +114,8 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { } private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); - private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static Boolean REQUIRES_SYNC; + private static boolean REQUIRES_SYNC; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_18_R2/pom.xml b/v1_18_R2/pom.xml index 57c24e737..532de4afe 100644 --- a/v1_18_R2/pom.xml +++ b/v1_18_R2/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_18_R2 diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java index ebb4ac902..04c52f381 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java @@ -54,11 +54,8 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { public void updatePlayer(final ServerPlayer entityplayer) { if (tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - if (REQUIRES_SYNC == null) { - REQUIRES_SYNC = !Bukkit.isPrimaryThread(); - } NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - Util.callPossiblyAsyncEvent(event, REQUIRES_SYNC); + REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); if (event.isCancelled()) return; Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); @@ -117,9 +114,8 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { } private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); - private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static Boolean REQUIRES_SYNC; + private static boolean REQUIRES_SYNC; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_19_R3/pom.xml b/v1_19_R3/pom.xml index 1fe20cc5a..6b1f7e746 100644 --- a/v1_19_R3/pom.xml +++ b/v1_19_R3/pom.xml @@ -4,7 +4,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_19_R3 diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java index d49edcd5b..22c4207f7 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java @@ -81,11 +81,8 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { if (tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - if (REQUIRES_SYNC == null) { - REQUIRES_SYNC = !Bukkit.isPrimaryThread(); - } NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - Util.callPossiblyAsyncEvent(event, REQUIRES_SYNC); + REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); if (event.isCancelled()) return; Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); @@ -141,7 +138,7 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static Boolean REQUIRES_SYNC; + private static boolean REQUIRES_SYNC = false; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_20_R1/pom.xml b/v1_20_R1/pom.xml new file mode 100644 index 000000000..d3aad712b --- /dev/null +++ b/v1_20_R1/pom.xml @@ -0,0 +1,112 @@ + + + 4.0.0 + + net.citizensnpcs + citizens-parent + 2.0.32-SNAPSHOT + + citizens-v1_20_R1 + + UTF-8 + 1.20-R0.1-SNAPSHOT + + + + viaversion-repo + https://repo.viaversion.com + + + + + ${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 + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-deploy-plugin + ${maven-deploy-plugin.version} + + + default-deploy + none + + + + + net.md-5 + specialsource-maven-plugin + 1.2.4 + + + package + + remap + + remap-obf + + org.spigotmc:minecraft-server:${craftbukkit.version}:txt:maps-mojang + true + org.spigotmc:spigot:${craftbukkit.version}:jar:remapped-mojang + true + remapped-obf + + + + package + + remap + + remap-spigot + + ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar + org.spigotmc:minecraft-server:${craftbukkit.version}:csrg:maps-spigot + org.spigotmc:spigot:${craftbukkit.version}:jar:remapped-obf + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + package + + shade + + + + + + + \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AllayController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AllayController.java new file mode 100644 index 000000000..6613aa6bb --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AllayController.java @@ -0,0 +1,242 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftAllay; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import com.google.common.collect.Lists; +import com.mojang.datafixers.util.Pair; + +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.EquipmentSlot; +import net.minecraft.world.entity.animal.allay.Allay; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class AllayController extends MobEntityController { + public AllayController() { + super(EntityAllayNPC.class); + } + + @Override + public org.bukkit.entity.Allay getBukkitEntity() { + return (org.bukkit.entity.Allay) super.getBukkitEntity(); + } + + public static class AllayNPC extends CraftAllay implements ForwardingNPCHolder { + public AllayNPC(EntityAllayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityAllayNPC extends Allay implements NPCHolder { + private final CitizensNPC npc; + private int taskId = -1; + + public EntityAllayNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityAllayNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new AllayNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + protected InteractionResult mobInteract(Player var0, InteractionHand var1) { + if (npc != null && npc.isProtected()) { + // prevent clientside prediction + if (taskId == -1) { + taskId = Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + NMSImpl.sendPacket((org.bukkit.entity.Player) var0.getBukkitEntity(), + new ClientboundSetEquipmentPacket(getId(), + Lists.newArrayList( + Pair.of(EquipmentSlot.OFFHAND, + this.getItemInHand(InteractionHand.OFF_HAND)), + Pair.of(EquipmentSlot.MAINHAND, + this.getItemInHand(InteractionHand.MAIN_HAND))))); + ((org.bukkit.entity.Player) var0.getBukkitEntity()).updateInventory(); + taskId = -1; + }, 2); + } + return InteractionResult.FAIL; + } + return super.mobInteract(var0, var1); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ArmorStandController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ArmorStandController.java new file mode 100644 index 000000000..eebb2cf4c --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ArmorStandController.java @@ -0,0 +1,150 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftArmorStand; +import org.bukkit.craftbukkit.v1_20_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_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.MobAI; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_20_R1.util.MobAI.ForwardingMobAI; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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, ForwardingMobAI { + private MobAI ai; + 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; + if (npc != null) { + ai = new BasicMobAI(this); + } + } + + @Override + public MobAI getAI() { + return ai; + } + + @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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + ai.tickAI(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AxolotlController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AxolotlController.java new file mode 100644 index 000000000..cb601e037 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/AxolotlController.java @@ -0,0 +1,256 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftAxolotl; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import com.mojang.serialization.Dynamic; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.Brain; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.animal.axolotl.Axolotl; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + this.getAttribute(Attributes.MOVEMENT_SPEED) + .setBaseValue(this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue() / 10); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + protected Brain makeBrain(Dynamic dynamic) { + if (npc == null || npc.useMinecraftAI()) { + return super.makeBrain(dynamic); + } + return brainProvider().makeBrain(dynamic); + } + + @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 || itemstack.getItem() == Items.WATER_BUCKET) { + 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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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 MoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java new file mode 100644 index 000000000..ad1c180c6 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java @@ -0,0 +1,185 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftBat; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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) { + setFlying(false); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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()) { + super.customServerAiStep(); + } + npc.update(); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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); + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BeeController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BeeController.java new file mode 100644 index 000000000..22c17b0bd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BeeController.java @@ -0,0 +1,180 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftBee; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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()) { + super.customServerAiStep(); + } + npc.update(); + } + } + + + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BlazeController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BlazeController.java new file mode 100644 index 000000000..546275207 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BlazeController.java @@ -0,0 +1,175 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftBlaze; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class BlazeController extends MobEntityController { + public BlazeController() { + super(EntityBlazeNPC.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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CamelController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CamelController.java new file mode 100644 index 000000000..28d6a606f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CamelController.java @@ -0,0 +1,239 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCamel; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.camel.Camel; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class CamelController extends MobEntityController { + public CamelController() { + super(EntityCamelNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.Camel getBukkitEntity() { + return (org.bukkit.entity.Camel) super.getBukkitEntity(); + } + + public static class CamelNPC extends CraftCamel implements ForwardingNPCHolder { + public CamelNPC(EntityCamelNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityCamelNPC extends Camel implements NPCHolder { + private final CitizensNPC npc; + + public EntityCamelNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityCamelNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + ((org.bukkit.entity.Camel) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Camel) getBukkitEntity()).getMaxDomestication()); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new CamelNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CatController.java new file mode 100644 index 000000000..5ea7dbbc2 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CatController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCat; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CaveSpiderController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CaveSpiderController.java new file mode 100644 index 000000000..188a3e757 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CaveSpiderController.java @@ -0,0 +1,221 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCaveSpider; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ChickenController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ChickenController.java new file mode 100644 index 000000000..a263ce207 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ChickenController.java @@ -0,0 +1,230 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftChicken; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @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.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CodController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CodController.java new file mode 100644 index 000000000..bb07a854c --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CodController.java @@ -0,0 +1,261 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCod; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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.isProtected(); + } + 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 EntityMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CowController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CowController.java new file mode 100644 index 000000000..02a8713f7 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CowController.java @@ -0,0 +1,238 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCow; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CreeperController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CreeperController.java new file mode 100644 index 000000000..62201cfcd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/CreeperController.java @@ -0,0 +1,241 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftCreeper; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public void ignite() { + if (npc == null || !npc.isProtected()) { + super.ignite(); + } + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DolphinController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DolphinController.java new file mode 100644 index 000000000..e29d7aea9 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DolphinController.java @@ -0,0 +1,240 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDolphin; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.ai.control.MoveControl; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 boolean inProtectedTick; + + 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) { + this.oldMoveController = this.moveControl; + this.moveControl = new MoveControl(this); + this.getAttribute(Attributes.MOVEMENT_SPEED) + .setBaseValue(this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue() / 10); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isInWaterRainOrBubble() { + return inProtectedTick ? true : super.isInWaterRainOrBubble(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null && npc.isProtected()) { + inProtectedTick = true; + } + super.tick(); + inProtectedTick = false; + 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 MoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DrownedController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DrownedController.java new file mode 100644 index 000000000..f4ab376dd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/DrownedController.java @@ -0,0 +1,211 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDrowned; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EnderDragonController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EnderDragonController.java new file mode 100644 index 000000000..2038b4adc --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EnderDragonController.java @@ -0,0 +1,274 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import java.lang.invoke.MethodHandle; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEnderDragon; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.versioned.EnderDragonTrait; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntitySelector; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + public void aiStep() { + if (npc != null) { + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + + } + if (npc != null && !npc.useMinecraftAI()) { + if (isDeadOrDying()) { + setHealth(0F); + return; + } + if (this.posPointer < 0) { + for (int i = 0; i < this.positions.length; ++i) { + this.positions[i][0] = this.getYRot(); + this.positions[i][1] = this.getY(); + } + } + + if (++this.posPointer == this.positions.length) { + this.posPointer = 0; + } + + this.positions[this.posPointer][0] = this.getYRot(); + this.positions[this.posPointer][1] = this.getY(); + + float[][] pos = NMS.calculateDragonPositions(getYRot(), + new double[][] { getLatencyPos(0, 1F), getLatencyPos(5, 1F), getLatencyPos(10, 1F), + getLatencyPos(12, 1F), getLatencyPos(14, 1F), getLatencyPos(16, 1F) }); + for (int j = 0; j < subEntities.length; ++j) { + Vec3 vec3 = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), + this.subEntities[j].getZ()); + subEntities[j].setPos(this.getX() + pos[j][0], this.getY() + pos[j][1], this.getZ() + pos[j][2]); + subEntities[j].xo = subEntities[j].xOld = vec3.x; + subEntities[j].yo = subEntities[j].yOld = vec3.y; + subEntities[j].zo = subEntities[j].zOld = vec3.z; + } + + if (getFirstPassenger() != null) { + setYRot(getFirstPassenger().getBukkitYaw() - 180); + } + + Vec3 mot = getDeltaMovement(); + if (mot.x != 0 || mot.y != 0 || mot.z != 0) { + mot = mot.multiply(0.98, 0.91, 0.98); + if (getFirstPassenger() == null) { + setYRot(Util.getDragonYaw(getBukkitEntity(), mot.x, mot.z)); + } + setPos(getX() + mot.x, getY() + mot.y, getZ() + mot.z); + setDeltaMovement(mot); + } + + if (npc.hasTrait(EnderDragonTrait.class) && npc.getOrAddTrait(EnderDragonTrait.class).isDestroyWalls() + && NMSImpl.ENDERDRAGON_CHECK_WALLS != null) { + for (int i = 0; i < 3; i++) { + try { + this.inWall |= (boolean) NMSImpl.ENDERDRAGON_CHECK_WALLS.invoke(this, + subEntities[i].getBoundingBox()); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + if (npc.data().get(NPC.Metadata.COLLIDABLE, false)) { + try { + KNOCKBACK.invoke(this, + this.level().getEntities(this, + subEntities[6].getBoundingBox().inflate(4.0, 2.0, 4.0).move(0.0, -2.0, 0.0), + EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + KNOCKBACK.invoke(this, + this.level().getEntities(this, + subEntities[7].getBoundingBox().inflate(4.0, 2.0, 4.0).move(0.0, -2.0, 0.0), + EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + HURT.invoke(this, this.level().getEntities(this, subEntities[0].getBoundingBox().inflate(1.0), + EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + HURT.invoke(this, this.level().getEntities(this, subEntities[1].getBoundingBox().inflate(1.0), + EntitySelector.NO_CREATIVE_OR_SPECTATOR)); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } else { + super.aiStep(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + return super.canRide(entity); + } + + @Override + public void checkDespawn() { + if (npc == null) { + super.checkDespawn(); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new EnderDragonNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 + protected boolean reallyHurt(DamageSource source, float f) { + if (npc == null) + return super.reallyHurt(source, f); + + Vec3 old = getDeltaMovement(); + boolean res = super.reallyHurt(source, f); + if (getPhaseManager().getCurrentPhase().getPhase() == EnderDragonPhase.HOVERING) { + setDeltaMovement(old); + } + return res; + } + + @Override + public boolean save(CompoundTag save) { + return npc == null ? super.save(save) : false; + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + + private static final MethodHandle HURT = NMS.getMethodHandle(EnderDragon.class, "c", true, List.class); + + private static final MethodHandle KNOCKBACK = NMS.getMethodHandle(EnderDragon.class, "b", true, List.class); + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermanController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermanController.java new file mode 100644 index 000000000..d9e23cc66 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermanController.java @@ -0,0 +1,232 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import java.util.Optional; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEnderman; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Optional randomTeleport(double d0, double d1, double d2, boolean flag, + PlayerTeleportEvent.TeleportCause cause) { + if (npc == null) { + return super.randomTeleport(d0, d1, d2, flag, cause); + } + return Optional.of(false); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermiteController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermiteController.java new file mode 100644 index 000000000..0149f1f19 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EndermiteController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEndermite; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EntityHumanNPC.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EntityHumanNPC.java new file mode 100644 index 000000000..ecf3f37d3 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EntityHumanNPC.java @@ -0,0 +1,494 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.net.Socket; +import java.util.List; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_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.mojang.authlib.GameProfile; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.event.NPCKnockbackEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.npc.NPC.NPCUpdate; +import net.citizensnpcs.api.trait.trait.Inventory; +import net.citizensnpcs.api.util.SpigotUtil; +import net.citizensnpcs.nms.v1_20_R1.network.EmptyNetHandler; +import net.citizensnpcs.nms.v1_20_R1.network.EmptyNetworkManager; +import net.citizensnpcs.nms.v1_20_R1.util.EmptyAdvancementDataPlayer; +import net.citizensnpcs.nms.v1_20_R1.util.EmptyServerStatsCounter; +import net.citizensnpcs.nms.v1_20_R1.util.MobAI; +import net.citizensnpcs.nms.v1_20_R1.util.MobAI.ForwardingMobAI; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +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.EmptySocket; +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.MutableComponent; +import net.minecraft.network.chat.contents.LiteralContents; +import net.minecraft.network.protocol.PacketFlow; +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.sounds.SoundEvent; +import net.minecraft.stats.ServerStatsCounter; +import net.minecraft.tags.TagKey; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class EntityHumanNPC extends ServerPlayer implements NPCHolder, SkinnableEntity, ForwardingMobAI { + private MobAI ai; + private int jumpTicks = 0; + private final CitizensNPC npc; + private boolean setBukkitEntity; + private final SkinPacketTracker skinTracker; + private EmptyServerStatsCounter statsCache; + + public EntityHumanNPC(MinecraftServer minecraftServer, ServerLevel world, GameProfile gameProfile, NPC npc) { + super(minecraftServer, world, gameProfile); + this.npc = (CitizensNPC) npc; + if (npc != null) { + ai = new BasicMobAI(this); + 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 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(), () -> { + ((ServerLevel) level()).removePlayerImmediately(EntityHumanNPC.this, RemovalReason.KILLED); + ((ServerLevel) level()).getChunkSource().removeEntity(EntityHumanNPC.this); + }, 15); // give enough time for death and smoke animation + } + + @Override + public void doTick() { + if (npc == null) { + super.doTick(); + return; + } + super.baseTick(); + boolean navigating = npc.getNavigator().isNavigating() || ai.getMoveControl().hasWanted(); + if (!navigating && getBukkitEntity() != null + && (!npc.hasTrait(Gravity.class) || npc.getOrAddTrait(Gravity.class).hasGravity()) + && Util.isLoaded(getBukkitEntity().getLocation(LOADED_LOCATION)) + && SpigotUtil.checkYSafe(getY(), getBukkitEntity().getWorld())) { + moveWithFallDamage(Vec3.ZERO); + } + Vec3 mot = getDeltaMovement(); + if (Math.abs(mot.x) < EPSILON && Math.abs(mot.y) < EPSILON && Math.abs(mot.z) < EPSILON) { + setDeltaMovement(Vec3.ZERO); + } + if (navigating) { + if (!ai.getNavigation().isDone()) { + ai.getNavigation().tick(); + } + moveOnCurrentHeading(); + } + tickAI(); + detectEquipmentUpdates(); + noPhysics = isSpectator(); + if (isSpectator()) { + this.onGround = false; + } + + pushEntities(); + + if (npc.data().get(NPC.Metadata.PICKUP_ITEMS, false)) { + AABB axisalignedbb; + if (this.isPassenger() && !this.getVehicle().isRemoved()) { + axisalignedbb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0); + } else { + axisalignedbb = this.getBoundingBox().inflate(1.0, 0.5, 1.0); + } + for (Entity entity : level().getEntities(this, axisalignedbb)) { + entity.playerTouch(this); + } + } + } + + @Override + public MobAI getAI() { + return ai; + } + + @Override + public CraftPlayer getBukkitEntity() { + if (npc != null && !setBukkitEntity) { + NMSImpl.setBukkitEntity(this, new PlayerNPC(this)); + setBukkitEntity = true; + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public NPC getNPC() { + return npc; + } + + @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 ServerStatsCounter getStats() { + return this.statsCache == null ? statsCache = new EmptyServerStatsCounter() : statsCache; + } + + @Override + public Component getTabListDisplayName() { + if (Setting.DISABLE_TABLIST.asBoolean()) { + return MutableComponent.create(new LiteralContents("")); + } + 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 + } + 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()); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NPCKnockbackEvent event = new NPCKnockbackEvent(npc, strength, dx, dz); + Bukkit.getPluginManager().callEvent(event); + Vector kb = event.getKnockbackVector(); + if (!event.isCancelled()) { + super.knockback(event.getStrength(), kb.getX(), kb.getZ()); + } + } + + private void moveOnCurrentHeading() { + if (jumping) { + if (onGround && jumpTicks == 0) { + jumpFromGround(); + jumpTicks = 10; + } + } else { + jumpTicks = 0; + } + xxa *= 0.98F; + zza *= 0.98F; + moveWithFallDamage(new Vec3(this.xxa, this.yya, this.zza)); + NMS.setHeadYaw(getBukkitEntity(), getYRot()); + if (jumpTicks > 0) { + jumpTicks--; + } + } + + private void moveWithFallDamage(Vec3 vec) { + double x = getX(); + double y = getY(); + double z = getZ(); + travel(vec); + if (!npc.isProtected()) { + doCheckFallDamage(getX() - x, getY() - y, getZ() - z, onGround); + } + } + + @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(); + } + + @Override + public void setSkinFlags(byte flags) { + 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); + } + + @Override + public void tick() { + super.tick(); + if (npc == null) + return; + Bukkit.getServer().getPluginManager().unsubscribeFromPermission("bukkit.broadcast.user", getBukkitEntity()); + updatePackets(npc.getNavigator().isNavigating()); + npc.update(); + } + + @Override + public void tickAI() { + ai.getMoveControl().tick(); + ai.getJumpControl().tick(); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + Vec3 old = getDeltaMovement().add(0, 0, 0); + boolean res = super.updateFluidHeightAndDoFluidPushing(tagkey, d0); + if (!npc.isPushableByFluids()) { + setDeltaMovement(old); + } + return res; + } + + private void updatePackets(boolean navigating) { + if (!npc.isUpdating(NPCUpdate.PACKET)) + return; + + effectsDirty = true; + } + + public static class PlayerNPC extends CraftPlayer implements NPCHolder, SkinnableEntity { + private final CitizensNPC npc; + + private PlayerNPC(EntityHumanNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + this.npc = entity.npc; + npc.getOrAddTrait(Inventory.class); + } + + @Override + public boolean canSee(org.bukkit.entity.Entity entity) { + if (entity != null && entity.getType().name().contains("ITEM_FRAME")) { + return false; // optimise for large maps in item frames + } + return super.canSee(entity); + } + + @Override + public Player getBukkitEntity() { + return this; + } + + @Override + public EntityHumanNPC getHandle() { + return (EntityHumanNPC) this.entity; + } + + @Override + public List getMetadata(String metadataKey) { + return ((CraftServer) Bukkit.getServer()).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 ((CraftServer) Bukkit.getServer()).getEntityMetadata().hasMetadata(this, metadataKey); + } + + @Override + public void removeMetadata(String metadataKey, Plugin owningPlugin) { + ((CraftServer) Bukkit.getServer()).getEntityMetadata().removeMetadata(this, metadataKey, owningPlugin); + } + + @Override + public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { + ((CraftServer) Bukkit.getServer()).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 float EPSILON = 0.003F; + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EvokerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EvokerController.java new file mode 100644 index 000000000..82a02678c --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/EvokerController.java @@ -0,0 +1,212 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEvoker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class EvokerNPC extends CraftEvoker implements ForwardingNPCHolder { + public EvokerNPC(EntityEvokerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FoxController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FoxController.java new file mode 100644 index 000000000..3869ead2b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FoxController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFox; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class FoxNPC extends CraftFox implements ForwardingNPCHolder { + public FoxNPC(EntityFoxNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FrogController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FrogController.java new file mode 100644 index 000000000..ff8293f1f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/FrogController.java @@ -0,0 +1,225 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFrog; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.animal.frog.Frog; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class FrogController extends MobEntityController { + public FrogController() { + super(EntityFrogNPC.class); + } + + @Override + public org.bukkit.entity.Frog getBukkitEntity() { + return (org.bukkit.entity.Frog) super.getBukkitEntity(); + } + + public static class EntityFrogNPC extends Frog implements NPCHolder { + private final CitizensNPC npc; + + public EntityFrogNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityFrogNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + croakAnimationState.start(1); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new FrogNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class FrogNPC extends CraftFrog implements ForwardingNPCHolder { + public FrogNPC(EntityFrogNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GhastController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GhastController.java new file mode 100644 index 000000000..5e5d1dcb2 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GhastController.java @@ -0,0 +1,181 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGhast; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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); + } + super.customServerAiStep(); + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isAutoSpinAttack() { + return npc != null; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GhastNPC extends CraftGhast implements ForwardingNPCHolder { + public GhastNPC(EntityGhastNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GiantController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GiantController.java new file mode 100644 index 000000000..706fae85a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GiantController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGiant; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GiantNPC extends CraftGiant implements ForwardingNPCHolder { + public GiantNPC(EntityGiantNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GlowSquidController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GlowSquidController.java new file mode 100644 index 000000000..0b131084a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GlowSquidController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGlowSquid; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GlowSquidNPC extends CraftGlowSquid implements ForwardingNPCHolder { + public GlowSquidNPC(EntityGlowSquidNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GoatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GoatController.java new file mode 100644 index 000000000..958223c3e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GoatController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGoat; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GoatNPC extends CraftGoat implements ForwardingNPCHolder { + public GoatNPC(EntityGoatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianController.java new file mode 100644 index 000000000..b70d0b473 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianController.java @@ -0,0 +1,227 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGuardian; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @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.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GuardianNPC extends CraftGuardian implements ForwardingNPCHolder { + public GuardianNPC(EntityGuardianNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianElderController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianElderController.java new file mode 100644 index 000000000..60eeea193 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/GuardianElderController.java @@ -0,0 +1,227 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftElderGuardian; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @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.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class GuardianElderNPC extends CraftElderGuardian implements ForwardingNPCHolder { + public GuardianElderNPC(EntityGuardianElderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HoglinController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HoglinController.java new file mode 100644 index 000000000..9812dd068 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HoglinController.java @@ -0,0 +1,215 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftHoglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HoglinNPC extends CraftHoglin implements ForwardingNPCHolder { + public HoglinNPC(EntityHoglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseController.java new file mode 100644 index 000000000..c20c11cec --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseController.java @@ -0,0 +1,268 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class HorseController extends MobEntityController { + public HorseController() { + super(EntityHorseNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.Horse getBukkitEntity() { + return (org.bukkit.entity.Horse) super.getBukkitEntity(); + } + + public static class EntityHorseNPC extends Horse implements NPCHolder { + private double baseMovementSpeed; + + 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) { + org.bukkit.entity.Horse horse = (org.bukkit.entity.Horse) getBukkitEntity(); + horse.setDomestication(horse.getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.isVehicle(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HorseNPC extends CraftHorse implements ForwardingNPCHolder { + public HorseNPC(EntityHorseNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseDonkeyController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseDonkeyController.java new file mode 100644 index 000000000..edeef6e44 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseDonkeyController.java @@ -0,0 +1,268 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDonkey; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class HorseDonkeyController extends MobEntityController { + public HorseDonkeyController() { + super(EntityHorseDonkeyNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.addTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.Donkey getBukkitEntity() { + return (org.bukkit.entity.Donkey) super.getBukkitEntity(); + } + + public static class EntityHorseDonkeyNPC extends Donkey implements NPCHolder { + private double baseMovementSpeed; + + 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) { + ((org.bukkit.entity.Donkey) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Donkey) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.isVehicle(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HorseDonkeyNPC extends CraftDonkey implements ForwardingNPCHolder { + public HorseDonkeyNPC(EntityHorseDonkeyNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseMuleController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseMuleController.java new file mode 100644 index 000000000..fa6abc3af --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseMuleController.java @@ -0,0 +1,268 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMule; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class HorseMuleController extends MobEntityController { + public HorseMuleController() { + super(EntityHorseMuleNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.Mule getBukkitEntity() { + return (org.bukkit.entity.Mule) super.getBukkitEntity(); + } + + public static class EntityHorseMuleNPC extends Mule implements NPCHolder { + private double baseMovementSpeed; + + 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) { + ((org.bukkit.entity.Mule) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.Mule) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.isVehicle(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HorseMuleNPC extends CraftMule implements ForwardingNPCHolder { + public HorseMuleNPC(EntityHorseMuleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java new file mode 100644 index 000000000..b23902359 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseSkeletonController.java @@ -0,0 +1,268 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSkeletonHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class HorseSkeletonController extends MobEntityController { + public HorseSkeletonController() { + super(EntityHorseSkeletonNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.SkeletonHorse getBukkitEntity() { + return (org.bukkit.entity.SkeletonHorse) super.getBukkitEntity(); + } + + public static class EntityHorseSkeletonNPC extends SkeletonHorse implements NPCHolder { + private double baseMovementSpeed; + + 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) { + ((org.bukkit.entity.SkeletonHorse) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.SkeletonHorse) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.isVehicle(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HorseSkeletonNPC extends CraftSkeletonHorse implements ForwardingNPCHolder { + public HorseSkeletonNPC(EntityHorseSkeletonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseZombieController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseZombieController.java new file mode 100644 index 000000000..731ab2711 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HorseZombieController.java @@ -0,0 +1,268 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftZombieHorse; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class HorseZombieController extends MobEntityController { + public HorseZombieController() { + super(EntityHorseZombieNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.ZombieHorse getBukkitEntity() { + return (org.bukkit.entity.ZombieHorse) super.getBukkitEntity(); + } + + public static class EntityHorseZombieNPC extends ZombieHorse implements NPCHolder { + private double baseMovementSpeed; + + 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) { + ((org.bukkit.entity.ZombieHorse) getBukkitEntity()) + .setDomestication(((org.bukkit.entity.ZombieHorse) getBukkitEntity()).getMaxDomestication()); + baseMovementSpeed = this.getAttribute(Attributes.MOVEMENT_SPEED).getValue(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isControlledByLocalInstance() { + if (npc != null && riding) { + return true; + } + return super.isControlledByLocalInstance(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return npc != null && npc.getNavigator().isNavigating() ? false : super.isVehicle(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class HorseZombieNPC extends CraftZombieHorse implements ForwardingNPCHolder { + public HorseZombieNPC(EntityHorseZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HumanController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HumanController.java new file mode 100644 index 000000000..ea00736ab --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/HumanController.java @@ -0,0 +1,70 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_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.trait.ScoreboardTrait; +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) { // set version to 2 + 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()) { + npc.getOrAddTrait(ScoreboardTrait.class).createTeam(name); + } + 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(), () -> { + if (getBukkitEntity() == null || !getBukkitEntity().isValid() + || getBukkitEntity() != handle.getBukkitEntity()) + return; + boolean removeFromPlayerList = npc.data().get(NPC.Metadata.REMOVE_FROM_PLAYERLIST, + 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(); + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IllusionerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IllusionerController.java new file mode 100644 index 000000000..856c56624 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IllusionerController.java @@ -0,0 +1,212 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftIllusioner; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class IllusionerNPC extends CraftIllusioner implements ForwardingNPCHolder { + public IllusionerNPC(EntityIllusionerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IronGolemController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IronGolemController.java new file mode 100644 index 000000000..55d16d68d --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/IronGolemController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftIronGolem; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class IronGolemNPC extends CraftIronGolem implements ForwardingNPCHolder { + public IronGolemNPC(EntityIronGolemNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/LlamaController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/LlamaController.java new file mode 100644 index 000000000..f4f56f89b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/LlamaController.java @@ -0,0 +1,239 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLlama; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class LlamaController extends MobEntityController { + public LlamaController() { + super(EntityLlamaNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.Llama getBukkitEntity() { + return (org.bukkit.entity.Llama) super.getBukkitEntity(); + } + + public static class EntityLlamaNPC extends Llama implements NPCHolder { + 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) { + ((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.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class LlamaNPC extends CraftLlama implements ForwardingNPCHolder { + public LlamaNPC(EntityLlamaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MagmaCubeController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MagmaCubeController.java new file mode 100644 index 000000000..c7cbede63 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MagmaCubeController.java @@ -0,0 +1,243 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMagmaCube; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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); + this.oldMoveController = this.moveControl; + this.moveControl = new EntityMoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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 EntityMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MagmaCubeNPC extends CraftMagmaCube implements ForwardingNPCHolder { + public MagmaCubeNPC(EntityMagmaCubeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MobEntityController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MobEntityController.java new file mode 100644 index 000000000..8e3c8b5d5 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MobEntityController.java @@ -0,0 +1,82 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import java.lang.reflect.Constructor; +import java.util.Map; +import java.util.WeakHashMap; + +import org.bukkit.Location; +import org.bukkit.block.BlockFace; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.entity.Entity; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.nms.v1_20_R1.util.PitchableLookControl; +import net.citizensnpcs.npc.AbstractEntityController; +import net.citizensnpcs.trait.ScoreboardTrait; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; +import net.minecraft.world.level.Level; + +public abstract class MobEntityController extends AbstractEntityController { + private final Class clazz; + + protected MobEntityController(Class clazz) { + super(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); + if (entity instanceof Mob) { + NMSImpl.clearGoals(npc, ((Mob) entity).goalSelector, ((Mob) entity).targetSelector); + Mob mob = (Mob) entity; + if (mob.getLookControl().getClass() == LookControl.class) { + NMSImpl.setLookControl(mob, new PitchableLookControl(mob)); + } + } + entity.absMoveTo(at.getX(), at.getY(), at.getZ(), at.getYaw(), at.getPitch()); + if (npc != null) { + // 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); + } + entity.setUUID(npc.getUniqueId()); + if (Setting.USE_SCOREBOARD_TEAMS.asBoolean()) { + npc.getOrAddTrait(ScoreboardTrait.class).createTeam(npc.getUniqueId().toString()); + } + } + + return entity.getBukkitEntity(); + } + + private net.minecraft.world.entity.Entity createEntityFromClass(Object... args) { + try { + return (net.minecraft.world.entity.Entity) getConstructor(clazz).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 { + CONSTRUCTOR_CACHE.put(clazz, constructor = clazz.getConstructor(EntityType.class, Level.class, NPC.class)); + return constructor; + } catch (Exception ex) { + throw new IllegalStateException("unable to find an entity constructor"); + } + } + + private static final Map, Constructor> CONSTRUCTOR_CACHE = new WeakHashMap, Constructor>(); +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MushroomCowController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MushroomCowController.java new file mode 100644 index 000000000..c9f68ae54 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/MushroomCowController.java @@ -0,0 +1,231 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMushroomCow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MushroomCowNPC extends CraftMushroomCow implements ForwardingNPCHolder { + public MushroomCowNPC(EntityMushroomCowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/OcelotController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/OcelotController.java new file mode 100644 index 000000000..89ebe0ddb --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/OcelotController.java @@ -0,0 +1,228 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftOcelot; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class OcelotNPC extends CraftOcelot implements ForwardingNPCHolder { + public OcelotNPC(EntityOcelotNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PandaController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PandaController.java new file mode 100644 index 000000000..5d1a45cce --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PandaController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPanda; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PandaNPC extends CraftPanda implements ForwardingNPCHolder { + public PandaNPC(EntityPandaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ParrotController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ParrotController.java new file mode 100644 index 000000000..43363090d --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ParrotController.java @@ -0,0 +1,190 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftParrot; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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()) { + super.customServerAiStep(); + } + npc.update(); + } + } + + @Override + public SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + // block feeding + if (npc == null || !npc.isProtected()) { + 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; + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ParrotNPC extends CraftParrot implements ForwardingNPCHolder { + public ParrotNPC(EntityParrotNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PhantomController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PhantomController.java new file mode 100644 index 000000000..12dac8ccc --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PhantomController.java @@ -0,0 +1,257 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPhantom; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new EntityMoveControl(this); + this.lookControl = new LookControl(this); + } + if (npc.isProtected()) { + setSecondsOnFire(0); + } + npc.update(); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isSunBurnTick() { + if (npc == null || !npc.isProtected()) + return super.isSunBurnTick(); + return false; + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 + protected boolean shouldDespawnInPeaceful() { + return npc != null ? false : super.shouldDespawnInPeaceful(); + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PhantomNPC extends CraftPhantom implements ForwardingNPCHolder { + public PhantomNPC(EntityPhantomNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigController.java new file mode 100644 index 000000000..877285346 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigController.java @@ -0,0 +1,236 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPig; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + // block carrot-on-a-stick behaviour + return npc == null ? super.isVehicle() : false; + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PigNPC extends CraftPig implements ForwardingNPCHolder { + public PigNPC(EntityPigNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigZombieController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigZombieController.java new file mode 100644 index 000000000..9718d6915 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PigZombieController.java @@ -0,0 +1,211 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPigZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PigZombieNPC extends CraftPigZombie implements ForwardingNPCHolder { + public PigZombieNPC(EntityPigZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinBruteController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinBruteController.java new file mode 100644 index 000000000..0c7a22145 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinBruteController.java @@ -0,0 +1,214 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPiglinBrute; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PiglinBruteNPC extends CraftPiglinBrute implements ForwardingNPCHolder { + public PiglinBruteNPC(EntityPiglinBruteNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinController.java new file mode 100644 index 000000000..0bbf3a27d --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PiglinController.java @@ -0,0 +1,214 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPiglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PiglinNPC extends CraftPiglin implements ForwardingNPCHolder { + public PiglinNPC(EntityPiglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PillagerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PillagerController.java new file mode 100644 index 000000000..14ec3d035 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PillagerController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPillager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PillagerNPC extends CraftPillager implements ForwardingNPCHolder { + public PillagerNPC(EntityPillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PolarBearController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PolarBearController.java new file mode 100644 index 000000000..b786878eb --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PolarBearController.java @@ -0,0 +1,186 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPolarBear; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +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.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PolarBearNPC extends CraftPolarBear implements ForwardingNPCHolder { + public PolarBearNPC(EntityPolarBearNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PufferFishController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PufferFishController.java new file mode 100644 index 000000000..f30106f53 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/PufferFishController.java @@ -0,0 +1,293 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPufferFish; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.trait.versioned.PufferFishTrait; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +import net.minecraft.core.BlockPos; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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.isProtected(); + } + 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 EntityMoveControl(this); + } + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @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.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RabbitController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RabbitController.java new file mode 100644 index 000000000..25724e034 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RabbitController.java @@ -0,0 +1,242 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftRabbit; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public LivingEntity getTarget() { + return npc != null ? null : super.getTarget(); + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 setVariant(Variant variant) { + if (npc != null) { + if (NMSImpl.getRabbitTypeField() == null) + return; + this.entityData.set(NMSImpl.getRabbitTypeField(), variant.id()); + return; + } + super.setVariant(variant); + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class RabbitNPC extends CraftRabbit implements ForwardingNPCHolder { + public RabbitNPC(EntityRabbitNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RavagerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RavagerController.java new file mode 100644 index 000000000..1ec7c7372 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/RavagerController.java @@ -0,0 +1,227 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftRavager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isVehicle() { + return (npc == null || npc.useMinecraftAI()) ? super.isVehicle() : false; + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class RavagerNPC extends CraftRavager implements ForwardingNPCHolder { + public RavagerNPC(EntityRavagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SalmonController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SalmonController.java new file mode 100644 index 000000000..c38243a83 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SalmonController.java @@ -0,0 +1,258 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSalmon; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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.isProtected(); + } + 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 EntityMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SalmonNPC extends CraftSalmon implements ForwardingNPCHolder { + public SalmonNPC(EntitySalmonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SheepController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SheepController.java new file mode 100644 index 000000000..cb7c212d1 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SheepController.java @@ -0,0 +1,221 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSheep; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SheepNPC extends CraftSheep implements ForwardingNPCHolder { + public SheepNPC(EntitySheepNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ShulkerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ShulkerController.java new file mode 100644 index 000000000..c707e15e1 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ShulkerController.java @@ -0,0 +1,237 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftShulker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @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.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ShulkerNPC extends CraftShulker implements ForwardingNPCHolder { + public ShulkerNPC(EntityShulkerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SilverfishController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SilverfishController.java new file mode 100644 index 000000000..b1b1b3551 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SilverfishController.java @@ -0,0 +1,221 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSilverfish; +import org.bukkit.util.Vector; + + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SilverfishNPC extends CraftSilverfish implements ForwardingNPCHolder { + public SilverfishNPC(EntitySilverfishNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonController.java new file mode 100644 index 000000000..17696075a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSkeleton; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SkeletonNPC extends CraftSkeleton implements ForwardingNPCHolder { + public SkeletonNPC(EntitySkeletonNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonStrayController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonStrayController.java new file mode 100644 index 000000000..f148f3594 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonStrayController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftStray; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class StrayNPC extends CraftStray implements ForwardingNPCHolder { + public StrayNPC(EntityStrayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonWitherController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonWitherController.java new file mode 100644 index 000000000..56d623589 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SkeletonWitherController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWitherSkeleton; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SkeletonWitherNPC extends CraftWitherSkeleton implements ForwardingNPCHolder { + public SkeletonWitherNPC(EntitySkeletonWitherNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SlimeController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SlimeController.java new file mode 100644 index 000000000..00acee619 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SlimeController.java @@ -0,0 +1,244 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSlime; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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); + this.oldMoveController = this.moveControl; + this.moveControl = new EntityMoveControl(this); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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 EntityMoveControl(this); + } + npc.update(); + } + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SlimeNPC extends CraftSlime implements ForwardingNPCHolder { + public SlimeNPC(EntitySlimeNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnifferController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnifferController.java new file mode 100644 index 000000000..8cebfdd4a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnifferController.java @@ -0,0 +1,236 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSniffer; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.sniffer.Sniffer; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class SnifferController extends MobEntityController { + public SnifferController() { + super(EntitySnifferNPC.class); + } + + @Override + public org.bukkit.entity.Sniffer getBukkitEntity() { + return (org.bukkit.entity.Sniffer) super.getBukkitEntity(); + } + + public static class EntitySnifferNPC extends Sniffer implements NPCHolder { + private final CitizensNPC npc; + + public EntitySnifferNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntitySnifferNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new SnifferNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SnifferNPC extends CraftSniffer implements ForwardingNPCHolder { + public SnifferNPC(EntitySnifferNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnowmanController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnowmanController.java new file mode 100644 index 000000000..9766e1910 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SnowmanController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSnowman; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SnowmanNPC extends CraftSnowman implements ForwardingNPCHolder { + public SnowmanNPC(EntitySnowmanNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SpiderController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SpiderController.java new file mode 100644 index 000000000..834f4ea11 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SpiderController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSpider; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SpiderNPC extends CraftSpider implements ForwardingNPCHolder { + public SpiderNPC(EntitySpiderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SquidController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SquidController.java new file mode 100644 index 000000000..5bdeaded6 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/SquidController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSquid; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SquidNPC extends CraftSquid implements ForwardingNPCHolder { + public SquidNPC(EntitySquidNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/StriderController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/StriderController.java new file mode 100644 index 000000000..a3382ece2 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/StriderController.java @@ -0,0 +1,211 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftStrider; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class StriderNPC extends CraftStrider implements ForwardingNPCHolder { + public StriderNPC(EntityStriderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TadpoleController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TadpoleController.java new file mode 100644 index 000000000..8c6f83810 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TadpoleController.java @@ -0,0 +1,258 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTadpole; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.frog.Frog; +import net.minecraft.world.entity.animal.frog.Tadpole; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class TadpoleController extends MobEntityController { + public TadpoleController() { + super(EntityTadpoleNPC.class); + } + + @Override + public org.bukkit.entity.Tadpole getBukkitEntity() { + return (org.bukkit.entity.Tadpole) super.getBukkitEntity(); + } + + public static class EntityTadpoleNPC extends Tadpole implements NPCHolder { + private final CitizensNPC npc; + + private MoveControl oldMoveController; + + public EntityTadpoleNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTadpoleNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + if (npc != null) { + 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.isProtected(); + } + 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); + if (npc.useMinecraftAI() && this.moveControl != this.oldMoveController) { + this.moveControl = this.oldMoveController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new EntityMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new TadpoleNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc == null || !npc.isProtected()) + return super.mobInteract(entityhuman, enumhand); + ItemStack itemstack = entityhuman.getItemInHand(enumhand); + if ((Frog.TEMPTATION_ITEM.test(itemstack) || 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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TadpoleNPC extends CraftTadpole implements ForwardingNPCHolder { + public TadpoleNPC(EntityTadpoleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TraderLlamaController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TraderLlamaController.java new file mode 100644 index 000000000..a8cb412f9 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TraderLlamaController.java @@ -0,0 +1,240 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTraderLlama; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class TraderLlamaController extends MobEntityController { + public TraderLlamaController() { + super(EntityTraderLlamaNPC.class); + } + + @Override + public void create(Location at, NPC npc) { + npc.getOrAddTrait(HorseModifiers.class); + super.create(at, npc); + } + + @Override + public org.bukkit.entity.TraderLlama getBukkitEntity() { + return (org.bukkit.entity.TraderLlama) super.getBukkitEntity(); + } + + public static class EntityTraderLlamaNPC extends TraderLlama implements NPCHolder { + 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) { + ((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.isProtected(); + } + 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(); + } + setDespawnDelay(10); + NMS.setStepHeight(getBukkitEntity(), 1); + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TraderLlamaNPC extends CraftTraderLlama implements ForwardingNPCHolder { + public TraderLlamaNPC(EntityTraderLlamaNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TropicalFishController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TropicalFishController.java new file mode 100644 index 000000000..be8527f9e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TropicalFishController.java @@ -0,0 +1,260 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTropicalFish; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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.isProtected(); + } + 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 EntityMoveControl(this); + } + } + super.customServerAiStep(); + if (npc != null) { + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TropicalFishNPC extends CraftTropicalFish implements ForwardingNPCHolder { + public TropicalFishNPC(EntityTropicalFishNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TurtleController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TurtleController.java new file mode 100644 index 000000000..38b6cd08c --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/TurtleController.java @@ -0,0 +1,246 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTurtle; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.EntityMoveControl; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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) { + 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.isProtected(); + } + 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; + this.jumpControl = this.oldJumpController; + } + if (!npc.useMinecraftAI() && this.moveControl == this.oldMoveController) { + this.moveControl = new EntityMoveControl(this); + this.jumpControl = new EmptyControllerJump(this); + } + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + if (!NMSImpl.moveFish(npc, this, vec3d)) { + super.travel(vec3d); + } + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VexController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VexController.java new file mode 100644 index 000000000..f468b5b85 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VexController.java @@ -0,0 +1,179 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftVex; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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) { + setNoGravity(true); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class VexNPC extends CraftVex implements ForwardingNPCHolder { + public VexNPC(EntityVexNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VillagerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VillagerController.java new file mode 100644 index 000000000..91b919bfc --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VillagerController.java @@ -0,0 +1,263 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftVillager; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 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) { + getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.3); + } + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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(); + if (npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, true)) { + NMS.setPitch(getBukkitEntity(), 0); + } + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isTrading() { + if (blockingATrade) { + blockingATrade = false; + return true; + } + return super.isTrading(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public InteractionResult mobInteract(Player entityhuman, InteractionHand enumhand) { + if (npc != null && npc.data().get(NPC.Metadata.VILLAGER_BLOCK_TRADES, true)) { + 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) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class VillagerNPC extends CraftVillager implements ForwardingNPCHolder { + public VillagerNPC(EntityVillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VindicatorController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VindicatorController.java new file mode 100644 index 000000000..238ebdd2e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/VindicatorController.java @@ -0,0 +1,222 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftVindicator; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class VindicatorNPC extends CraftVindicator implements ForwardingNPCHolder { + public VindicatorNPC(EntityVindicatorNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WanderingTraderController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WanderingTraderController.java new file mode 100644 index 000000000..fa982e3ba --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WanderingTraderController.java @@ -0,0 +1,269 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWanderingTrader; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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) { + setDespawnDelay(10); + npc.update(); + } + } + + + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + public boolean isBlockingTrades() { + return blockTrades; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public boolean isTrading() { + if (blockingATrade) { + blockingATrade = false; + return true; + } + return super.isTrading(); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class WanderingTraderNPC extends CraftWanderingTrader implements ForwardingNPCHolder { + public WanderingTraderNPC(EntityWanderingTraderNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WardenController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WardenController.java new file mode 100644 index 000000000..7b16a0cb2 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WardenController.java @@ -0,0 +1,217 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWarden; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +import net.minecraft.util.Unit; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.memory.MemoryModuleType; +import net.minecraft.world.entity.monster.warden.Warden; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class WardenController extends MobEntityController { + public WardenController() { + super(EntityWardenNPC.class); + } + + @Override + public org.bukkit.entity.Warden getBukkitEntity() { + return (org.bukkit.entity.Warden) super.getBukkitEntity(); + } + + public static class EntityWardenNPC extends Warden implements NPCHolder { + private final CitizensNPC npc; + + public EntityWardenNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityWardenNPC(EntityType types, Level level, NPC npc) { + super(types, level); + this.npc = (CitizensNPC) npc; + this.getBrain().setMemoryWithExpiry(MemoryModuleType.DIG_COOLDOWN, Unit.INSTANCE, 1200L); + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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(); + return; + } + NMSImpl.updateMinecraftAIState(npc, this); + npc.update(); + if (npc.useMinecraftAI()) { + super.customServerAiStep(); + } + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @Override + public CraftEntity getBukkitEntity() { + if (npc != null && !(super.getBukkitEntity() instanceof NPCHolder)) { + NMSImpl.setBukkitEntity(this, new WardenNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + protected SoundEvent getDeathSound() { + return NMSImpl.getSoundEffect(npc, super.getDeathSound(), NPC.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class WardenNPC extends CraftWarden implements ForwardingNPCHolder { + public WardenNPC(EntityWardenNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitchController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitchController.java new file mode 100644 index 000000000..5f43822ea --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitchController.java @@ -0,0 +1,220 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWitch; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class WitchNPC extends CraftWitch implements ForwardingNPCHolder { + public WitchNPC(EntityWitchNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitherController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitherController.java new file mode 100644 index 000000000..cb5ce6c7e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WitherController.java @@ -0,0 +1,190 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWither; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 int getAlternativeTarget(int i) { + return npc == null ? super.getAlternativeTarget(i) : 0; + } + + @Override + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPowered() { + return npc == null || !npc.data().has("wither-arrow-shield") ? super.isPowered() + : npc.data().get("wither-arrow-shield"); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class WitherNPC extends CraftWither implements ForwardingNPCHolder { + public WitherNPC(EntityWitherNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WolfController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WolfController.java new file mode 100644 index 000000000..5f5927d25 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/WolfController.java @@ -0,0 +1,234 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWolf; +import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +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.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 { + 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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @Override + public boolean onClimbable() { + if (npc == null || !npc.isFlyable()) { + return super.onClimbable(); + } else { + return false; + } + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor datawatcherobject) { + if (npc == null) { + super.onSyncedDataUpdated(datawatcherobject); + return; + } + NMSImpl.checkAndUpdateHeight(this, datawatcherobject, super::onSyncedDataUpdated); + } + + @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 setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fire) { + return npc == null || this.equals(entityliving) ? super.setTarget(entityliving, reason, fire) : false; + } + + @Override + public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZoglinController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZoglinController.java new file mode 100644 index 000000000..02dfd251b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZoglinController.java @@ -0,0 +1,213 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftZoglin; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ZoglinNPC extends CraftZoglin implements ForwardingNPCHolder { + public ZoglinNPC(EntityZoglinNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieController.java new file mode 100644 index 000000000..52f10b7d5 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieController.java @@ -0,0 +1,211 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ZombieNPC extends CraftZombie implements ForwardingNPCHolder { + public ZombieNPC(EntityZombieNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieHuskController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieHuskController.java new file mode 100644 index 000000000..2c9eed96b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieHuskController.java @@ -0,0 +1,211 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftHusk; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 + protected SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + protected SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ZombieHuskNPC extends CraftHusk implements ForwardingNPCHolder { + public ZombieHuskNPC(EntityZombieHuskNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieVillagerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieVillagerController.java new file mode 100644 index 000000000..5a534593f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/ZombieVillagerController.java @@ -0,0 +1,212 @@ +package net.citizensnpcs.nms.v1_20_R1.entity; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftVillagerZombie; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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; + } + + @Override + protected boolean canRide(Entity entity) { + if (npc != null && (entity instanceof Boat || entity instanceof AbstractMinecart)) { + return !npc.isProtected(); + } + 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 SoundEvent getAmbientSound() { + return NMSImpl.getSoundEffect(npc, super.getAmbientSound(), NPC.Metadata.AMBIENT_SOUND); + } + + @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.Metadata.DEATH_SOUND); + } + + @Override + public SoundEvent getHurtSound(DamageSource damagesource) { + return NMSImpl.getSoundEffect(npc, super.getHurtSound(damagesource), NPC.Metadata.HURT_SOUND); + } + + @Override + public int getMaxFallDistance() { + return NMS.getFallDistance(npc, super.getMaxFallDistance()); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isLeashed() { + return NMSImpl.isLeashed(npc, super::isLeashed, this); + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + public void knockback(double strength, double dx, double dz) { + NMS.callKnockbackEvent(npc, (float) strength, dx, dz, (evt) -> super.knockback((float) evt.getStrength(), + evt.getKnockbackVector().getX(), evt.getKnockbackVector().getZ())); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void travel(Vec3 vec3d) { + if (npc == null || !npc.isFlyable()) { + super.travel(vec3d); + } else { + NMSImpl.flyingMoveLogic(this, vec3d); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ZombieVillagerNPC extends CraftVillagerZombie implements ForwardingNPCHolder { + public ZombieVillagerNPC(EntityZombieVillagerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/AreaEffectCloudController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/AreaEffectCloudController.java new file mode 100644 index 000000000..82c4ee291 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/AreaEffectCloudController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftAreaEffectCloud; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.AreaEffectCloud; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BlockDisplayController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BlockDisplayController.java new file mode 100644 index 000000000..76d3011a0 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BlockDisplayController.java @@ -0,0 +1,123 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftBlockDisplay; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Display.BlockDisplay; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class BlockDisplayController extends MobEntityController { + public BlockDisplayController() { + super(EntityBlockDisplayNPC.class); + } + + @Override + public org.bukkit.entity.BlockDisplay getBukkitEntity() { + return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity(); + } + + public static class BlockDisplayNPC extends CraftBlockDisplay implements ForwardingNPCHolder { + public BlockDisplayNPC(EntityBlockDisplayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityBlockDisplayNPC extends BlockDisplay implements NPCHolder { + private final CitizensNPC npc; + + public EntityBlockDisplayNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityBlockDisplayNPC(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 BlockDisplayNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BoatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BoatController.java new file mode 100644 index 000000000..824056e43 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/BoatController.java @@ -0,0 +1,258 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftBoat; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.FluidTags; +import net.minecraft.tags.TagKey; +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.Fluid; +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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; + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ChestBoatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ChestBoatController.java new file mode 100644 index 000000000..f9f752418 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ChestBoatController.java @@ -0,0 +1,259 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftChestBoat; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.FluidTags; +import net.minecraft.tags.TagKey; +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.entity.vehicle.ChestBoat; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public class ChestBoatController extends MobEntityController { + public ChestBoatController() { + super(EntityChestBoatNPC.class); + } + + @Override + public org.bukkit.entity.ChestBoat getBukkitEntity() { + return (org.bukkit.entity.ChestBoat) super.getBukkitEntity(); + } + + public static class ChestBoatNPC extends CraftChestBoat implements ForwardingNPCHolder { + public ChestBoatNPC(EntityChestBoatNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } + + public static class EntityChestBoatNPC extends ChestBoat 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 EntityChestBoatNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityChestBoatNPC(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 ChestBoatNPC(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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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; + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/DragonFireballController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/DragonFireballController.java new file mode 100644 index 000000000..ab31a22ee --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/DragonFireballController.java @@ -0,0 +1,136 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftDragonFireball; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EggController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EggController.java new file mode 100644 index 000000000..3b303503b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EggController.java @@ -0,0 +1,141 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEgg; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderCrystalController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderCrystalController.java new file mode 100644 index 000000000..94f8d3b6f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderCrystalController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEnderCrystal; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderPearlController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderPearlController.java new file mode 100644 index 000000000..2523d8476 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderPearlController.java @@ -0,0 +1,128 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEnderPearl; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.entity.EnderPearl; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderSignalController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderSignalController.java new file mode 100644 index 000000000..b71d28dce --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EnderSignalController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEnderSignal; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.entity.EnderSignal; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EvokerFangsController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EvokerFangsController.java new file mode 100644 index 000000000..7bf880682 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/EvokerFangsController.java @@ -0,0 +1,139 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_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_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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.level.material.Fluid; +import net.minecraft.world.phys.AABB; +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class EvokerFangsNPC extends CraftEvokerFangs implements ForwardingNPCHolder { + public EvokerFangsNPC(EntityEvokerFangsNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ExperienceOrbController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ExperienceOrbController.java new file mode 100644 index 000000000..716188a14 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ExperienceOrbController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftExperienceOrb; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ExperienceOrb; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ExperienceOrbNPC extends CraftExperienceOrb implements ForwardingNPCHolder { + public ExperienceOrbNPC(EntityExperienceOrbNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FallingBlockController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FallingBlockController.java new file mode 100644 index 000000000..6ff4dbedc --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FallingBlockController.java @@ -0,0 +1,166 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFallingBlock; +import org.bukkit.craftbukkit.v1_20_R1.util.CraftMagicNumbers; +import org.bukkit.entity.FallingBlock; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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.material.Fluid; +import net.minecraft.world.phys.AABB; +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 = CraftMagicNumbers.getBlock(npc.getItemProvider().get().getType()); + final EntityFallingBlockNPC handle = new EntityFallingBlockNPC(EntityType.FALLING_BLOCK, ws, npc); + handle.setPos(at.getX(), at.getY(), at.getZ()); + handle.setDeltaMovement(Vec3.ZERO); + NMSImpl.setFallingBlockState(handle, 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; + } + + @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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @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(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + + 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; + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FireworkController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FireworkController.java new file mode 100644 index 000000000..35d26b5b1 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FireworkController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftFirework; +import org.bukkit.entity.Firework; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class FireworkNPC extends CraftFirework implements ForwardingNPCHolder { + public FireworkNPC(EntityFireworkNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FishingHookController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FishingHookController.java new file mode 100644 index 000000000..fbe84d012 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/FishingHookController.java @@ -0,0 +1,159 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_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_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class FishingHookController extends MobEntityController { + public FishingHookController() { + super(EntityFishingHookNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + ServerLevel level = ((CraftWorld) at.getWorld()).getHandle(); + ServerPlayer sp = new ServerPlayer(level.getServer(), level, + new GameProfile(UUID.randomUUID(), "dummyfishhook")) { + }; + sp.setPos(at.getX(), at.getY(), at.getZ()); + sp.setYRot(at.getYaw()); + sp.setXRot(at.getPitch()); + sp.setHealth(20F); + sp.getInventory().items.set(sp.getInventory().selected, new ItemStack(Items.FISHING_ROD, 1)); + final EntityFishingHookNPC handle = new EntityFishingHookNPC(EntityType.FISHING_BOBBER, level, npc, sp); + return handle.getBukkitEntity(); + } + + @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, null); + } + + public EntityFishingHookNPC(EntityType types, Level level, NPC npc, ServerPlayer sp) { + super(sp, 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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + getPlayerOwner().unsetRemoved(); + NMSImpl.setLife(this, 0); + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class FishingHookNPC extends CraftFishHook implements ForwardingNPCHolder { + public FishingHookNPC(EntityFishingHookNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/GlowItemFrameController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/GlowItemFrameController.java new file mode 100644 index 000000000..4c004c361 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/GlowItemFrameController.java @@ -0,0 +1,150 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftGlowItemFrame; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ItemFrameController.EntityItemFrameNPC; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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.getBlockX(), at.getBlockY(), at.getBlockZ()); + 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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + 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; + setItem(npc.getItemProvider().get()); + } + + @Override + public NPC getNPC() { + return npc; + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/InteractionController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/InteractionController.java new file mode 100644 index 000000000..a1ff41806 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/InteractionController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftInteraction; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Interaction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class InteractionController extends MobEntityController { + public InteractionController() { + super(EntityInteractionNPC.class); + } + + @Override + public org.bukkit.entity.Interaction getBukkitEntity() { + return (org.bukkit.entity.Interaction) super.getBukkitEntity(); + } + + public static class EntityInteractionNPC extends Interaction implements NPCHolder { + private final CitizensNPC npc; + + public EntityInteractionNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityInteractionNPC(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 InteractionNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class InteractionNPC extends CraftInteraction implements ForwardingNPCHolder { + public InteractionNPC(EntityInteractionNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemController.java new file mode 100644 index 000000000..cdc2fdefd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemController.java @@ -0,0 +1,152 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftItem; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.entity.Item; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class ItemController extends AbstractEntityController { + public ItemController() { + super(EntityItemNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + final EntityItemNPC handle = new EntityItemNPC(((CraftWorld) at.getWorld()).getHandle(), npc, at.getX(), + at.getY(), at.getZ(), CraftItemStack.asNMSCopy(npc.getItemProvider().get())); + 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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + 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; + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemDisplayController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemDisplayController.java new file mode 100644 index 000000000..728bb7ba1 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemDisplayController.java @@ -0,0 +1,136 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftItemDisplay; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Display.ItemDisplay; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class ItemDisplayController extends MobEntityController { + public ItemDisplayController() { + super(EntityItemDisplayNPC.class); + } + + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + final EntityItemDisplayNPC handle = new EntityItemDisplayNPC(EntityType.ITEM_DISPLAY, + ((CraftWorld) at.getWorld()).getHandle(), npc); + if (npc != null) { + handle.setItemStack(CraftItemStack.asNMSCopy(npc.getItemProvider().get())); + } + return handle.getBukkitEntity(); + } + + @Override + public org.bukkit.entity.ItemDisplay getBukkitEntity() { + return (org.bukkit.entity.ItemDisplay) super.getBukkitEntity(); + } + + public static class EntityItemDisplayNPC extends ItemDisplay implements NPCHolder { + private final CitizensNPC npc; + + public EntityItemDisplayNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityItemDisplayNPC(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 ItemDisplayNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ItemDisplayNPC extends CraftItemDisplay implements ForwardingNPCHolder { + public ItemDisplayNPC(EntityItemDisplayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemFrameController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemFrameController.java new file mode 100644 index 000000000..eacfb11e7 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ItemFrameController.java @@ -0,0 +1,149 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftItemFrame; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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.getBlockX(), at.getBlockY(), at.getBlockZ()); + 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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + 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; + setItem(npc.getItemProvider().get()); + } + + @Override + public NPC getNPC() { + return npc; + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LargeFireballController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LargeFireballController.java new file mode 100644 index 000000000..eb42f4b6a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LargeFireballController.java @@ -0,0 +1,136 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLargeFireball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class LargeFireballNPC extends CraftLargeFireball implements ForwardingNPCHolder { + public LargeFireballNPC(EntityLargeFireballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LeashController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LeashController.java new file mode 100644 index 000000000..5bf5b2b45 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LeashController.java @@ -0,0 +1,130 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLeash; +import org.bukkit.entity.LeashHitch; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class LeashNPC extends CraftLeash implements ForwardingNPCHolder { + public LeashNPC(EntityLeashNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LlamaSpitController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LlamaSpitController.java new file mode 100644 index 000000000..685e68c7e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/LlamaSpitController.java @@ -0,0 +1,144 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftLlamaSpit; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_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.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class LlamaSpitNPC extends CraftLlamaSpit implements ForwardingNPCHolder { + public LlamaSpitNPC(EntityLlamaSpitNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MarkerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MarkerController.java new file mode 100644 index 000000000..cc2f0d972 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MarkerController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMarker; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Marker; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MarkerNPC extends CraftMarker implements ForwardingNPCHolder { + public MarkerNPC(EntityMarkerNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartChestController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartChestController.java new file mode 100644 index 000000000..cf355ff8a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartChestController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMinecartChest; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MinecartChestNPC extends CraftMinecartChest implements ForwardingNPCHolder { + public MinecartChestNPC(EntityMinecartChestNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartCommandController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartCommandController.java new file mode 100644 index 000000000..fe6935948 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartCommandController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMinecartCommand; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MinecartCommandNPC extends CraftMinecartCommand implements ForwardingNPCHolder { + public MinecartCommandNPC(EntityMinecartCommandNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartFurnaceController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartFurnaceController.java new file mode 100644 index 000000000..a495a307b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartFurnaceController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMinecartFurnace; +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MinecartFurnaceNPC extends CraftMinecartFurnace implements ForwardingNPCHolder { + public MinecartFurnaceNPC(EntityMinecartFurnaceNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartHopperController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartHopperController.java new file mode 100644 index 000000000..517af4a52 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartHopperController.java @@ -0,0 +1,106 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartRideableController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartRideableController.java new file mode 100644 index 000000000..73ec3d2ed --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartRideableController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftMinecartRideable; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class MinecartRideableNPC extends CraftMinecartRideable implements ForwardingNPCHolder { + public MinecartRideableNPC(EntityMinecartRideableNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartSpawnerController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartSpawnerController.java new file mode 100644 index 000000000..0a0784aa9 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartSpawnerController.java @@ -0,0 +1,106 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartTNTController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartTNTController.java new file mode 100644 index 000000000..a5eb7be1a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/MinecartTNTController.java @@ -0,0 +1,106 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.entity.Minecart; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + NMSImpl.minecartItemLogic(this); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/PaintingController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/PaintingController.java new file mode 100644 index 000000000..1817f4b2e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/PaintingController.java @@ -0,0 +1,129 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPainting; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class PaintingNPC extends CraftPainting implements ForwardingNPCHolder { + public PaintingNPC(EntityPaintingNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ShulkerBulletController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ShulkerBulletController.java new file mode 100644 index 000000000..f99c56bc4 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ShulkerBulletController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftShulkerBullet; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ShulkerBulletNPC extends CraftShulkerBullet implements ForwardingNPCHolder { + public ShulkerBulletNPC(EntityShulkerBulletNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SmallFireballController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SmallFireballController.java new file mode 100644 index 000000000..f646bbd02 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SmallFireballController.java @@ -0,0 +1,127 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSmallFireball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SmallFireballNPC extends CraftSmallFireball implements ForwardingNPCHolder { + public SmallFireballNPC(EntitySmallFireballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SnowballController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SnowballController.java new file mode 100644 index 000000000..11a9772bb --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SnowballController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftSnowball; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SnowballNPC extends CraftSnowball implements ForwardingNPCHolder { + public SnowballNPC(EntitySnowballNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SpectralArrowController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SpectralArrowController.java new file mode 100644 index 000000000..fa2d6a0c3 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/SpectralArrowController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftArrow; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.entity.Arrow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class SpectralArrowNPC extends CraftArrow implements ForwardingNPCHolder { + public SpectralArrowNPC(EntitySpectralArrowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TNTPrimedController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TNTPrimedController.java new file mode 100644 index 000000000..190766307 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TNTPrimedController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTNTPrimed; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TNTPrimedNPC extends CraftTNTPrimed implements ForwardingNPCHolder { + public TNTPrimedNPC(EntityTNTPrimedNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TextDisplayController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TextDisplayController.java new file mode 100644 index 000000000..96351a996 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TextDisplayController.java @@ -0,0 +1,123 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTextDisplay; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +import net.minecraft.world.entity.Display.TextDisplay; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +public class TextDisplayController extends MobEntityController { + public TextDisplayController() { + super(EntityTextDisplayNPC.class); + } + + @Override + public org.bukkit.entity.TextDisplay getBukkitEntity() { + return (org.bukkit.entity.TextDisplay) super.getBukkitEntity(); + } + + public static class EntityTextDisplayNPC extends TextDisplay implements NPCHolder { + private final CitizensNPC npc; + + public EntityTextDisplayNPC(EntityType types, Level level) { + this(types, level, null); + } + + public EntityTextDisplayNPC(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 TextDisplayNPC(this)); + } + return super.getBukkitEntity(); + } + + @Override + public NPC getNPC() { + return npc; + } + + @Override + public boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + super.tick(); + if (npc != null) { + npc.update(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TextDisplayNPC extends CraftTextDisplay implements ForwardingNPCHolder { + public TextDisplayNPC(EntityTextDisplayNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownExpBottleController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownExpBottleController.java new file mode 100644 index 000000000..7e974381b --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownExpBottleController.java @@ -0,0 +1,128 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftThrownExpBottle; +import org.bukkit.entity.ThrownExpBottle; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + if (!npc.isProtected()) { + super.tick(); + } + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ThrownExpBottleNPC extends CraftThrownExpBottle implements ForwardingNPCHolder { + public ThrownExpBottleNPC(EntityThrownExpBottleNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownPotionController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownPotionController.java new file mode 100644 index 000000000..2e2c4bb4e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownPotionController.java @@ -0,0 +1,143 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftThrownPotion; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownTridentController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownTridentController.java new file mode 100644 index 000000000..f398df610 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/ThrownTridentController.java @@ -0,0 +1,125 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTrident; +import org.bukkit.entity.Trident; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class ThrownTridentNPC extends CraftTrident implements ForwardingNPCHolder { + public ThrownTridentNPC(EntityThrownTridentNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TippedArrowController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TippedArrowController.java new file mode 100644 index 000000000..9fe494b64 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/TippedArrowController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftTippedArrow; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class TippedArrowNPC extends CraftTippedArrow implements ForwardingNPCHolder { + public TippedArrowNPC(EntityTippedArrowNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/WitherSkullController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/WitherSkullController.java new file mode 100644 index 000000000..a2faa18c7 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/nonliving/WitherSkullController.java @@ -0,0 +1,124 @@ +package net.citizensnpcs.nms.v1_20_R1.entity.nonliving; + +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWitherSkull; +import org.bukkit.util.Vector; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.MobEntityController; +import net.citizensnpcs.nms.v1_20_R1.util.ForwardingNPCHolder; +import net.citizensnpcs.nms.v1_20_R1.util.NMSBoundingBox; +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.citizensnpcs.npc.CitizensNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.Util; +import net.minecraft.core.PositionImpl; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.TagKey; +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; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.phys.AABB; + +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 boolean isPushable() { + return npc == null ? super.isPushable() + : npc.data(). get(NPC.Metadata.COLLIDABLE, !npc.isProtected()); + } + + @Override + protected AABB makeBoundingBox() { + return NMSBoundingBox.makeBB(npc, super.makeBoundingBox()); + } + + @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 Entity teleportTo(ServerLevel worldserver, PositionImpl location) { + if (npc == null) + return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); + } + + @Override + public void tick() { + if (npc != null) { + npc.update(); + } else { + super.tick(); + } + } + + @Override + public boolean updateFluidHeightAndDoFluidPushing(TagKey tagkey, double d0) { + return NMSImpl.fluidPush(npc, this, () -> super.updateFluidHeightAndDoFluidPushing(tagkey, d0)); + } + } + + public static class WitherSkullNPC extends CraftWitherSkull implements ForwardingNPCHolder { + public WitherSkullNPC(EntityWitherSkullNPC entity) { + super((CraftServer) Bukkit.getServer(), entity); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetHandler.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetHandler.java new file mode 100644 index 000000000..a6eca6bad --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetHandler.java @@ -0,0 +1,17 @@ +package net.citizensnpcs.nms.v1_20_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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetworkManager.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetworkManager.java new file mode 100644 index 000000000..c1a989388 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/network/EmptyNetworkManager.java @@ -0,0 +1,25 @@ +package net.citizensnpcs.nms.v1_20_R1.network; + +import java.io.IOException; + +import net.citizensnpcs.nms.v1_20_R1.util.NMSImpl; +import net.minecraft.network.Connection; +import net.minecraft.network.PacketSendListener; +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, PacketSendListener genericfuturelistener) { + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensBlockBreaker.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensBlockBreaker.java new file mode 100644 index 000000000..9de5208c6 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensBlockBreaker.java @@ -0,0 +1,99 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; + +import net.citizensnpcs.util.AbstractBlockBreaker; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +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.state.BlockState; + +public class CitizensBlockBreaker extends AbstractBlockBreaker { + public CitizensBlockBreaker(org.bukkit.entity.Entity entity, org.bukkit.block.Block target, + BlockBreakerConfiguration config) { + super(entity, target, config); + } + + private ItemStack getCurrentItem() { + return configuration.item() != null ? CraftItemStack.asNMSCopy(configuration.item()) + : getHandle() instanceof LivingEntity ? ((LivingEntity) getHandle()).getMainHandItem() : null; + } + + @Override + protected float getDamage(int tickDifference) { + return getStrength(getHandle().level().getBlockState(new BlockPos(x, y, z))) * (tickDifference + 1) + * configuration.blockStrengthModifier(); + } + + private Entity getHandle() { + return NMSImpl.getHandle(entity); + } + + protected 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 + protected void setBlockDamage(int modifiedDamage) { + ((ServerLevel) getHandle().level()).destroyBlockProgress(getHandle().getId(), new BlockPos(x, y, z), + modifiedDamage); + } + + private float strengthMod(BlockState block) { + ItemStack itemstack = getCurrentItem(); + float f = itemstack.getDestroySpeed(block); + if (getHandle() instanceof LivingEntity) { + LivingEntity handle = (LivingEntity) getHandle(); + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java new file mode 100644 index 000000000..661fbcb3f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java @@ -0,0 +1,151 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.lang.invoke.MethodHandle; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; + +import com.google.common.collect.ForwardingSet; + +import net.citizensnpcs.Settings.Setting; +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.event.NPCSeenByPlayerEvent; +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.nms.v1_20_R1.entity.EntityHumanNPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.citizensnpcs.util.NMS; +import net.citizensnpcs.util.Util; +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.server.network.ServerPlayerConnection; +import net.minecraft.world.entity.Entity; + +public class CitizensEntityTracker extends ChunkMap.TrackedEntity { + private final Entity tracker; + + public CitizensEntityTracker(ChunkMap map, Entity entity, int i, int j, boolean flag) { + map.super(entity, i, j, flag); + this.tracker = entity; + try { + Set set = (Set) TRACKING_SET_GETTER.invoke(this); + TRACKING_SET_SETTER.invoke(this, new ForwardingSet() { + @Override + public boolean add(ServerPlayerConnection conn) { + boolean res = super.add(conn); + if (res) { + updateLastPlayer(conn.getPlayer()); + } + return res; + } + + @Override + protected Set delegate() { + return set; + } + }); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public CitizensEntityTracker(ChunkMap map, TrackedEntity entry) { + this(map, getTracker(entry), getTrackingDistance(entry), getE(entry), getF(entry)); + } + + public void updateLastPlayer(ServerPlayer lastUpdatedPlayer) { + if (tracker.isRemoved() || tracker.getBukkitEntity().getType() != EntityType.PLAYER) + return; + final ServerPlayer entityplayer = lastUpdatedPlayer; + boolean sendTabRemove = NMS.sendTabListAdd(entityplayer.getBukkitEntity(), (Player) tracker.getBukkitEntity()); + if (!sendTabRemove || !Setting.DISABLE_TABLIST.asBoolean()) { + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), + () -> NMSImpl.sendPacket(entityplayer.getBukkitEntity(), new ClientboundAnimatePacket(tracker, 0)), + 1); + return; + } + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + NMSImpl.sendPacket(entityplayer.getBukkitEntity(), new ClientboundAnimatePacket(tracker, 0)); + NMS.sendTabListRemove(entityplayer.getBukkitEntity(), (Player) tracker.getBukkitEntity()); + }, Setting.TABLIST_REMOVE_PACKET_DELAY.asTicks()); + } + + @Override + public void updatePlayer(final ServerPlayer entityplayer) { + if (entityplayer instanceof EntityHumanNPC) + return; + + if (tracker instanceof NPCHolder) { + NPC npc = ((NPCHolder) tracker).getNPC(); + if (REQUIRES_SYNC == null) { + REQUIRES_SYNC = !Bukkit.isPrimaryThread(); + } + NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); + Util.callEventPossiblySync(event, REQUIRES_SYNC); + if (event.isCancelled()) + return; + Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); + if (TRACKING_RANGE_SETTER != null && trackingRange != null + && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + try { + TRACKING_RANGE_SETTER.invoke(this, trackingRange); + npc.data().set("last-tracking-range", trackingRange); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + 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_RANGE.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 Boolean REQUIRES_SYNC; + private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); + private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); + private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); + private static final MethodHandle TRACKING_RANGE_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, int.class); + private static final MethodHandle TRACKING_SET_GETTER = NMS.getFirstGetter(TrackedEntity.class, Set.class); + private static final MethodHandle TRACKING_SET_SETTER = NMS.getFirstFinalSetter(TrackedEntity.class, Set.class); +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CustomEntityRegistry.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CustomEntityRegistry.java new file mode 100644 index 000000000..6fe033b29 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CustomEntityRegistry.java @@ -0,0 +1,477 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.lang.invoke.MethodHandle; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; +import java.util.function.Supplier; +import java.util.stream.Stream; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; +import com.mojang.datafixers.util.Pair; +import com.mojang.serialization.Lifecycle; + +import net.citizensnpcs.util.NMS; +import net.minecraft.core.DefaultedMappedRegistry; +import net.minecraft.core.DefaultedRegistry; +import net.minecraft.core.Holder; +import net.minecraft.core.Holder.Reference; +import net.minecraft.core.HolderGetter; +import net.minecraft.core.HolderLookup.RegistryLookup; +import net.minecraft.core.HolderOwner; +import net.minecraft.core.HolderSet.Named; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.AreaEffectCloud; +import net.minecraft.world.entity.Display; +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.allay.Allay; +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import net.minecraft.world.entity.animal.camel.Camel; +import net.minecraft.world.entity.animal.frog.Frog; +import net.minecraft.world.entity.animal.frog.Tadpole; +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.animal.sniffer.Sniffer; +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.monster.warden.Warden; +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.ChestBoat; +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 DefaultedMappedRegistry> + implements Supplier>> { + private final BiMap entities = HashBiMap.create(); + private final BiMap entityClasses = this.entities.inverse(); + private final Map entityIds = Maps.newHashMap(); + private final MappedRegistry> wrapped; + + public CustomEntityRegistry(DefaultedRegistry> original) throws Throwable { + super(original.getDefaultKey().getNamespace(), + (ResourceKey>>) IREGISTRY_RESOURCE_KEY.invoke(original), + (Lifecycle) IREGISTRY_LIFECYCLE.invoke(original), true); + this.wrapped = (MappedRegistry>) original; + } + + @Override + public RegistryLookup> asLookup() { + return wrapped.asLookup(); + } + + @Override + public void bindTags(Map>, List>>> map) { + wrapped.bindTags(map); + } + + @Override + public EntityType byId(int var0) { + return this.wrapped.byId(var0); + } + + @Override + public EntityType byIdOrThrow(int var0) { + return this.wrapped.byIdOrThrow(var0); + } + + @Override + public boolean containsKey(ResourceKey> var0) { + return this.wrapped.containsKey(var0); + } + + @Override + public boolean containsKey(ResourceLocation var0) { + return this.wrapped.containsKey(var0); + } + + @Override + public HolderGetter> createRegistrationLookup() { + return wrapped.createRegistrationLookup(); + } + + @Override + public Set>, EntityType>> entrySet() { + return wrapped.entrySet(); + } + + public EntityType findType(Class search) { + return minecraftClassMap.inverse().get(search); + } + + @Override + public MappedRegistry> get() { + return wrapped; + } + + @Override + public EntityType get(ResourceKey> key) { + return wrapped.get(key); + } + + @Override + public EntityType get(ResourceLocation key) { + if (entities.containsKey(key)) { + return entities.get(key); + } + return wrapped.get(key); + } + + @Override + public Optional>> getHolder(int var0) { + return this.wrapped.getHolder(var0); + } + + @Override + public Optional>> getHolder(ResourceKey> var0) { + return this.wrapped.getHolder(var0); + } + + @Override + public int getId(EntityType key) { + if (entityIds.containsKey(key)) { + return entityIds.get(key); + } + return wrapped.getId(key); + } + + @Override + public ResourceLocation getKey(EntityType value) { + if (entityClasses.containsKey(value)) { + return entityClasses.get(value); + } + return wrapped.getKey(value); + } + + @Override + public Optional> getOptional(ResourceKey> var0) { + return this.wrapped.getOptional(var0); + } + + @Override + public Optional> getOptional(ResourceLocation var0) { + if (entities.containsKey(var0)) { + return Optional.of(entities.get(var0)); + } + return this.wrapped.getOptional(var0); + } + + @Override + public Optional>> getRandom(RandomSource paramRandom) { + return wrapped.getRandom(paramRandom); + } + + @Override + public Optional>> getResourceKey(EntityType var0) { + return wrapped.getResourceKey(var0); + } + + @Override + public Optional>> getTag(TagKey> var0) { + return this.wrapped.getTag(var0); + } + + @Override + public Stream>> getTagNames() { + return wrapped.getTagNames(); + } + + @Override + public Stream>, Named>>> getTags() { + return wrapped.getTags(); + } + + @Override + public HolderOwner> holderOwner() { + return wrapped.holderOwner(); + } + + @Override + public Stream>> holders() { + return wrapped.holders(); + } + + @Override + public boolean isEmpty() { + return wrapped.isEmpty(); + } + + @Override + public Iterator> iterator() { + return wrapped.iterator(); + } + + @Override + public Set keySet() { + return wrapped.keySet(); + } + + @Override + public Lifecycle lifecycle(EntityType type) { + return wrapped.lifecycle(type); + } + + public void put(int entityId, ResourceLocation key, EntityType entityClass) { + entities.put(key, entityClass); + entityIds.put(entityClass, entityId); + } + + @Override + public Set>> registryKeySet() { + return wrapped.registryKeySet(); + } + + @Override + public void resetTags() { + wrapped.resetTags(); + } + + @Override + public int size() { + return wrapped.size(); + } + + private static final MethodHandle IREGISTRY_LIFECYCLE = NMS.getFirstGetter(MappedRegistry.class, Lifecycle.class); + // replace regex .*?> ([A-Z_]+).*?of\((.*?)::new.*?$ minecraftClassMap.put(EntityType.\1, \2.class); + private static final MethodHandle IREGISTRY_RESOURCE_KEY = NMS.getFirstGetter(MappedRegistry.class, + ResourceKey.class); + private static final BiMap> minecraftClassMap = HashBiMap.create(); + static { + minecraftClassMap.put(EntityType.ALLAY, Allay.class); + 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.CHEST_BOAT, ChestBoat.class); + minecraftClassMap.put(EntityType.CAT, Cat.class); + minecraftClassMap.put(EntityType.CAMEL, Camel.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.FROG, Frog.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.SNIFFER, Sniffer.class); + minecraftClassMap.put(EntityType.BLOCK_DISPLAY, Display.BlockDisplay.class); + minecraftClassMap.put(EntityType.ITEM_DISPLAY, Display.ItemDisplay.class); + minecraftClassMap.put(EntityType.TEXT_DISPLAY, Display.TextDisplay.class); + minecraftClassMap.put(EntityType.INTERACTION, net.minecraft.world.entity.Interaction.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.TADPOLE, Tadpole.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.WARDEN, Warden.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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyAdvancementDataPlayer.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyAdvancementDataPlayer.java new file mode 100644 index 000000000..e7ac4d7ea --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyAdvancementDataPlayer.java @@ -0,0 +1,77 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.io.File; +import java.lang.invoke.MethodHandle; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.mojang.datafixers.DataFixer; + +import net.citizensnpcs.api.CitizensAPI; +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, CitizensAPI.getDataFolder().toPath(), 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(); + try { + ((Map) PROGRESS.invoke(data)).clear(); + for (MethodHandle handle : SETS) { + ((Set) handle.invoke(data)).clear(); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static final MethodHandle PROGRESS = NMS.getFirstGetter(PlayerAdvancements.class, Map.class); + private static final List SETS = NMS.getFieldsOfType(PlayerAdvancements.class, Set.class); +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyServerStatsCounter.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyServerStatsCounter.java new file mode 100644 index 000000000..cb694acfb --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EmptyServerStatsCounter.java @@ -0,0 +1,42 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import com.mojang.datafixers.DataFixer; + +import net.citizensnpcs.api.CitizensAPI; +import net.minecraft.SharedConstants; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.ServerStatsCounter; +import net.minecraft.stats.Stat; +import net.minecraft.world.entity.player.Player; + +public class EmptyServerStatsCounter extends ServerStatsCounter { + public EmptyServerStatsCounter() { + super(null, CitizensAPI.getDataFolder()); + } + + @Override + public void markAllDirty() { + } + + @Override + public void parseLocal(DataFixer datafixer, String s) { + } + + @Override + public void save() { + } + + @Override + public void sendStats(ServerPlayer entityplayer) { + } + + @Override + public void setValue(Player entityhuman, Stat statistic, int i) { + } + + @Override + protected String toJson() { + return "{\"stats\":{},\"DataVersion\":" + + Integer.valueOf(SharedConstants.getCurrentVersion().getDataVersion().getVersion()) + "}"; + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityJumpControl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityJumpControl.java new file mode 100644 index 000000000..9936b1736 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityJumpControl.java @@ -0,0 +1,27 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.control.JumpControl; +import net.minecraft.world.entity.monster.Slime; + +public class EntityJumpControl extends JumpControl { + private boolean a; + private final LivingEntity b; + + public EntityJumpControl(LivingEntity entity) { + super(new Slime(EntityType.SLIME, entity.level())); + this.b = entity; + } + + @Override + public void jump() { + this.a = true; + } + + @Override + public void tick() { + this.b.setJumping(this.a); + this.a = false; + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityMoveControl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityMoveControl.java new file mode 100644 index 000000000..74b1a3d4f --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityMoveControl.java @@ -0,0 +1,126 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.Random; + +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.Attributes; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.monster.Slime; + +public class EntityMoveControl extends MoveControl { + protected LivingEntity entity; + private int jumpTicks; + protected boolean moving; + protected double speedMod; + protected double tx; + protected double ty; + protected double tz; + + public EntityMoveControl(LivingEntity entityinsentient) { + super(entityinsentient instanceof Mob ? (Mob) entityinsentient + : new Slime(EntityType.SLIME, entityinsentient.level())); + this.entity = entityinsentient; + this.tx = entityinsentient.getX(); + this.ty = entityinsentient.getY(); + this.tz = entityinsentient.getZ(); + } + + @Override + public double getSpeedModifier() { + return this.speedMod; + } + + @Override + public double getWantedX() { + return this.tx; + } + + @Override + public double getWantedY() { + return this.ty; + } + + @Override + public double getWantedZ() { + return this.tz; + } + + @Override + public boolean hasWanted() { + return this.moving; + } + + protected int jumpTicks() { + return new Random().nextInt(20) + 10; + } + + @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.tx = d0; + this.ty = d1; + this.tz = d2; + this.speedMod = d3; + this.moving = true; + } + + private boolean shouldJump() { + if (!(this.entity instanceof Slime)) + return false; + + if (this.jumpTicks-- <= 0) + return true; + + return false; + } + + @Override + public void tick() { + this.entity.zza = 0; + if (this.moving) { + this.moving = false; + double dX = this.tx - this.entity.getX(); + double dZ = this.tz - this.entity.getZ(); + double dY = this.ty - this.entity.getY(); + double dXZ = Math.sqrt(dX * dX + dZ * dZ); + if (Math.abs(dY) < 1.0 && dXZ < 0.01) { + // this.entity.zza = 0.0F; + return; + } + if (dXZ > 0.4) { + float f = (float) Math.toDegrees(Mth.atan2(dZ, dX)) - 90.0F; + this.entity.setYRot(rotlerp(this.entity.getYRot(), f, 90.0F)); + NMS.setHeadYaw(entity.getBukkitEntity(), this.entity.getYRot()); + } + float movement = (float) (this.speedMod * this.entity.getAttribute(Attributes.MOVEMENT_SPEED).getValue()); + this.entity.setSpeed(movement); + this.entity.zza = movement; + if (shouldJump() || (dY >= NMS.getStepHeight(entity.getBukkitEntity()) && dXZ < 0.4D)) { + this.jumpTicks = jumpTicks(); + this.jumpTicks /= 3; + entity.setJumping(true); + } + } + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNavigation.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNavigation.java new file mode 100644 index 000000000..5eabc706a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNavigation.java @@ -0,0 +1,538 @@ +package net.citizensnpcs.nms.v1_20_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.Settings; +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.LivingEntity; +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.entity.monster.Slime; +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.PathFinder; +import net.minecraft.world.phys.Vec3; + +public class EntityNavigation 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 float maxDistanceToWaypoint = 0.5F; + private float maxVisitedNodesMultiplier = 1.0F; + private final LivingEntity mob; + private final MobAI mvmt; + protected EntityNodeEvaluator nodeEvaluator; + protected Path path; + private final EntityPathfinder 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 EntityNavigation(LivingEntity entityinsentient, Level world) { + super(new Slime(EntityType.SLIME, world), world); + this.mob = entityinsentient; + this.mvmt = MobAI.from(entityinsentient); + this.followRange = entityinsentient.getAttribute(Attributes.FOLLOW_RANGE); + this.nodeEvaluator = new EntityNodeEvaluator(); + this.nodeEvaluator.setCanPassDoors(true); + this.pathFinder = new EntityPathfinder(this.nodeEvaluator, Settings.Setting.MAXIMUM_VISITED_NODES.asInt()); + this.setRange(24); + } + + @Override + public boolean canCutCorner(BlockPathTypes pathtype) { + return (pathtype != BlockPathTypes.DANGER_FIRE && pathtype != BlockPathTypes.DANGER_POWDER_SNOW + && pathtype != BlockPathTypes.DANGER_OTHER && pathtype != BlockPathTypes.WALKABLE_DOOR); + } + + @Override + public boolean canFloat() { + return this.nodeEvaluator.canFloat(); + } + + @Override + protected boolean canMoveDirectly(Vec3 var0, Vec3 var1) { + return false; + /* + 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.onGround() || isInLiquid() || this.mob.isPassenger()); + } + + @Override + public Path createPath(BlockPos var0, int var1) { + BlockPos var2; + if (this.level.getBlockState(var0).isAir()) { + for (var2 = var0.below(); var2.getY() > this.level.getMinBuildHeight() + && this.level.getBlockState(var2).isAir(); var2 = var2.below()) { + } + + if (var2.getY() > this.level.getMinBuildHeight()) { + return supercreatePath(var2.above(), var1); + } + + while (var2.getY() < this.level.getMaxBuildHeight() && this.level.getBlockState(var2).isAir()) { + var2 = var2.above(); + } + + var0 = var2; + } + + if (!this.level.getBlockState(var0).isSolid()) { + return supercreatePath(var0, var1); + } else { + for (var2 = var0.above(); var2.getY() < this.level.getMaxBuildHeight() + && this.level.getBlockState(var2).isSolid(); var2 = var2.above()) { + } + + return supercreatePath(var2, 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() || (this.mob.getY() < this.level.getMinBuildHeight()) || !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().above() : this.mob.blockPosition(); + int var6 = (int) (var4 + var1); + PathNavigationRegion var7 = new PathNavigationRegion(this.level, var5.offset(-var6, -var6, -var6), + var5.offset(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; + this.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 || (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; + } + + public Path getPathEntity() { + return this.path; + } + + private int getSurfaceY() { + if (this.mob.isInWater() && this.canFloat()) { + int var0 = this.mob.getBlockY(); + BlockState var1 = this.level.getBlockState(BlockPos.containing(this.mob.getX(), var0, this.mob.getZ())); + int var2 = 0; + + do { + if (!var1.is(Blocks.WATER)) { + return var0; + } + + ++var0; + var1 = this.level.getBlockState(BlockPos.containing(this.mob.getX(), var0, this.mob.getZ())); + ++var2; + } while (var2 <= 16); + + return this.mob.getBlockY(); + } else { + return Mth.floor(this.mob.getY() + 0.5); + } + } + + @Override + public BlockPos getTargetPos() { + return this.targetPos; + } + + @Override + protected Vec3 getTempMobPos() { + return new Vec3(this.mob.getX(), getSurfaceY(), this.mob.getZ()); + } + + protected boolean hasValidPathType(BlockPathTypes var0) { + if (var0 == BlockPathTypes.WATER) { + return false; + } else if (var0 == BlockPathTypes.LAVA) { + return false; + } else { + return var0 != BlockPathTypes.OPEN; + } + } + + @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.below(); + 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(BlockPos.containing(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 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; + } + + @Override + public boolean shouldRecomputePath(BlockPos var0) { + if (this.hasDelayedRecomputation) { + return false; + } else if (this.path != null && !this.path.isDone() && this.path.getNodeCount() != 0) { + 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); + return var0.closerToCenterThan(var2, this.path.getNodeCount() - this.path.getNextNodeIndex()); + } else { + return false; + } + } + + 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.onGround() && 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); + mvmt.getMoveControl().setWantedPosition(var0.x, this.getGroundY(var0), var0.z, this.speedModifier); + } + + private void timeoutPath() { + resetStuckTimeout(); + stop(); + } + + @Override + protected void trimPath() { + supertrimPath(); + if (this.avoidSun) { + if (this.level.canSeeSky(BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, 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; + } + } + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluator.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluator.java new file mode 100644 index 000000000..054bcecec --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluator.java @@ -0,0 +1,624 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.EnumSet; +import java.util.Iterator; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanMap; +import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.Direction.Axis; +import net.minecraft.tags.BlockTags; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.PathNavigationRegion; +import net.minecraft.world.level.block.BaseRailBlock; +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.LeavesBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +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 EntityNodeEvaluator extends EntityNodeEvaluatorBase { + private final Object2BooleanMap collisionCache = new Object2BooleanOpenHashMap(); + protected float oldWaterCost; + private final Long2ObjectMap pathTypesByPosCache = new Long2ObjectOpenHashMap(); + + private boolean canReachWithoutCollision(Node var0) { + AABB var1 = this.mob.getBoundingBox(); + Vec3 var2 = new Vec3(var0.x - this.mob.getX() + var1.getXsize() / 2.0, + var0.y - this.mob.getY() + var1.getYsize() / 2.0, var0.z - this.mob.getZ() + var1.getZsize() / 2.0); + int var3 = Mth.ceil(var2.length() / var1.getSize()); + var2 = var2.scale(1.0F / var3); + + for (int var4 = 1; var4 <= var3; ++var4) { + var1 = var1.move(var2); + if (this.hasCollisions(var1)) { + return false; + } + } + + return true; + } + + protected boolean canStartAt(BlockPos var0) { + BlockPathTypes var1 = this.getBlockPathType(this.mob, var0); + return var1 != BlockPathTypes.OPEN && this.mvmt.getPathfindingMalus(var1) >= 0.0F; + } + + @Override + public void done() { + this.mvmt.setPathfindingMalus(BlockPathTypes.WATER, this.oldWaterCost); + this.pathTypesByPosCache.clear(); + this.collisionCache.clear(); + super.done(); + } + + protected BlockPathTypes evaluateBlockPathType(BlockGetter var0, BlockPos var1, BlockPathTypes var2) { + boolean var3 = this.canPassDoors(); + if (var2 == BlockPathTypes.DOOR_WOOD_CLOSED && this.canOpenDoors() && var3) { + var2 = BlockPathTypes.WALKABLE_DOOR; + } + + if (var2 == BlockPathTypes.DOOR_OPEN && !var3) { + var2 = BlockPathTypes.BLOCKED; + } + + if (var2 == BlockPathTypes.RAIL && !(var0.getBlockState(var1).getBlock() instanceof BaseRailBlock) + && !(var0.getBlockState(var1.below()).getBlock() instanceof BaseRailBlock)) { + var2 = BlockPathTypes.UNPASSABLE_RAIL; + } + + return var2; + } + + 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 = this.getFloorLevel(var9.set(var0, var1, var2)); + if (var10 - var4 > this.getMobJumpHeight()) { + return null; + } else { + BlockPathTypes var12 = this.getCachedBlockType(this.mob, var0, var1, var2); + float var13 = this.mvmt.getPathfindingMalus(var12); + double var14 = this.mob.getBbWidth() / 2.0; + if (var13 >= 0.0F) { + var8 = this.getNodeAndUpdateCostToMax(var0, var1, var2, var12, var13); + } + + if (doesBlockHavePartialCollision(var7) && var8 != null && var8.costMalus >= 0.0F + && !this.canReachWithoutCollision(var8)) { + var8 = null; + } + + if (var12 == BlockPathTypes.WALKABLE || this.isAmphibious() && var12 == BlockPathTypes.WATER) { + return var8; + } else { + if ((var8 == null || var8.costMalus < 0.0F) && var3 > 0 + && (var12 != BlockPathTypes.FENCE || this.canWalkOverFences()) + && var12 != BlockPathTypes.UNPASSABLE_RAIL && var12 != BlockPathTypes.TRAPDOOR + && var12 != BlockPathTypes.POWDER_SNOW) { + var8 = this.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.5; + double var18 = var2 - var6.getStepZ() + 0.5; + AABB var20 = new AABB(var16 - var14, + this.getFloorLevel(var9.set(var16, var1 + 1, var18)) + 0.001, var18 - var14, + var16 + var14, + this.mob.getBbHeight() + this + .getFloorLevel(var9.set((double) var8.x, (double) var8.y, (double) var8.z)) + - 0.002, + var18 + var14); + if (this.hasCollisions(var20)) { + var8 = null; + } + } + } + + if (!this.isAmphibious() && var12 == BlockPathTypes.WATER && !this.canFloat()) { + if (this.getCachedBlockType(this.mob, var0, var1 - 1, var2) != BlockPathTypes.WATER) { + return var8; + } + + while (var1 > this.mob.level().getMinBuildHeight()) { + --var1; + var12 = this.getCachedBlockType(this.mob, var0, var1, var2); + if (var12 != BlockPathTypes.WATER) { + return var8; + } + + var8 = this.getNodeAndUpdateCostToMax(var0, var1, var2, var12, + this.mvmt.getPathfindingMalus(var12)); + } + } + + if (var12 == BlockPathTypes.OPEN) { + int var16 = 0; + int var17 = var1; + + while (var12 == BlockPathTypes.OPEN) { + --var1; + if (var1 < this.mob.level().getMinBuildHeight()) { + return this.getBlockedNode(var0, var17, var2); + } + + if (var16++ >= this.mob.getMaxFallDistance()) { + return this.getBlockedNode(var0, var1, var2); + } + + var12 = this.getCachedBlockType(this.mob, var0, var1, var2); + var13 = this.mvmt.getPathfindingMalus(var12); + if (var12 != BlockPathTypes.OPEN && var13 >= 0.0F) { + var8 = this.getNodeAndUpdateCostToMax(var0, var1, var2, var12, var13); + break; + } + + if (var13 < 0.0F) { + return this.getBlockedNode(var0, var1, var2); + } + } + } + + if (doesBlockHavePartialCollision(var12) && var8 == null) { + var8 = this.getNode(var0, var1, var2); + var8.closed = true; + var8.type = var12; + var8.costMalus = var12.getMalus(); + } + + return var8; + } + } + } + + private Node getBlockedNode(int var0, int var1, int var2) { + Node var3 = this.getNode(var0, var1, var2); + var3.type = BlockPathTypes.BLOCKED; + var3.costMalus = -1.0F; + return var3; + } + + @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, LivingEntity var4) { + EnumSet var5 = EnumSet.noneOf(BlockPathTypes.class); + BlockPathTypes var6 = BlockPathTypes.BLOCKED; + var6 = this.getBlockPathTypes(var0, var1, var2, var3, var5, var6, var4.blockPosition()); + if (var5.contains(BlockPathTypes.FENCE)) { + return BlockPathTypes.FENCE; + } else if (var5.contains(BlockPathTypes.UNPASSABLE_RAIL)) { + return BlockPathTypes.UNPASSABLE_RAIL; + } else { + BlockPathTypes var7 = BlockPathTypes.BLOCKED; + Iterator var9 = var5.iterator(); + + while (var9.hasNext()) { + BlockPathTypes varr9 = (BlockPathTypes) var9.next(); + if (mvmt.getPathfindingMalus(varr9) < 0.0F) { + return varr9; + } + + if (mvmt.getPathfindingMalus(varr9) >= mvmt.getPathfindingMalus(var7)) { + var7 = varr9; + } + } + + if (var6 == BlockPathTypes.OPEN && mvmt.getPathfindingMalus(var7) == 0.0F && this.entityWidth <= 1) { + return BlockPathTypes.OPEN; + } else { + return var7; + } + } + } + + @Override + public BlockPathTypes getBlockPathType(BlockGetter var0, int var1, int var2, int var3, Mob var4) { + EnumSet var5 = EnumSet.noneOf(BlockPathTypes.class); + BlockPathTypes var6 = BlockPathTypes.BLOCKED; + var6 = this.getBlockPathTypes(var0, var1, var2, var3, var5, var6, var4.blockPosition()); + if (var5.contains(BlockPathTypes.FENCE)) { + return BlockPathTypes.FENCE; + } else if (var5.contains(BlockPathTypes.UNPASSABLE_RAIL)) { + return BlockPathTypes.UNPASSABLE_RAIL; + } else { + BlockPathTypes var7 = BlockPathTypes.BLOCKED; + Iterator var9 = var5.iterator(); + + while (var9.hasNext()) { + BlockPathTypes varr9 = (BlockPathTypes) var9.next(); + if (var4.getPathfindingMalus(varr9) < 0.0F) { + return varr9; + } + + if (var4.getPathfindingMalus(varr9) >= var4.getPathfindingMalus(var7)) { + var7 = varr9; + } + } + + if (var6 == BlockPathTypes.OPEN && var4.getPathfindingMalus(var7) == 0.0F && this.entityWidth <= 1) { + return BlockPathTypes.OPEN; + } else { + return var7; + } + } + } + + protected BlockPathTypes getBlockPathType(LivingEntity var0, BlockPos var1) { + return this.getCachedBlockType(var0, var1.getX(), var1.getY(), var1.getZ()); + } + + public BlockPathTypes getBlockPathTypes(BlockGetter var0, int var1, int var2, int var3, EnumSet var4, + BlockPathTypes var5, BlockPos var6) { + for (int var7 = 0; var7 < this.entityWidth; ++var7) { + for (int var8 = 0; var8 < this.entityHeight; ++var8) { + for (int var9 = 0; var9 < this.entityDepth; ++var9) { + int var10 = var7 + var1; + int var11 = var8 + var2; + int var12 = var9 + var3; + BlockPathTypes var13 = this.getBlockPathType(var0, var10, var11, var12); + var13 = this.evaluateBlockPathType(var0, var6, var13); + if (var7 == 0 && var8 == 0 && var9 == 0) { + var5 = var13; + } + + var4.add(var13); + } + } + } + + return var5; + } + + protected BlockPathTypes getCachedBlockType(LivingEntity var0, int var1, int var2, int var3) { + return (BlockPathTypes) this.pathTypesByPosCache.computeIfAbsent(BlockPos.asLong(var1, var2, var3), (var4) -> { + return this.getBlockPathType(this.level, var1, var2, var3, var0); + }); + } + + protected double getFloorLevel(BlockPos var0) { + return (this.canFloat() || this.isAmphibious()) && this.level.getFluidState(var0).is(FluidTags.WATER) + ? var0.getY() + 0.5 + : getFloorLevel(this.level, var0); + } + + @Override + public Target getGoal(double var0, double var2, double var4) { + return this.getTargetFromNode(this.getNode(Mth.floor(var0), Mth.floor(var2), Mth.floor(var4))); + } + + private double getMobJumpHeight() { + return Math.max(1.125, this.mob.maxUpStep()); + } + + @Override + public int getNeighbors(Node[] var0, Node var1) { + int var2 = 0; + int var3 = 0; + BlockPathTypes var4 = this.getCachedBlockType(this.mob, var1.x, var1.y + 1, var1.z); + BlockPathTypes var5 = this.getCachedBlockType(this.mob, var1.x, var1.y, var1.z); + if (this.mvmt.getPathfindingMalus(var4) >= 0.0F && var5 != BlockPathTypes.STICKY_HONEY) { + var3 = Mth.floor(Math.max(1.0F, this.mob.maxUpStep())); + } + + double var6 = this.getFloorLevel(new BlockPos(var1.x, var1.y, var1.z)); + Node var8 = this.findAcceptedNode(var1.x, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (this.isNeighborValid(var8, var1)) { + var0[var2++] = var8; + } + + Node var9 = this.findAcceptedNode(var1.x - 1, var1.y, var1.z, var3, var6, Direction.WEST, var5); + if (this.isNeighborValid(var9, var1)) { + var0[var2++] = var9; + } + + Node var10 = this.findAcceptedNode(var1.x + 1, var1.y, var1.z, var3, var6, Direction.EAST, var5); + if (this.isNeighborValid(var10, var1)) { + var0[var2++] = var10; + } + + Node var11 = this.findAcceptedNode(var1.x, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (this.isNeighborValid(var11, var1)) { + var0[var2++] = var11; + } + + Node var12 = this.findAcceptedNode(var1.x - 1, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (this.isDiagonalValid(var1, var9, var11, var12)) { + var0[var2++] = var12; + } + + Node var13 = this.findAcceptedNode(var1.x + 1, var1.y, var1.z - 1, var3, var6, Direction.NORTH, var5); + if (this.isDiagonalValid(var1, var10, var11, var13)) { + var0[var2++] = var13; + } + + Node var14 = this.findAcceptedNode(var1.x - 1, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (this.isDiagonalValid(var1, var9, var8, var14)) { + var0[var2++] = var14; + } + + Node var15 = this.findAcceptedNode(var1.x + 1, var1.y, var1.z + 1, var3, var6, Direction.SOUTH, var5); + if (this.isDiagonalValid(var1, var10, var8, var15)) { + var0[var2++] = var15; + } + + return var2; + } + + private Node getNodeAndUpdateCostToMax(int var0, int var1, int var2, BlockPathTypes var3, float var4) { + Node var5 = this.getNode(var0, var1, var2); + var5.type = var3; + var5.costMalus = Math.max(var5.costMalus, var4); + return var5; + } + + @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())); + BlockPos var3; + if (!this.mob.canStandOnFluid(var2.getFluidState())) { + if (this.canFloat() && this.mob.isInWater()) { + while (true) { + if (!var2.is(Blocks.WATER) && var2.getFluidState() != Fluids.WATER.getSource(false)) { + --var0; + break; + } + + ++var0; + var2 = this.level.getBlockState(var1.set(this.mob.getX(), var0, this.mob.getZ())); + } + } else if (this.mob.onGround()) { + var0 = Mth.floor(this.mob.getY() + 0.5); + } else { + for (var3 = this.mob.blockPosition(); (this.level.getBlockState(var3).isAir() + || this.level.getBlockState(var3).isPathfindable(this.level, var3, PathComputationType.LAND)) + && var3.getY() > this.mob.level().getMinBuildHeight(); var3 = var3.below()) { + } + + var0 = var3.above().getY(); + } + } else { + while (true) { + if (!this.mob.canStandOnFluid(var2.getFluidState())) { + --var0; + break; + } + + ++var0; + var2 = this.level.getBlockState(var1.set(this.mob.getX(), var0, this.mob.getZ())); + } + } + + var3 = this.mob.blockPosition(); + if (!this.canStartAt(var1.set(var3.getX(), var0, var3.getZ()))) { + AABB var4 = this.mob.getBoundingBox(); + if (this.canStartAt(var1.set(var4.minX, var0, var4.minZ)) + || this.canStartAt(var1.set(var4.minX, var0, var4.maxZ)) + || this.canStartAt(var1.set(var4.maxX, var0, var4.minZ)) + || this.canStartAt(var1.set(var4.maxX, var0, var4.maxZ))) { + return this.getStartNode(var1); + } + } + + return this.getStartNode(new BlockPos(var3.getX(), var0, var3.getZ())); + } + + protected Node getStartNode(BlockPos var0) { + Node var1 = this.getNode(var0); + var1.type = this.getBlockPathType(this.mob, var1.asBlockPos()); + var1.costMalus = this.mvmt.getPathfindingMalus(var1.type); + return var1; + } + + private boolean hasCollisions(AABB var0) { + return this.collisionCache.computeIfAbsent(var0, (var1) -> { + return !this.level.noCollision(this.mob, var0); + }); + } + + protected boolean isAmphibious() { + return false; + } + + protected boolean isDiagonalValid(Node var0, Node var1, Node var2, Node var3) { + if (var3 != null && var2 != null && var1 != null) { + if (var3.closed) { + return false; + } else if (var2.y <= var0.y && var1.y <= var0.y) { + if (var1.type != BlockPathTypes.WALKABLE_DOOR && var2.type != BlockPathTypes.WALKABLE_DOOR + && var3.type != BlockPathTypes.WALKABLE_DOOR) { + boolean var4 = var2.type == BlockPathTypes.FENCE && var1.type == BlockPathTypes.FENCE + && this.mob.getBbWidth() < 0.5; + return var3.costMalus >= 0.0F && (var2.y < var0.y || var2.costMalus >= 0.0F || var4) + && (var1.y < var0.y || var1.costMalus >= 0.0F || var4); + } else { + return false; + } + } else { + return false; + } + } else { + return false; + } + } + + 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, LivingEntity var1) { + super.prepare(var0, var1); + this.oldWaterCost = mvmt.getPathfindingMalus(BlockPathTypes.WATER); + } + + @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) || 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; + } + + if (var9.is(Blocks.WITHER_ROSE) || var9.is(Blocks.POINTED_DRIPSTONE)) { + return BlockPathTypes.DAMAGE_CAUTIOUS; + } + } + } + } + } + + return var2; + } + + private static boolean doesBlockHavePartialCollision(BlockPathTypes var0) { + return var0 == BlockPathTypes.FENCE || var0 == BlockPathTypes.DOOR_WOOD_CLOSED + || var0 == BlockPathTypes.DOOR_IRON_CLOSED; + } + + protected static BlockPathTypes getBlockPathTypeRaw(BlockGetter var0, BlockPos var1) { + BlockState var2 = var0.getBlockState(var1); + Block var3 = var2.getBlock(); + if (var2.isAir()) { + return BlockPathTypes.OPEN; + } else if (!var2.is(BlockTags.TRAPDOORS) && !var2.is(Blocks.LILY_PAD) && !var2.is(Blocks.BIG_DRIPLEAF)) { + if (var2.is(Blocks.POWDER_SNOW)) { + return BlockPathTypes.POWDER_SNOW; + } else if (!var2.is(Blocks.CACTUS) && !var2.is(Blocks.SWEET_BERRY_BUSH)) { + if (var2.is(Blocks.HONEY_BLOCK)) { + return BlockPathTypes.STICKY_HONEY; + } else if (var2.is(Blocks.COCOA)) { + return BlockPathTypes.COCOA; + } else if (!var2.is(Blocks.WITHER_ROSE) && !var2.is(Blocks.POINTED_DRIPSTONE)) { + FluidState var4 = var0.getFluidState(var1); + if (var4.is(FluidTags.LAVA)) { + return BlockPathTypes.LAVA; + } else if (isBurningBlock(var2)) { + return BlockPathTypes.DAMAGE_FIRE; + } else if (var3 instanceof DoorBlock) { + DoorBlock var5 = (DoorBlock) var3; + if (var2.getValue(DoorBlock.OPEN)) { + return BlockPathTypes.DOOR_OPEN; + } else { + return var5.type().canOpenByHand() ? BlockPathTypes.DOOR_WOOD_CLOSED + : BlockPathTypes.DOOR_IRON_CLOSED; + } + } else if (var3 instanceof BaseRailBlock) { + return BlockPathTypes.RAIL; + } else if (var3 instanceof LeavesBlock) { + return BlockPathTypes.LEAVES; + } else if (var2.is(BlockTags.FENCES) || var2.is(BlockTags.WALLS) + || var3 instanceof FenceGateBlock && !(Boolean) var2.getValue(FenceGateBlock.OPEN)) { + return BlockPathTypes.FENCE; + } else if (!var2.isPathfindable(var0, var1, PathComputationType.LAND)) { + return BlockPathTypes.BLOCKED; + } else { + return var4.is(FluidTags.WATER) ? BlockPathTypes.WATER : BlockPathTypes.OPEN; + } + } else { + return BlockPathTypes.DAMAGE_CAUTIOUS; + } + } else { + return BlockPathTypes.DAMAGE_OTHER; + } + } else { + return BlockPathTypes.TRAPDOOR; + } + } + + 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.WALKABLE : BlockPathTypes.OPEN; + if (var6 == BlockPathTypes.DAMAGE_FIRE) { + var5 = BlockPathTypes.DAMAGE_FIRE; + } + + if (var6 == BlockPathTypes.DAMAGE_OTHER) { + var5 = BlockPathTypes.DAMAGE_OTHER; + } + + if (var6 == BlockPathTypes.STICKY_HONEY) { + var5 = BlockPathTypes.STICKY_HONEY; + } + + if (var6 == BlockPathTypes.POWDER_SNOW) { + var5 = BlockPathTypes.DANGER_POWDER_SNOW; + } + + if (var6 == BlockPathTypes.DAMAGE_CAUTIOUS) { + var5 = BlockPathTypes.DAMAGE_CAUTIOUS; + } + } + + 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.below(); + VoxelShape var3 = var0.getBlockState(var2).getCollisionShape(var0, var2); + return var2.getY() + (var3.isEmpty() ? 0.0 : var3.max(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); + } + + private static final double DEFAULT_MOB_JUMP_HEIGHT = 1.125; + public static final double SPACE_BETWEEN_WALL_POSTS = 0.5; + +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluatorBase.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluatorBase.java new file mode 100644 index 000000000..abe259842 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityNodeEvaluatorBase.java @@ -0,0 +1,108 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.LivingEntity; +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 EntityNodeEvaluatorBase extends NodeEvaluator { + protected boolean canFloat; + protected boolean canOpenDoors; + protected boolean canPassDoors; + protected boolean canWalkOverFences; + protected int entityDepth; + protected int entityHeight; + protected int entityWidth; + protected PathNavigationRegion level; + protected LivingEntity mob; + protected MobAI mvmt; + protected final Int2ObjectMap nodes = new Int2ObjectOpenHashMap(); + + @Override + public boolean canFloat() { + return this.canFloat; + } + + @Override + public boolean canOpenDoors() { + return this.canOpenDoors; + } + + @Override + public boolean canPassDoors() { + return this.canPassDoors; + } + + @Override + public boolean canWalkOverFences() { + return this.canWalkOverFences; + } + + @Override + public void done() { + this.level = null; + this.mob = null; + this.mvmt = null; + } + + @Override + protected Node getNode(BlockPos var0) { + return this.getNode(var0.getX(), var0.getY(), var0.getZ()); + } + + @Override + protected Node getNode(int var0, int var1, int var2) { + return this.nodes.computeIfAbsent(Node.createHash(var0, var1, var2), (var3) -> { + return new Node(var0, var1, var2); + }); + } + + @Override + protected net.minecraft.world.level.pathfinder.Target getTargetFromNode(Node var0) { + return new net.minecraft.world.level.pathfinder.Target(var0); + } + + public void prepare(PathNavigationRegion var0, LivingEntity var1) { + this.mob = var1; + this.mvmt = MobAI.from(var1); + this.level = var0; + this.nodes.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.nodes.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; + } + + @Override + public void setCanWalkOverFences(boolean var0) { + this.canWalkOverFences = var0; + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityPathfinder.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityPathfinder.java new file mode 100644 index 000000000..84638406e --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/EntityPathfinder.java @@ -0,0 +1,146 @@ +package net.citizensnpcs.nms.v1_20_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.Lists; +import com.google.common.collect.Sets; + +import net.citizensnpcs.Settings.Setting; +import net.minecraft.core.BlockPos; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.entity.LivingEntity; +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 EntityPathfinder extends PathFinder { + private final int maxVisitedNodes; + private final Node[] neighbors = new Node[32]; + private final EntityNodeEvaluator nodeEvaluator; + private final BinaryHeap openSet; + + public EntityPathfinder(EntityNodeEvaluator var0, int var1) { + super(var0, var1); + this.openSet = new BinaryHeap(); + this.nodeEvaluator = var0; + this.maxVisitedNodes = var1; + } + + public Path findPath(PathNavigationRegion var0, LivingEntity 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(null, 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(null, 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) { + Set var6 = var2.keySet(); + var1.g = 0.0F; + var1.h = getBestH(var1, var6); + var1.f = var1.h; + this.openSet.clear(); + this.openSet.insert(var1); + 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(); + 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_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/ForwardingNPCHolder.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/ForwardingNPCHolder.java new file mode 100644 index 000000000..1ea87a60c --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/ForwardingNPCHolder.java @@ -0,0 +1,22 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import org.bukkit.entity.Entity; + +import com.google.common.base.Joiner; + +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)) { + Messaging.idebug( + () -> Joiner.on(' ').join("ForwardingNPCHolder with an improper bukkit entity", this, handle)); + return null; + } + return ((NPCHolder) handle).getNPC(); + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/MobAI.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/MobAI.java new file mode 100644 index 000000000..e2f9f4cdd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/MobAI.java @@ -0,0 +1,176 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.Map; + +import com.google.common.collect.Maps; + +import net.citizensnpcs.Settings.Setting; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.control.JumpControl; +import net.minecraft.world.entity.ai.control.MoveControl; +import net.minecraft.world.entity.ai.navigation.PathNavigation; +import net.minecraft.world.level.pathfinder.BlockPathTypes; + +public interface MobAI { + org.bukkit.entity.Entity getBukkitEntity(); + + JumpControl getJumpControl(); + + Map getMalus(); + + MoveControl getMoveControl(); + + PathNavigation getNavigation(); + + default float getPathfindingMalus(BlockPathTypes var1) { + Map malus = getMalus(); + return malus.containsKey(var1) ? malus.get(var1) : var1.getMalus(); + } + + default void setPathfindingMalus(BlockPathTypes water, float oldWaterCost) { + getMalus().put(water, oldWaterCost); + } + + default void tickAI() { + getJumpControl().tick(); + getMoveControl().tick(); + PathNavigation nav = getNavigation(); + if (!nav.isDone()) { + nav.tick(); + } + } + + default void updatePathfindingRange(float range) { + ((LivingEntity) NMSImpl.getHandle(getBukkitEntity())).getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(range); + } + + public static class BasicMobAI implements MobAI { + private final EntityJumpControl controllerJump; + private final EntityMoveControl controllerMove; + private final LivingEntity entity; + private final Map malus; + private final EntityNavigation navigation; + + public BasicMobAI(LivingEntity entity) { + this.entity = entity; + NMSImpl.setAttribute(entity, Attributes.FOLLOW_RANGE, Setting.DEFAULT_PATHFINDING_RANGE.asDouble()); + entity.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.3D); + controllerJump = new EntityJumpControl(entity); + controllerMove = new EntityMoveControl(entity); + navigation = new EntityNavigation(entity, entity.level()); + malus = Maps.newEnumMap(BlockPathTypes.class); + } + + @Override + public org.bukkit.entity.Entity getBukkitEntity() { + return entity.getBukkitEntity(); + } + + @Override + public JumpControl getJumpControl() { + return controllerJump; + } + + @Override + public Map getMalus() { + return malus; + } + + @Override + public MoveControl getMoveControl() { + return controllerMove; + } + + @Override + public PathNavigation getNavigation() { + return navigation; + } + + } + + public static interface ForwardingMobAI extends MobAI { + MobAI getAI(); + + @Override + default org.bukkit.entity.Entity getBukkitEntity() { + return getAI().getBukkitEntity(); + } + + @Override + default JumpControl getJumpControl() { + return getAI().getJumpControl(); + } + + @Override + default Map getMalus() { + return getAI().getMalus(); + } + + @Override + default MoveControl getMoveControl() { + return getAI().getMoveControl(); + } + + @Override + default PathNavigation getNavigation() { + return getAI().getNavigation(); + } + } + + public static MobAI from(Entity handle) { + if (handle instanceof Mob) { + Mob mob = (Mob) handle; + return new MobAI() { + @Override + public org.bukkit.entity.Entity getBukkitEntity() { + return mob.getBukkitEntity(); + } + + @Override + public JumpControl getJumpControl() { + return mob.getJumpControl(); + } + + @Override + public Map getMalus() { + return null; + } + + @Override + public MoveControl getMoveControl() { + return mob.getMoveControl(); + } + + @Override + public PathNavigation getNavigation() { + return mob.getNavigation(); + } + + @Override + public float getPathfindingMalus(BlockPathTypes var1) { + return mob.getPathfindingMalus(var1); + } + + @Override + public void setPathfindingMalus(BlockPathTypes water, float oldWaterCost) { + mob.setPathfindingMalus(water, oldWaterCost); + } + + @Override + public void tickAI() { + mob.getSensing().tick(); + mob.getNavigation().tick(); + mob.getMoveControl().tick(); + mob.getLookControl().tick(); + mob.getJumpControl().tick(); + } + }; + } else if (handle instanceof MobAI) { + return (MobAI) handle; + } + return null; + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSBoundingBox.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSBoundingBox.java new file mode 100644 index 000000000..d9af8fefd --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSBoundingBox.java @@ -0,0 +1,26 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.api.util.BoundingBox; +import net.minecraft.world.phys.AABB; + +public class NMSBoundingBox { + private NMSBoundingBox() { + } + + public static AABB convert(BoundingBox box) { + return new AABB(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ); + } + + public static AABB makeBB(NPC npc, AABB def) { + return npc == null || !npc.data().has(NPC.Metadata.BOUNDING_BOX_FUNCTION) ? def + : NMSBoundingBox + .convert(npc.data().> get(NPC.Metadata.BOUNDING_BOX_FUNCTION).get()); + } + + public static BoundingBox wrap(AABB bb) { + return new BoundingBox(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java new file mode 100644 index 000000000..ad630e412 --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/NMSImpl.java @@ -0,0 +1,2625 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.lang.invoke.MethodHandle; +import java.net.SocketAddress; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +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 java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.World; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; +import org.bukkit.command.BlockCommandSender; +import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R1.CraftSound; +import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_20_R1.boss.CraftBossBar; +import org.bukkit.craftbukkit.v1_20_R1.command.CraftBlockCommandSender; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R1.entity.CraftWither; +import org.bukkit.craftbukkit.v1_20_R1.event.CraftEventFactory; +import org.bukkit.craftbukkit.v1_20_R1.event.CraftPortalEvent; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryAnvil; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +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.Inventory; +import org.bukkit.inventory.InventoryView; +import org.bukkit.inventory.meta.SkullMeta; +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.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +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.properties.Property; +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.astar.pathfinder.DoorExaminer; +import net.citizensnpcs.api.command.CommandManager; +import net.citizensnpcs.api.command.exception.CommandException; +import net.citizensnpcs.api.event.DespawnReason; +import net.citizensnpcs.api.gui.ForwardingInventory; +import net.citizensnpcs.api.jnbt.ByteArrayTag; +import net.citizensnpcs.api.jnbt.ByteTag; +import net.citizensnpcs.api.jnbt.CompoundTag; +import net.citizensnpcs.api.jnbt.DoubleTag; +import net.citizensnpcs.api.jnbt.EndTag; +import net.citizensnpcs.api.jnbt.FloatTag; +import net.citizensnpcs.api.jnbt.IntArrayTag; +import net.citizensnpcs.api.jnbt.IntTag; +import net.citizensnpcs.api.jnbt.ListTag; +import net.citizensnpcs.api.jnbt.LongTag; +import net.citizensnpcs.api.jnbt.ShortTag; +import net.citizensnpcs.api.jnbt.StringTag; +import net.citizensnpcs.api.jnbt.Tag; +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.Trait; +import net.citizensnpcs.api.trait.TraitInfo; +import net.citizensnpcs.api.util.BoundingBox; +import net.citizensnpcs.api.util.EntityDim; +import net.citizensnpcs.api.util.Messaging; +import net.citizensnpcs.nms.v1_20_R1.entity.AllayController; +import net.citizensnpcs.nms.v1_20_R1.entity.ArmorStandController; +import net.citizensnpcs.nms.v1_20_R1.entity.AxolotlController; +import net.citizensnpcs.nms.v1_20_R1.entity.BatController; +import net.citizensnpcs.nms.v1_20_R1.entity.BeeController; +import net.citizensnpcs.nms.v1_20_R1.entity.BlazeController; +import net.citizensnpcs.nms.v1_20_R1.entity.CamelController; +import net.citizensnpcs.nms.v1_20_R1.entity.CatController; +import net.citizensnpcs.nms.v1_20_R1.entity.CaveSpiderController; +import net.citizensnpcs.nms.v1_20_R1.entity.ChickenController; +import net.citizensnpcs.nms.v1_20_R1.entity.CodController; +import net.citizensnpcs.nms.v1_20_R1.entity.CowController; +import net.citizensnpcs.nms.v1_20_R1.entity.CreeperController; +import net.citizensnpcs.nms.v1_20_R1.entity.DolphinController; +import net.citizensnpcs.nms.v1_20_R1.entity.DrownedController; +import net.citizensnpcs.nms.v1_20_R1.entity.EnderDragonController; +import net.citizensnpcs.nms.v1_20_R1.entity.EndermanController; +import net.citizensnpcs.nms.v1_20_R1.entity.EndermiteController; +import net.citizensnpcs.nms.v1_20_R1.entity.EvokerController; +import net.citizensnpcs.nms.v1_20_R1.entity.FoxController; +import net.citizensnpcs.nms.v1_20_R1.entity.FrogController; +import net.citizensnpcs.nms.v1_20_R1.entity.GhastController; +import net.citizensnpcs.nms.v1_20_R1.entity.GiantController; +import net.citizensnpcs.nms.v1_20_R1.entity.GlowSquidController; +import net.citizensnpcs.nms.v1_20_R1.entity.GoatController; +import net.citizensnpcs.nms.v1_20_R1.entity.GuardianController; +import net.citizensnpcs.nms.v1_20_R1.entity.GuardianElderController; +import net.citizensnpcs.nms.v1_20_R1.entity.HoglinController; +import net.citizensnpcs.nms.v1_20_R1.entity.HorseController; +import net.citizensnpcs.nms.v1_20_R1.entity.HorseDonkeyController; +import net.citizensnpcs.nms.v1_20_R1.entity.HorseMuleController; +import net.citizensnpcs.nms.v1_20_R1.entity.HorseSkeletonController; +import net.citizensnpcs.nms.v1_20_R1.entity.HorseZombieController; +import net.citizensnpcs.nms.v1_20_R1.entity.HumanController; +import net.citizensnpcs.nms.v1_20_R1.entity.IllusionerController; +import net.citizensnpcs.nms.v1_20_R1.entity.IronGolemController; +import net.citizensnpcs.nms.v1_20_R1.entity.LlamaController; +import net.citizensnpcs.nms.v1_20_R1.entity.MagmaCubeController; +import net.citizensnpcs.nms.v1_20_R1.entity.MushroomCowController; +import net.citizensnpcs.nms.v1_20_R1.entity.OcelotController; +import net.citizensnpcs.nms.v1_20_R1.entity.PandaController; +import net.citizensnpcs.nms.v1_20_R1.entity.ParrotController; +import net.citizensnpcs.nms.v1_20_R1.entity.PhantomController; +import net.citizensnpcs.nms.v1_20_R1.entity.PigController; +import net.citizensnpcs.nms.v1_20_R1.entity.PigZombieController; +import net.citizensnpcs.nms.v1_20_R1.entity.PiglinBruteController; +import net.citizensnpcs.nms.v1_20_R1.entity.PiglinController; +import net.citizensnpcs.nms.v1_20_R1.entity.PillagerController; +import net.citizensnpcs.nms.v1_20_R1.entity.PolarBearController; +import net.citizensnpcs.nms.v1_20_R1.entity.PufferFishController; +import net.citizensnpcs.nms.v1_20_R1.entity.RabbitController; +import net.citizensnpcs.nms.v1_20_R1.entity.RavagerController; +import net.citizensnpcs.nms.v1_20_R1.entity.SalmonController; +import net.citizensnpcs.nms.v1_20_R1.entity.SheepController; +import net.citizensnpcs.nms.v1_20_R1.entity.ShulkerController; +import net.citizensnpcs.nms.v1_20_R1.entity.SilverfishController; +import net.citizensnpcs.nms.v1_20_R1.entity.SkeletonController; +import net.citizensnpcs.nms.v1_20_R1.entity.SkeletonStrayController; +import net.citizensnpcs.nms.v1_20_R1.entity.SkeletonWitherController; +import net.citizensnpcs.nms.v1_20_R1.entity.SlimeController; +import net.citizensnpcs.nms.v1_20_R1.entity.SnifferController; +import net.citizensnpcs.nms.v1_20_R1.entity.SnowmanController; +import net.citizensnpcs.nms.v1_20_R1.entity.SpiderController; +import net.citizensnpcs.nms.v1_20_R1.entity.SquidController; +import net.citizensnpcs.nms.v1_20_R1.entity.StriderController; +import net.citizensnpcs.nms.v1_20_R1.entity.TadpoleController; +import net.citizensnpcs.nms.v1_20_R1.entity.TraderLlamaController; +import net.citizensnpcs.nms.v1_20_R1.entity.TropicalFishController; +import net.citizensnpcs.nms.v1_20_R1.entity.TurtleController; +import net.citizensnpcs.nms.v1_20_R1.entity.VexController; +import net.citizensnpcs.nms.v1_20_R1.entity.VillagerController; +import net.citizensnpcs.nms.v1_20_R1.entity.VindicatorController; +import net.citizensnpcs.nms.v1_20_R1.entity.WanderingTraderController; +import net.citizensnpcs.nms.v1_20_R1.entity.WardenController; +import net.citizensnpcs.nms.v1_20_R1.entity.WitchController; +import net.citizensnpcs.nms.v1_20_R1.entity.WitherController; +import net.citizensnpcs.nms.v1_20_R1.entity.WolfController; +import net.citizensnpcs.nms.v1_20_R1.entity.ZoglinController; +import net.citizensnpcs.nms.v1_20_R1.entity.ZombieController; +import net.citizensnpcs.nms.v1_20_R1.entity.ZombieHuskController; +import net.citizensnpcs.nms.v1_20_R1.entity.ZombieVillagerController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.AreaEffectCloudController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.BlockDisplayController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.BoatController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ChestBoatController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.DragonFireballController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.EggController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.EnderCrystalController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.EnderPearlController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.EnderSignalController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.EvokerFangsController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.FallingBlockController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.FireworkController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.FishingHookController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.GlowItemFrameController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.InteractionController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ItemController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ItemDisplayController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ItemFrameController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.LargeFireballController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.LeashController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.LlamaSpitController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MarkerController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartChestController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartCommandController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartFurnaceController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartHopperController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartRideableController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.MinecartTNTController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.PaintingController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ShulkerBulletController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.SmallFireballController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.SnowballController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.SpectralArrowController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.TNTPrimedController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.TextDisplayController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ThrownExpBottleController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ThrownPotionController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.ThrownTridentController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.TippedArrowController; +import net.citizensnpcs.nms.v1_20_R1.entity.nonliving.WitherSkullController; +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.MirrorTrait; +import net.citizensnpcs.trait.RotationTrait; +import net.citizensnpcs.trait.versioned.AllayTrait; +import net.citizensnpcs.trait.versioned.AxolotlTrait; +import net.citizensnpcs.trait.versioned.BeeTrait; +import net.citizensnpcs.trait.versioned.BossBarTrait; +import net.citizensnpcs.trait.versioned.CamelTrait; +import net.citizensnpcs.trait.versioned.CamelTrait.CamelPose; +import net.citizensnpcs.trait.versioned.CatTrait; +import net.citizensnpcs.trait.versioned.EnderDragonTrait; +import net.citizensnpcs.trait.versioned.FoxTrait; +import net.citizensnpcs.trait.versioned.FrogTrait; +import net.citizensnpcs.trait.versioned.GoatTrait; +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.PiglinTrait; +import net.citizensnpcs.trait.versioned.PolarBearTrait; +import net.citizensnpcs.trait.versioned.PufferFishTrait; +import net.citizensnpcs.trait.versioned.ShulkerTrait; +import net.citizensnpcs.trait.versioned.SnifferTrait.SnifferState; +import net.citizensnpcs.trait.versioned.SnowmanTrait; +import net.citizensnpcs.trait.versioned.SpellcasterTrait; +import net.citizensnpcs.trait.versioned.TropicalFishTrait; +import net.citizensnpcs.trait.versioned.VillagerTrait; +import net.citizensnpcs.trait.versioned.WardenTrait; +import net.citizensnpcs.util.EmptyChannel; +import net.citizensnpcs.util.EntityPacketTracker; +import net.citizensnpcs.util.EntityPacketTracker.PacketAggregator; +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.core.BlockPos; +import net.minecraft.core.PositionImpl; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.network.chat.contents.LiteralContents; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundBundlePacket; +import net.minecraft.network.protocol.game.ClientboundMoveEntityPacket; +import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; +import net.minecraft.network.protocol.game.VecDeltaCodec; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +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.ServerEntity; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerPlayerConnection; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Mth; +import net.minecraft.world.Container; +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.EquipmentSlot; +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.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.control.FlyingMoveControl; +import net.minecraft.world.entity.ai.control.JumpControl; +import net.minecraft.world.entity.ai.control.LookControl; +import net.minecraft.world.entity.ai.control.MoveControl; +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.Dolphin; +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.Turtle; +import net.minecraft.world.entity.animal.allay.Allay; +import net.minecraft.world.entity.animal.axolotl.Axolotl; +import net.minecraft.world.entity.animal.camel.Camel; +import net.minecraft.world.entity.animal.horse.AbstractHorse; +import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.entity.item.FallingBlockEntity; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Shulker; +import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.world.entity.projectile.FishingHook; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.inventory.AnvilMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.dimension.end.EndDragonFight; +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.level.pathfinder.PathFinder; +import net.minecraft.world.level.portal.PortalInfo; +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(); + } + + @Override + public void activate(org.bukkit.entity.Entity entity) { + getHandle(entity).activatedTick = MinecraftServer.currentTick; + } + + @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().addFreshEntity(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); + } + try { + CHUNKMAP_UPDATE_PLAYER_STATUS.invoke(((ServerLevel) handle.level()).getChunkSource().chunkMap, handle, + !remove); + } catch (Throwable e) { + e.printStackTrace(); + } + // PlayerUpdateTask.addOrRemove(entity, remove); + } + + @Override + public void attack(org.bukkit.entity.LivingEntity attacker, org.bukkit.entity.LivingEntity btarget) { + LivingEntity source = getHandle(attacker); + LivingEntity target = getHandle(btarget); + if (source instanceof ServerPlayer) { + ((ServerPlayer) source).attack(target); + PlayerAnimation.ARM_SWING.play((Player) source.getBukkitEntity()); + return; + } + boolean hasAttackDamage = source.getAttributes().hasAttribute(Attributes.ATTACK_DAMAGE); + if (source instanceof Mob && hasAttackDamage) { + ((Mob) source).doHurtTarget(target); + return; + } + float f = (float) (hasAttackDamage ? source.getAttributeValue(Attributes.ATTACK_DAMAGE) : 1f); + int i = 0; + f += EnchantmentHelper.getDamageBonus(source.getMainHandItem(), target.getMobType()); + i += EnchantmentHelper.getKnockbackBonus(source); + boolean flag = target.hurt(target.damageSources().mobAttack(source), f); + if (!flag) + return; + if (i > 0) { + target.knockback(-Math.sin(source.getYRot() * Math.PI / 180.0F) * i * 0.5F, 0.1D, + Math.cos(source.getYRot() * Math.PI / 180.0F) * i * 0.5F); + source.setDeltaMovement(source.getDeltaMovement().multiply(0.6, 1, 0.6)); + } + int fireAspectLevel = EnchantmentHelper.getFireAspect(source); + if (fireAspectLevel > 0) { + target.setSecondsOnFire(fireAspectLevel * 4, false); + } + if (target instanceof ServerPlayer) { + ServerPlayer entityhuman = (ServerPlayer) target; + ItemStack itemstack = source.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(source) * 0.05F; + if (new Random().nextFloat() < f2) { + entityhuman.getCooldowns().addCooldown(Items.SHIELD, 100); + source.level().broadcastEntityEvent(entityhuman, (byte) 30); + } + } + } + EnchantmentHelper.doPostHurtEffects(source, target); + EnchantmentHelper.doPostDamageEffects(target, source); + } + + @Override + public void cancelMoveDestination(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + MobAI ai = MobAI.from(handle); + MoveControl control = ai != null ? ai.getMoveControl() : null; + if (control instanceof EntityMoveControl) { + ((EntityMoveControl) control).moving = false; + } else { + try { + MOVE_CONTROLLER_OPERATION.invoke(control, null); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + + @Override + @SuppressWarnings("rawtypes") + public Iterable createBundlePacket(List source) { + return source.isEmpty() ? ImmutableList.of() : ImmutableList.of(new ClientboundBundlePacket(source)); + } + + @Override + public EntityPacketTracker createPacketTracker(org.bukkit.entity.Entity entity, PacketAggregator agg) { + Entity handle = getHandle(entity); + Set linked = Sets.newIdentityHashSet(); + ServerEntity tracker = new ServerEntity((ServerLevel) handle.level(), handle, handle.getType().updateInterval(), + handle.getType().trackDeltas(), agg::send, linked); + Map equipment = Maps.newEnumMap(EquipmentSlot.class); + return new EntityPacketTracker() { + @Override + public void link(Player player) { + ServerPlayer p = (ServerPlayer) getHandle(player); + handle.unsetRemoved(); + tracker.addPairing(p); + linked.add(p.connection); + agg.add(p.getUUID(), packet -> p.connection.send((Packet) packet)); + } + + @Override + public void run() { + if (handle instanceof LivingEntity) { + boolean changed = false; + LivingEntity entity = (LivingEntity) handle; + for (EquipmentSlot slot : EquipmentSlot.values()) { + ItemStack old = equipment.getOrDefault(slot, ItemStack.EMPTY); + ItemStack curr = entity.getItemBySlot(slot); + if (!changed && entity.equipmentHasChanged(old, curr)) { + changed = true; + } + equipment.put(slot, curr); + } + if (changed) { + List> vals = Lists.newArrayList(); + for (EquipmentSlot slot : EquipmentSlot.values()) { + vals.add(com.mojang.datafixers.util.Pair.of(slot, equipment.get(slot))); + } + agg.send(new ClientboundSetEquipmentPacket(handle.getId(), vals)); + } + } + tracker.sendChanges(); + } + + @Override + public void unlink(Player player) { + ServerPlayer p = (ServerPlayer) getHandle(player); + tracker.removePairing(p); + linked.remove(p.connection); + agg.removeConnection(p.getUUID()); + } + + @Override + public void unlinkAll(Consumer callback) { + handle.remove(RemovalReason.KILLED); + for (ServerPlayerConnection link : Lists.newArrayList(linked)) { + Player entity = link.getPlayer().getBukkitEntity(); + unlink(entity); + if (callback != null) { + callback.accept(entity); + } + } + linked.clear(); + } + }; + } + + @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) getHandle(entity)).bossEvent; + } else if (entity.getType() == EntityType.ENDER_DRAGON) { + EndDragonFight df = ((EnderDragon) getHandle(entity)).getDragonFight(); + if (df != null) { + bserver = df.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(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()); + return shape.isEmpty() ? BoundingBox.EMPTY : NMSBoundingBox.wrap(shape.bounds()); + } + + @Override + public Location getDestination(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + MobAI ai = MobAI.from(handle); + MoveControl controller = ai != null ? ai.getMoveControl() : null; + if (controller == null || !controller.hasWanted()) { + return null; + } + return new Location(entity.getWorld(), controller.getWantedX(), controller.getWantedY(), + controller.getWantedZ()); + } + + @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 = getHandle((org.bukkit.entity.LivingEntity) entity); + return handle.zza; + } + + @Override + public CompoundTag getNBT(org.bukkit.inventory.ItemStack item) { + return convertNBT(CraftItemStack.asNMSCopy(item).getTag()); + } + + @Override + public NPC getNPC(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + return handle instanceof NPCHolder ? ((NPCHolder) handle).getNPC() : null; + } + + @Override + public EntityPacketTracker getPacketTracker(org.bukkit.entity.Entity entity) { + ServerLevel server = (ServerLevel) getHandle(entity).level(); + TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId()); + if (entry == null) + return null; + return new EntityPacketTracker() { + @Override + public void link(Player player) { + entry.updatePlayer((ServerPlayer) getHandle(player)); + } + + @Override + public void run() { + } + + @Override + public void unlink(Player player) { + entry.removePlayer((ServerPlayer) getHandle(player)); + } + + @Override + public void unlinkAll(Consumer callback) { + entry.broadcastRemoved(); + } + }; + } + + @Override + public List getPassengers(org.bukkit.entity.Entity entity) { + Entity handle = 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(Player player) { + return ((net.minecraft.world.entity.player.Player) getHandle(player)).getGameProfile(); + } + + @Override + public GameProfile getProfile(SkullMeta meta) { + if (SKULL_META_PROFILE == null) { + SKULL_META_PROFILE = NMS.getFirstGetter(meta.getClass(), GameProfile.class); + if (SKULL_META_PROFILE == null) { + return null; + } + } + try { + return (GameProfile) SKULL_META_PROFILE.invoke(meta); + } catch (Throwable e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String getSound(String flag) throws CommandException { + try { + Sound sound = Sound.valueOf(flag.toUpperCase()); + SoundEvent effect = CraftSound.getSoundEffect(sound); + if (effect == null) + throw new CommandException(Messages.INVALID_SOUND); + return effect.getLocation().getPath(); + } catch (Throwable e) { + throw new CommandException(Messages.INVALID_SOUND); + } + } + + @Override + public org.bukkit.entity.Entity getSource(BlockCommandSender sender) { + Entity source = ((CraftBlockCommandSender) sender).getWrapper().getEntity(); + return source != null ? source.getBukkitEntity() : null; + } + + @Override + public float getSpeedFor(NPC npc) { + if (!npc.isSpawned() || !(npc.getEntity() instanceof org.bukkit.entity.LivingEntity)) + return DEFAULT_SPEED; + LivingEntity handle = 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 getHandle(entity).maxUpStep(); + } + + @Override + public MCNavigator getTargetNavigator(org.bukkit.entity.Entity entity, Iterable nodes, + final NavigatorParameters params) { + List list = Lists. newArrayList(Iterables. transform(nodes, (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, (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, 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 = getNavigation(entity); + final float oldWater = raw instanceof MobAI ? ((MobAI) raw).getPathfindingMalus(BlockPathTypes.WATER) + : ((Mob) raw).getPathfindingMalus(BlockPathTypes.WATER); + if (params.avoidWater() && oldWater >= 0) { + if (raw instanceof MobAI) { + ((MobAI) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater + 1F); + } else { + ((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater + 1F); + } + } + navigation.getNodeEvaluator().setCanOpenDoors(params.hasExaminer(DoorExaminer.class)); + return new MCNavigator() { + float lastSpeed; + CancelReason reason; + + private List getBlocks(final org.bukkit.entity.Entity entity, Path path) { + List blocks = Lists.newArrayList(); + for (int i = 0; i < path.getNodeCount(); i++) { + Node pp = path.getNode(i); + blocks.add(entity.getWorld().getBlockAt(pp.x, pp.y, pp.z)); + } + return blocks; + } + + @Override + public CancelReason getCancelReason() { + return reason; + } + + @Override + public Iterable getPath() { + return new NavigationIterable(navigation); + } + + @Override + public void stop() { + Path path = getPathEntity(navigation); + if (params.debug() && path != null) { + List blocks = getBlocks(entity, path); + Util.sendBlockChanges(blocks, null); + } + if (oldWater >= 0) { + if (raw instanceof MobAI) { + ((MobAI) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater); + } else { + ((Mob) raw).setPathfindingMalus(BlockPathTypes.WATER, oldWater); + } + } + navigation.stop(); + } + + @Override + public boolean update() { + if (params.speed() != lastSpeed) { + 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. + } + if (params.debug() && getPathEntity(navigation) != null) { + Util.sendBlockChanges(getBlocks(entity, getPathEntity(navigation)), Material.DANDELION); + } + lastSpeed = params.speed(); + } + navigation.setSpeedModifier(params.speed()); + return navigation.isDone(); + } + }; + } + + @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 MCTargetNavigator(entity, navigation, target, parameters); + } + + @Override + public org.bukkit.entity.Entity getVehicle(org.bukkit.entity.Entity entity) { + Entity handle = 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 = 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 getHandle(entity).onGround(); + } + + @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) { + registerTraitWithCommand(manager, EnderDragonTrait.class); + registerTraitWithCommand(manager, AllayTrait.class); + registerTraitWithCommand(manager, AxolotlTrait.class); + registerTraitWithCommand(manager, BeeTrait.class); + registerTraitWithCommand(manager, BossBarTrait.class); + registerTraitWithCommand(manager, CamelTrait.class); + registerTraitWithCommand(manager, CatTrait.class); + registerTraitWithCommand(manager, FoxTrait.class); + registerTraitWithCommand(manager, FrogTrait.class); + registerTraitWithCommand(manager, GoatTrait.class); + registerTraitWithCommand(manager, LlamaTrait.class); + registerTraitWithCommand(manager, MushroomCowTrait.class); + registerTraitWithCommand(manager, ParrotTrait.class); + registerTraitWithCommand(manager, PandaTrait.class); + registerTraitWithCommand(manager, PiglinTrait.class); + registerTraitWithCommand(manager, PhantomTrait.class); + registerTraitWithCommand(manager, PolarBearTrait.class); + registerTraitWithCommand(manager, PufferFishTrait.class); + registerTraitWithCommand(manager, SpellcasterTrait.class); + registerTraitWithCommand(manager, ShulkerTrait.class); + registerTraitWithCommand(manager, SnowmanTrait.class); + registerTraitWithCommand(manager, TropicalFishTrait.class); + registerTraitWithCommand(manager, VillagerTrait.class); + registerTraitWithCommand(manager, WardenTrait.class); + } + + private void loadEntityTypes() { + EntityControllers.setEntityControllerForType(EntityType.ALLAY, AllayController.class); + 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.CAMEL, CamelController.class); + EntityControllers.setEntityControllerForType(EntityType.CAVE_SPIDER, CaveSpiderController.class); + EntityControllers.setEntityControllerForType(EntityType.CHEST_BOAT, ChestBoatController.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.FROG, FrogController.class); + EntityControllers.setEntityControllerForType(EntityType.TADPOLE, TadpoleController.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.LLAMA_SPIT, LlamaSpitController.class); + EntityControllers.setEntityControllerForType(EntityType.TRADER_LLAMA, TraderLlamaController.class); + EntityControllers.setEntityControllerForType(EntityType.WANDERING_TRADER, WanderingTraderController.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.SPLASH_POTION, ThrownPotionController.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.WARDEN, WardenController.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); + EntityControllers.setEntityControllerForType(EntityType.SNIFFER, SnifferController.class); + EntityControllers.setEntityControllerForType(EntityType.BLOCK_DISPLAY, BlockDisplayController.class); + EntityControllers.setEntityControllerForType(EntityType.TEXT_DISPLAY, TextDisplayController.class); + EntityControllers.setEntityControllerForType(EntityType.ITEM_DISPLAY, ItemDisplayController.class); + EntityControllers.setEntityControllerForType(EntityType.INTERACTION, InteractionController.class); + } + + @Override + public void look(org.bukkit.entity.Entity entity, float yaw, float pitch) { + Entity handle = getHandle(entity); + if (handle == null) + return; + yaw = Util.clamp(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 = getHandle(entity); + if (immediate || headOnly || BAD_CONTROLLER_LOOK.contains(handle.getBukkitEntity().getType()) + || (!(handle instanceof Mob) && !(handle instanceof MobAI))) { + 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 = distanceXZ == 0 ? 0 : Math.toDegrees(Math.acos(xDiff / distanceXZ)); + double pitch = distanceY == 0 ? 0 + : 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 = Util.getDragonYaw(handle.getBukkitEntity(), xDiff, zDiff); + } 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 NPCHolder) { + ((NPCHolder) handle).getNPC().getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToFace(to); + } + } + + @Override + public void look(org.bukkit.entity.Entity from, org.bukkit.entity.Entity to) { + Entity handle = getHandle(from), target = getHandle(to); + if (BAD_CONTROLLER_LOOK.contains(handle.getBukkitEntity().getType()) + || (!(handle instanceof Mob) && !(handle instanceof MobAI))) { + 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 NPCHolder) { + ((NPCHolder) handle).getNPC().getOrAddTrait(RotationTrait.class).getPhysicalSession().rotateToFace(to); + } + } + + @Override + public void mount(org.bukkit.entity.Entity entity, org.bukkit.entity.Entity passenger) { + if (getHandle(passenger) == null) + return; + getHandle(passenger).startRiding(getHandle(entity)); + } + + @Override + public void onPlayerInfoAdd(Player player, Object raw) { + ClientboundPlayerInfoUpdatePacket packet = (ClientboundPlayerInfoUpdatePacket) raw; + List list = Lists.newArrayList(packet.entries()); + boolean changed = false; + for (int i = 0; i < list.size(); i++) { + ClientboundPlayerInfoUpdatePacket.Entry npcInfo = list.get(i); + if (npcInfo == null) + continue; + NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(npcInfo.profileId()); + if (npc == null || !npc.isSpawned()) + continue; + if (Setting.DISABLE_TABLIST.asBoolean() != npcInfo.listed()) { + list.set(i, + new ClientboundPlayerInfoUpdatePacket.Entry(npcInfo.profileId(), npcInfo.profile(), + !Setting.DISABLE_TABLIST.asBoolean(), npcInfo.latency(), npcInfo.gameMode(), + !Setting.DISABLE_TABLIST.asBoolean() ? npcInfo.displayName() : Component.empty(), + npcInfo.chatSession())); + changed = true; + } + MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class); + if (trait == null || !trait.isMirroring(player)) { + continue; + } + GameProfile playerProfile = NMS.getProfile(player); + if (trait.mirrorName()) { + list.set(i, + new ClientboundPlayerInfoUpdatePacket.Entry(npcInfo.profileId(), playerProfile, + !Setting.DISABLE_TABLIST.asBoolean(), npcInfo.latency(), npcInfo.gameMode(), + Component.literal(playerProfile.getName()), npcInfo.chatSession())); + changed = true; + continue; + } + Collection textures = playerProfile.getProperties().get("textures"); + if (textures == null || textures.size() == 0) + continue; + npcInfo.profile().getProperties().clear(); + for (String key : playerProfile.getProperties().keySet()) { + npcInfo.profile().getProperties().putAll(key, playerProfile.getProperties().get(key)); + } + changed = true; + } + if (changed) { + try { + PLAYER_INFO_ENTRIES_LIST.invoke(packet, list); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } + + @Override + public InventoryView openAnvilInventory(Player player, Inventory anvil, String title) { + ServerPlayer handle = (ServerPlayer) getHandle(player); + final AnvilMenu container = new AnvilMenu(handle.nextContainerCounter(), handle.getInventory(), + ContainerLevelAccess.create(handle.level(), new BlockPos(0, 0, 0))) { + private CraftInventoryView bukkitEntity; + + @Override + protected void clearContainer(net.minecraft.world.entity.player.Player entityhuman, Container iinventory) { + } + + @Override + public void createResult() { + super.createResult(); + cost.set(0); + } + + @Override + public CraftInventoryView getBukkitView() { + if (this.bukkitEntity == null) { + this.bukkitEntity = new CraftInventoryView(this.player.getBukkitEntity(), + new CitizensInventoryAnvil(this.access.getLocation(), this.inputSlots, this.resultSlots, + this, anvil), + this); + } + return this.bukkitEntity; + } + }; + container.setTitle(MutableComponent.create(new LiteralContents(title == null ? "" : title))); + container.getBukkitView().setItem(0, anvil.getItem(0)); + container.getBukkitView().setItem(1, anvil.getItem(1)); + container.checkReachable = false; + handle.connection.send( + new ClientboundOpenScreenPacket(container.containerId, container.getType(), container.getTitle())); + handle.containerMenu = container; + handle.initMenu(container); + return container.getBukkitView(); + } + + @Override + public void openHorseScreen(Tameable horse, Player equipper) { + LivingEntity handle = getHandle(horse); + ServerPlayer equipperHandle = (ServerPlayer) getHandle(equipper); + if (handle == null || equipperHandle == null) + return; + boolean wasTamed = horse.isTamed(); + horse.setTamed(true); + ((AbstractHorse) handle).openCustomInventoryScreen(equipperHandle); + horse.setTamed(wasTamed); + } + + @Override + public void playAnimation(PlayerAnimation animation, Player player, int radius) { + PlayerAnimationImpl.play(animation, player, radius); + } + + @Override + public Runnable playerTicker(Player entity) { + return ((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()); + } + + private void registerTraitWithCommand(CommandManager manager, Class clazz) { + CitizensAPI.getTraitFactory().registerTrait(TraitInfo.create(clazz)); + manager.register(clazz); + } + + @Override + public void remove(org.bukkit.entity.Entity entity) { + getHandle(entity).remove(RemovalReason.KILLED); + } + + @Override + public void removeFromServerPlayerList(Player player) { + ServerPlayer handle = (ServerPlayer) 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()).getChunkSource().removeEntity(nmsEntity); + } + + @Override + public void removeHookIfNecessary(NPCRegistry npcRegistry, FishHook entity) { + FishingHook hook = (FishingHook) getHandle(entity); + Entity hooked = hook.getHookedIn(); + if (hooked == null) + return; + NPC npc = npcRegistry.getNPC(hooked.getBukkitEntity()); + if (npc != null && npc.isProtected()) { + hook.hookedIn = null; + hook.setRemoved(RemovalReason.KILLED); + } + } + + @Override + public void replaceTrackerEntry(org.bukkit.entity.Entity entity) { + ServerLevel server = (ServerLevel) getHandle(entity).level(); + TrackedEntity entry = server.getChunkSource().chunkMap.entityMap.get(entity.getEntityId()); + if (entry == null) + return; + CitizensEntityTracker replace = new CitizensEntityTracker(server.getChunkSource().chunkMap, entry); + server.getChunkSource().chunkMap.entityMap.put(entity.getEntityId(), replace); + } + + @Override + public void sendPositionUpdate(org.bukkit.entity.Entity from, boolean position, Float bodyYaw, Float pitch, + Float headYaw) { + List> toSend = getPositionUpdate(from, position, bodyYaw, pitch, headYaw); + sendPacketsNearby(null, from.getLocation(), toSend, 64); + } + + @Override + public boolean sendTabListAdd(Player recipient, Player listPlayer) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(listPlayer); + ServerPlayer from = ((CraftPlayer) listPlayer).getHandle(); + ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket + .createPlayerInitializing(Arrays.asList(from)); + boolean list = from instanceof NPCHolder + ? !((NPCHolder) from).getNPC().data().get("removefromtablist", Setting.DISABLE_TABLIST.asBoolean()) + : false; + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(from.getUUID(), + from.getGameProfile(), list, from.latency, from.gameMode.getGameModeForPlayer(), + list ? from.getTabListDisplayName() : Component.empty(), + from.getChatSession() == null ? null : from.getChatSession().asData()); + try { + PLAYERINFO_ENTRIES.invoke(packet, Lists.newArrayList(entry)); + } catch (Throwable e) { + e.printStackTrace(); + } + sendPacket(recipient, packet); + return true; + } + + @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++; + } + sendPacket(recipient, new ClientboundPlayerInfoRemovePacket( + skinnableNPCs.stream().map(e -> ((ServerPlayer) e).getUUID()).collect(Collectors.toList()))); + } + + @Override + public void sendTabListRemove(Player recipient, Player listPlayer) { + Preconditions.checkNotNull(recipient); + Preconditions.checkNotNull(listPlayer); + sendPacket(recipient, new ClientboundPlayerInfoRemovePacket(Arrays.asList(getHandle(listPlayer).getUUID()))); + } + + @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)); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @Override + public void setAggressive(org.bukkit.entity.Entity entity, boolean aggro) { + Entity handle = getHandle(entity); + if (!(handle instanceof Mob)) + return; + ((Mob) handle).setAggressive(aggro); + } + + @Override + public void setAllayDancing(org.bukkit.entity.Entity entity, boolean dancing) { + Allay allay = (Allay) getHandle(entity); + allay.setDancing(dancing); + } + + @Override + public void setBodyYaw(org.bukkit.entity.Entity entity, float yaw) { + getHandle(entity).setYRot(yaw); + } + + @Override + public void setBoundingBox(org.bukkit.entity.Entity entity, BoundingBox box) { + getHandle(entity).setBoundingBox(NMSBoundingBox.convert(box)); + } + + @Override + public void setCamelPose(org.bukkit.entity.Entity entity, CamelPose pose) { + if (entity.getType() != EntityType.CAMEL) + throw new IllegalStateException(); + Camel camel = (Camel) getHandle(entity); + switch (pose) { + case STANDING: + if (!camel.isStanding()) { + camel.standUp(); + } + return; + case SITTING: + if (!camel.isCamelSitting()) { + camel.sitDown(); + } + return; + case PANIC: + if (!camel.isPanicking()) { + camel.standUpInstantly(); + } + return; + } + } + + @Override + public void setCustomName(org.bukkit.entity.Entity entity, Object component, String string) { + if (getHandle(entity) instanceof net.minecraft.world.entity.Display.TextDisplay) { + net.minecraft.world.entity.Display.TextDisplay disp = (net.minecraft.world.entity.Display.TextDisplay) getHandle( + entity); + disp.setText((Component) component); + } else { + getHandle(entity).setCustomName((Component) component); + } + } + + @Override + public void setDestination(org.bukkit.entity.Entity entity, double x, double y, double z, float speed) { + Entity handle = getHandle(entity); + if (handle == null) + return; + MobAI ai = MobAI.from(handle); + if (ai != null) { + ai.getMoveControl().setWantedPosition(x, y, z, speed); + } + } + + @Override + public void setDimensions(org.bukkit.entity.Entity entity, EntityDim desired) { + setSize(getHandle(entity), new EntityDimensions(desired.width, desired.height, true)); + } + + @Override + public void setEndermanAngry(org.bukkit.entity.Enderman enderman, boolean angry) { + if (ENDERMAN_CREEPY == null) + return; + getHandle(enderman).getEntityData().set(ENDERMAN_CREEPY, 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.clamp(yaw); + handle.yBodyRotO = yaw; + if (!(handle instanceof net.minecraft.world.entity.player.Player)) { + handle.setYBodyRot(yaw); + } + handle.setYHeadRot(yaw); + } + + @Override + public void setKnockbackResistance(org.bukkit.entity.LivingEntity entity, double d) { + LivingEntity handle = getHandle(entity); + handle.getAttribute(Attributes.KNOCKBACK_RESISTANCE).setBaseValue(d); + } + + @Override + public void setLocationDirectly(org.bukkit.entity.Entity entity, Location location) { + getHandle(entity).setPos(location.getX(), location.getY(), location.getZ()); + getHandle(entity).moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), + location.getPitch()); + } + + @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) { + getNavigation(handle).moveTo(getHandle(target), speed); + } + + @Override + public void setNoGravity(org.bukkit.entity.Entity entity, boolean nogravity) { + Entity handle = getHandle(entity); + handle.setNoGravity(nogravity); + if (!(handle instanceof Mob) || !(entity instanceof NPCHolder)) + return; + Mob mob = (Mob) handle; + NPC npc = ((NPCHolder) entity).getNPC(); + if (!(mob.getMoveControl() instanceof FlyingMoveControl) || npc.data().has("flying-nogravity-float")) + return; + try { + if (nogravity) { + boolean old = (boolean) FLYING_MOVECONTROL_FLOAT_GETTER.invoke(mob.getMoveControl()); + FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), true); + npc.data().set("flying-nogravity-float", old); + } else if (npc.data().has("flying-nogravity-float")) { + FLYING_MOVECONTROL_FLOAT_SETTER.invoke(mob.getMoveControl(), npc.data().get("flying-nogravity-float")); + npc.data().remove("flying-nogravity-float"); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @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 setPiglinDancing(org.bukkit.entity.Entity entity, boolean dancing) { + if (!(getHandle(entity) instanceof Piglin)) + return; + ((Piglin) getHandle(entity)).setDancing(dancing); + } + + @Override + public void setPitch(org.bukkit.entity.Entity entity, float pitch) { + getHandle(entity).setXRot(pitch); + } + + @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 (SET_PROFILE_METHOD == null) { + SET_PROFILE_METHOD = NMS.getMethodHandle(meta.getClass(), "setProfile", true, GameProfile.class); + if (SET_PROFILE_METHOD == null) { + return; + } + } + try { + SET_PROFILE_METHOD.invoke(meta, profile); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @Override + public void setShouldJump(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + if (handle == null) + return; + if (handle instanceof Mob) { + JumpControl controller = ((Mob) handle).getJumpControl(); + controller.jump(); + } else { + ((LivingEntity) handle).setJumping(true); + } + } + + @Override + public void setSitting(org.bukkit.entity.Ocelot ocelot, boolean sitting) { + setSneaking(ocelot, sitting); + } + + @Override + public void setSitting(Tameable tameable, boolean sitting) { + ((TamableAnimal) getHandle(tameable)).setInSittingPose(sitting); + } + + @Override + public void setSneaking(org.bukkit.entity.Entity entity, boolean sneaking) { + if (entity instanceof Player) { + ((Player) entity).setSneaking(sneaking); + } + Pose pose = sneaking ? Pose.CROUCHING : Pose.STANDING; + getHandle(entity).setPose(pose); + } + + @Override + public void setSnifferState(org.bukkit.entity.Entity entity, SnifferState state) { + net.minecraft.world.entity.animal.sniffer.Sniffer handle = (net.minecraft.world.entity.animal.sniffer.Sniffer) getHandle( + entity); + handle.transitionTo(net.minecraft.world.entity.animal.sniffer.Sniffer.State.valueOf(state.name())); + } + + @Override + public void setStepHeight(org.bukkit.entity.Entity entity, float height) { + getHandle(entity).setMaxUpStep(height); + } + + @Override + public void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) { + if (!bukkitEntity.getType().isAlive()) + return; + LivingEntity handle = 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 org.bukkit.entity.LivingEntity)) + return false; + try { + return (boolean) JUMP_FIELD.invoke(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.get()); + } catch (Throwable e) { + } + } + + @Override + public void sleep(org.bukkit.entity.Player player, boolean sleeping) { + getHandle(player).setPose(sleeping ? Pose.SLEEPING : Pose.STANDING); + } + + @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 = getHandle(entity); + if (handle == null) + return; + if (RANDOM.nextFloat() <= 0.85F && handle.isInWater()) { + handle.setDeltaMovement(handle.getDeltaMovement().x, handle.getDeltaMovement().y + power, + handle.getDeltaMovement().z); + } + } + + @Override + public void updateInventoryTitle(Player player, InventoryView view, String newTitle) { + ServerPlayer handle = (ServerPlayer) getHandle(player); + MenuType menuType = null; + switch (view.getTopInventory().getType()) { + case ANVIL: + menuType = MenuType.ANVIL; + break; + case BARREL: + menuType = MenuType.GENERIC_9x3; + break; + case BEACON: + menuType = MenuType.BEACON; + break; + case BLAST_FURNACE: + menuType = MenuType.BLAST_FURNACE; + break; + case BREWING: + menuType = MenuType.BREWING_STAND; + break; + case CARTOGRAPHY: + menuType = MenuType.CARTOGRAPHY_TABLE; + break; + case CHEST: + int sz = view.getTopInventory().getSize(); + if (sz > 45) { + menuType = MenuType.GENERIC_9x6; + } else if (sz > 36) { + menuType = MenuType.GENERIC_9x5; + } else if (sz > 27) { + menuType = MenuType.GENERIC_9x4; + } else if (sz > 18) { + menuType = MenuType.GENERIC_9x3; + } else if (sz > 9) { + menuType = MenuType.GENERIC_9x2; + } else { + menuType = MenuType.GENERIC_9x1; + } + break; + case COMPOSTER: + break; + case PLAYER: + case CRAFTING: + case CREATIVE: + return; + case DISPENSER: + case DROPPER: + menuType = MenuType.GENERIC_3x3; + break; + case ENCHANTING: + menuType = MenuType.ENCHANTMENT; + break; + case ENDER_CHEST: + menuType = MenuType.GENERIC_9x3; + break; + case FURNACE: + menuType = MenuType.FURNACE; + break; + case GRINDSTONE: + menuType = MenuType.GRINDSTONE; + break; + case HOPPER: + menuType = MenuType.HOPPER; + break; + case LECTERN: + menuType = MenuType.LECTERN; + break; + case LOOM: + menuType = MenuType.LOOM; + break; + case MERCHANT: + menuType = MenuType.MERCHANT; + break; + case SHULKER_BOX: + menuType = MenuType.SHULKER_BOX; + break; + case SMITHING: + menuType = MenuType.SMITHING; + break; + case SMOKER: + menuType = MenuType.SMOKER; + break; + case STONECUTTER: + menuType = MenuType.STONECUTTER; + break; + case WORKBENCH: + menuType = MenuType.CRAFTING; + break; + } + handle.connection.send(new ClientboundOpenScreenPacket(handle.containerMenu.containerId, menuType, + MutableComponent.create(new LiteralContents(newTitle)))); + player.updateInventory(); + } + + @Override + public void updateNavigationWorld(org.bukkit.entity.Entity entity, World world) { + if (NAVIGATION_WORLD_FIELD == null) + return; + Entity en = 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 = getHandle((org.bukkit.entity.LivingEntity) npc.getEntity()); + if (en instanceof MobAI) { + ((MobAI) en).updatePathfindingRange(pathfindingRange); + return; + } + if (NAVIGATION_PATHFINDER == 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_PATHFINDER.invoke(navigation, NAVIGATION_CREATE_PATHFINDER.invoke(navigation, mc)); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private static class CitizensInventoryAnvil extends CraftInventoryAnvil implements ForwardingInventory { + private final Inventory wrapped; + + public CitizensInventoryAnvil(Location location, Container inventory, Container resultInventory, + AnvilMenu container, Inventory wrapped) { + super(location, inventory, resultInventory, container); + this.wrapped = wrapped; + } + + @Override + public Inventory getWrapped() { + return wrapped; + } + + @Override + public void setItem(int slot, org.bukkit.inventory.ItemStack item) { + super.setItem(slot, item); + wrapped.setItem(slot, item); + } + } + + private static class MCTargetNavigator implements TargetNavigator { + private final org.bukkit.entity.Entity entity; + private final PathNavigation navigation; + private final NavigatorParameters parameters; + private final org.bukkit.entity.Entity target; + + private MCTargetNavigator(org.bukkit.entity.Entity entity, PathNavigation navigation, + org.bukkit.entity.Entity target, NavigatorParameters parameters) { + this.entity = entity; + this.navigation = navigation; + this.target = target; + this.parameters = parameters; + } + + @Override + public Location getCurrentDestination() { + return NMS.getDestination(entity); + } + + @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() { + navigation.stop(); + } + + @Override + public void update() { + navigation.tick(); + } + } + + private static class NavigationIterable implements Iterable { + private final PathNavigation navigation; + + public NavigationIterable(PathNavigation nav) { + this.navigation = nav; + } + + @Override + public Iterator iterator() { + Path path = getPathEntity(navigation); + final int npoints = path == null ? 0 : path.getNodeCount(); + return new Iterator() { + Node curr = npoints > 0 ? path.getNode(0) : null; + int i = 0; + + @Override + public boolean hasNext() { + return curr != null; + } + + @Override + public Vector next() { + Node old = curr; + curr = i + 1 < npoints ? path.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, + Consumer> cb) { + EntityDimensions size; + try { + size = (EntityDimensions) SIZE_FIELD_GETTER.invoke(living); + } catch (Throwable e) { + e.printStackTrace(); + return; + } + float oldw = size.width; + float oldl = size.height; + cb.accept(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 (goalSelectors == null) + return; + int i = 0; + for (GoalSelector selector : goalSelectors) { + try { + Collection list = selector.getAvailableGoals(); + 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++; + } + } + + private static CompoundTag convertNBT(net.minecraft.nbt.CompoundTag tag) { + if (tag == null) { + return new CompoundTag("", Collections.EMPTY_MAP); + } + Map tags = Maps.newHashMap(); + for (String key : tag.getAllKeys()) { + tags.put(key, convertNBT(key, tag.get(key))); + } + return new CompoundTag("", tags); + } + + private static Tag convertNBT(String key, net.minecraft.nbt.Tag base) { + if (base instanceof net.minecraft.nbt.IntTag) { + return new IntTag(key, ((net.minecraft.nbt.IntTag) base).getAsInt()); + } else if (base instanceof net.minecraft.nbt.FloatTag) { + return new FloatTag(key, ((net.minecraft.nbt.FloatTag) base).getAsFloat()); + } else if (base instanceof net.minecraft.nbt.DoubleTag) { + return new DoubleTag(key, ((net.minecraft.nbt.DoubleTag) base).getAsDouble()); + } else if (base instanceof net.minecraft.nbt.LongTag) { + return new LongTag(key, ((net.minecraft.nbt.LongTag) base).getAsLong()); + } else if (base instanceof net.minecraft.nbt.ShortTag) { + return new ShortTag(key, ((net.minecraft.nbt.ShortTag) base).getAsShort()); + } else if (base instanceof net.minecraft.nbt.ByteTag) { + return new ByteTag(key, ((net.minecraft.nbt.ByteTag) base).getAsByte()); + } else if (base instanceof net.minecraft.nbt.ByteArrayTag) { + return new ByteArrayTag(key, ((net.minecraft.nbt.ByteArrayTag) base).getAsByteArray()); + } else if (base instanceof net.minecraft.nbt.IntArrayTag) { + return new IntArrayTag(key, ((net.minecraft.nbt.IntArrayTag) base).getAsIntArray()); + } else if (base instanceof net.minecraft.nbt.StringTag) { + return new StringTag(key, base.getAsString()); + } else if (base instanceof net.minecraft.nbt.ListTag) { + List list = (List) base; + List converted = Lists.newArrayList(); + if (list.size() > 0) { + Class tagType = convertNBT("", list.get(0)).getClass(); + for (int i = 0; i < list.size(); i++) { + converted.add(convertNBT("", list.get(i))); + } + return new ListTag(key, tagType, converted); + } + return null; + } else if (base instanceof net.minecraft.nbt.CompoundTag) { + return convertNBT(((net.minecraft.nbt.CompoundTag) base)); + } else if (base instanceof net.minecraft.nbt.EndTag) { + return new EndTag(); + } + return null; + } + + public static boolean fluidPush(NPC npc, Entity entity, Supplier func) { + if (npc == null) { + return func.get(); + } + Vec3 old = entity.getDeltaMovement().add(0, 0, 0); + boolean res = func.get(); + if (!npc.isPushableByFluids()) { + entity.setDeltaMovement(old); + } + return res; + } + + 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)) { + 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.onGround()) + f2 *= 0.5F; + if (f2 > 0.0F) { + f += (0.546F - 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.8D, f)); + Vec3 vec3d2 = entity.getFluidFallingAdjustedMovement(d0, flag, entity.getDeltaMovement()); + entity.setDeltaMovement(vec3d2); + if (entity.horizontalCollision + && entity.isFree(vec3d2.x, vec3d2.y + 0.6D - entity.getY() + d1, vec3d2.z)) + entity.setDeltaMovement(vec3d2.x, 0.3D, vec3d2.z); + } else if (entity.isInLava() && !entity.canStandOnFluid(fluid)) { + 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.8D, 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.6D - entity.getY() + d1, vec3d3.z)) + entity.setDeltaMovement(vec3d3.x, 0.3D, 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.99D, 0.98D, 0.99D)); + 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) { + entity.playSound(entity.getFallDamageSound0((int) f4), 1.0F, 1.0F); + entity.hurt(entity.damageSources().flyIntoWall(), f4); + } + } + if (entity.onGround() && !entity.level().isClientSide && entity.getSharedFlag(7) + && !CraftEventFactory.callToggleGlideEvent(entity, false).isCancelled()) + entity.setSharedFlag(7, false); + } else { + BlockPos blockposition = BlockPos.containing(entity.getX(), (entity.getBoundingBox()).minY - 0.5D, + entity.getZ()); + float f5 = entity.level().getBlockState(blockposition).getBlock().getFriction(); + float f = entity.onGround() ? (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.98D, vec3d6.z * f); + } + } + } + entity.calculateEntityAnimation(entity instanceof net.minecraft.world.entity.animal.FlyingAnimal); + } + + public static TreeMap getBehaviorMap(LivingEntity entity) { + try { + return (TreeMap) BEHAVIOR_TREE_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) getHandle((org.bukkit.entity.Entity) entity); + } + + private static LivingEntity getHandle(Tameable entity) { + return (LivingEntity) getHandle((org.bukkit.entity.Entity) entity); + } + + public static PathNavigation getNavigation(org.bukkit.entity.Entity entity) { + Entity handle = getHandle(entity); + return handle instanceof Mob ? ((Mob) handle).getNavigation() + : handle instanceof MobAI ? ((MobAI) handle).getNavigation() : null; + } + + private static Path getPathEntity(PathNavigation nav) { + try { + return nav instanceof EntityNavigation ? ((EntityNavigation) nav).getPathEntity() + : (Path) NAVIGATION_PATH.invoke(nav); + } catch (Throwable e) { + e.printStackTrace(); + return null; + } + } + + public static List> getPositionUpdate(org.bukkit.entity.Entity from, boolean position, Float bodyYaw, + Float pitch, Float headYaw) { + Entity handle = getHandle(from); + if (bodyYaw == null) { + bodyYaw = handle.getYRot(); + } + if (pitch == null) { + pitch = handle.getXRot(); + } + List> toSend = Lists.newArrayList(); + if (position) { + TrackedEntity entry = ((ServerLevel) handle.level()).getChunkSource().chunkMap.entityMap + .get(handle.getId()); + VecDeltaCodec vdc = null; + try { + vdc = (VecDeltaCodec) POSITION_CODEC_GETTER.invoke((ServerEntity) SERVER_ENTITY_GETTER.invoke(entry)); + } catch (Throwable e) { + e.printStackTrace(); + return Collections.emptyList(); + } + Vec3 pos = handle.trackingPosition(); + toSend.add(new ClientboundMoveEntityPacket.PosRot(handle.getId(), (short) vdc.encodeX(pos), + (short) vdc.encodeY(pos), (short) vdc.encodeZ(pos), (byte) (bodyYaw * 256.0F / 360.0F), + (byte) (pitch * 256.0F / 360.0F), handle.onGround)); + } else { + toSend.add(new ClientboundMoveEntityPacket.Rot(handle.getId(), (byte) (bodyYaw * 256.0F / 360.0F), + (byte) (pitch * 256.0F / 360.0F), handle.onGround)); + } + if (headYaw != null) { + toSend.add(new ClientboundRotateHeadPacket(handle, (byte) (headYaw * 256.0F / 360.0F))); + } + return toSend; + } + + public static EntityDataAccessor getRabbitTypeField() { + return RABBIT_TYPE_DATAWATCHER; + } + + 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, NPC.Metadata meta) { + return npc == null || !npc.data().has(meta) ? snd + : BuiltInRegistries.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 isLeashed(NPC npc, Supplier isLeashed, Mob entity) { + return NMS.isLeashed(npc, isLeashed, () -> entity.dropLeash(true, false)); + } + + @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.Metadata.MINECART_ITEM, ""), false); + int data = npc.data().get(NPC.Metadata.MINECART_ITEM_DATA, 0); // TODO: migration for this + int offset = npc.data().get(NPC.Metadata.MINECART_OFFSET, 0); + minecart.setCustomDisplay(mat != null); + if (mat != null) { + minecart.setDisplayBlockState(BuiltInRegistries.BLOCK.byId(mat.getId()).defaultBlockState()); + } + minecart.setDisplayOffset(offset); + } + + public static boolean moveFish(NPC npc, Mob handle, Vec3 vec3d) { + if (npc == null) { + return false; + } + if (!npc.useMinecraftAI() && handle.isInWater() && !npc.getNavigator().isNavigating()) { + handle.moveRelative((handle instanceof Dolphin || handle instanceof Axolotl) ? handle.getSpeed() + : handle instanceof Turtle ? 0.1F : 0.01F, vec3d); + handle.move(MoverType.SELF, handle.getDeltaMovement()); + handle.setDeltaMovement(handle.getDeltaMovement().scale(0.9)); + return true; + } + return false; + } + + 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 (goalSelectors == null) + return; + int i = 0; + for (GoalSelector selector : goalSelectors) { + try { + Collection list = selector.getAvailableGoals(); + 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) 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 player : CitizensAPI.getLocationLookup().getNearbyPlayers(location, radius)) { + if (world != player.getWorld() || (from != null && !player.canSee(from)) + || (location.distanceSquared(player.getLocation(PACKET_CACHE_LOCATION)) > radius)) { + continue; + } + for (Packet packet : packets) { + sendPacket(player, packet); + } + } + } + + public static void sendPacketsNearby(Player from, Location location, Packet... packets) { + sendPacketsNearby(from, location, Arrays.asList(packets), 64); + } + + public static void setAdvancement(Player entity, PlayerAdvancements instance) { + try { + ADVANCEMENTS_PLAYER_SETTER.invoke(getHandle(entity), instance); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setAttribute(LivingEntity entity, Attribute attribute, double value) { + AttributeInstance attr = entity.getAttribute(attribute); + if (attr == null) { + try { + AttributeSupplier provider = (AttributeSupplier) ATTRIBUTE_SUPPLIER.invoke(entity.getAttributes()); + Map all = Maps + .newHashMap((Map) ATTRIBUTE_PROVIDER_MAP.invoke(provider)); + all.put(attribute, new AttributeInstance(attribute, 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(); + } + attr = entity.getAttribute(attribute); + } + attr.setBaseValue(value); + } + + public static void setBukkitEntity(Entity entity, CraftEntity bukkitEntity) { + try { + BUKKITENTITY_FIELD_SETTER.invoke(entity, bukkitEntity); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static void setFallingBlockState(FallingBlockEntity handle, BlockState state) { + try { + FALLING_BLOCK_STATE_SETTER.invoke(handle, state); + } 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 setLookControl(Mob mob, LookControl control) { + try { + LOOK_CONTROL_SETTER.invoke(mob, control); + } 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); + HEAD_HEIGHT.invoke(entity, + HEAD_HEIGHT_METHOD.invoke(entity, entity.getPose(), entity.getDimensions(entity.getPose()))); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public static Entity teleportAcrossWorld(Entity entity, ServerLevel worldserver, PositionImpl location) { + if (FIND_DIMENSION_ENTRY_POINT == null || entity.isRemoved()) + return null; + NPC npc = ((NPCHolder) entity).getNPC(); + PortalInfo sds = null; + try { + sds = location == null ? (PortalInfo) FIND_DIMENSION_ENTRY_POINT.invoke(entity, worldserver) + : new PortalInfo(new Vec3(location.x(), location.y(), location.z()), Vec3.ZERO, entity.getYRot(), + entity.getXRot(), worldserver, (CraftPortalEvent) null); + } catch (Throwable e) { + e.printStackTrace(); + } + if (npc == null || sds == null) + return null; + npc.despawn(DespawnReason.PENDING_RESPAWN); + npc.spawn(new Location(worldserver.getWorld(), sds.pos.x, sds.pos.y, sds.pos.z, sds.yRot, sds.xRot)); + Entity handle = ((CraftEntity) npc.getEntity()).getHandle(); + handle.setDeltaMovement(sds.speed); + handle.portalCooldown = entity.portalCooldown; + try { + PORTAL_ENTRANCE_POS_SETTER.invoke(handle, PORTAL_ENTRANCE_POS_GETTER.invoke(entity)); + } catch (Throwable e) { + e.printStackTrace(); + } + return handle; + } + + public static void updateAI(LivingEntity entity) { + if (entity instanceof Mob) { + Mob handle = (Mob) entity; + handle.getSensing().tick(); + handle.getNavigation().tick(); + handle.getMoveControl().tick(); + handle.getLookControl().tick(); + handle.getJumpControl().tick(); + } else if (entity instanceof MobAI) { + ((MobAI) entity).tickAI(); + } + } + + public static void updateMinecraftAIState(NPC npc, Mob entity) { + if (npc == null) + return; + if (npc.useMinecraftAI()) { + 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 { + clearGoals(npc, entity.goalSelector, entity.targetSelector); + TreeMap behaviorMap = getBehaviorMap(entity); + if (behaviorMap.size() > 0) { + npc.data().set("behavior-map", new TreeMap(behaviorMap)); + behaviorMap.clear(); + } + } + } + + private static final MethodHandle ADVANCEMENTS_PLAYER_SETTER = NMS.getFirstFinalSetter(ServerPlayer.class, + PlayerAdvancements.class); + private static final MethodHandle ATTRIBUTE_PROVIDER_MAP = NMS.getFirstGetter(AttributeSupplier.class, Map.class); + private static final MethodHandle ATTRIBUTE_PROVIDER_MAP_SETTER = NMS.getFirstFinalSetter(AttributeSupplier.class, + Map.class); + private static final MethodHandle ATTRIBUTE_SUPPLIER = NMS.getFirstGetter(AttributeMap.class, + AttributeSupplier.class); + 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_TREE_MAP = NMS.getGetter(Brain.class, "f"); + private static final MethodHandle BUKKITENTITY_FIELD_SETTER = NMS.getSetter(Entity.class, "bukkitEntity"); + private static final MethodHandle CHUNKMAP_UPDATE_PLAYER_STATUS = NMS.getMethodHandle(ChunkMap.class, "a", true, + ServerPlayer.class, boolean.class); + private static final Map, net.minecraft.world.entity.EntityType> CITIZENS_ENTITY_TYPES = Maps + .newHashMap(); + private static final MethodHandle CRAFT_BOSSBAR_HANDLE_FIELD = NMS.getFirstSetter(CraftBossBar.class, + ServerBossEvent.class); + private static final float DEFAULT_SPEED = 1F; + public static MethodHandle ENDERDRAGON_CHECK_WALLS = NMS.getFirstMethodHandleWithReturnType(EnderDragon.class, true, + boolean.class, AABB.class); + private static EntityDataAccessor ENDERMAN_CREEPY = null; + private static final MethodHandle ENTITY_FISH_NUM_IN_SCHOOL = NMS.getFirstSetter(AbstractSchoolingFish.class, + int.class); + private static CustomEntityRegistry ENTITY_REGISTRY; + private static MethodHandle ENTITY_REGISTRY_SETTER; + private static final MethodHandle FALLING_BLOCK_STATE_SETTER = NMS.getFirstSetter(FallingBlockEntity.class, + BlockState.class); + private static final MethodHandle FIND_DIMENSION_ENTRY_POINT = NMS.getFirstMethodHandleWithReturnType(Entity.class, + true, PortalInfo.class, ServerLevel.class); + // first int of block of 4 + private static final MethodHandle FISHING_HOOK_LIFE = NMS.getSetter(FishingHook.class, "i"); + private static final MethodHandle FLYING_MOVECONTROL_FLOAT_GETTER = NMS.getFirstGetter(FlyingMoveControl.class, + boolean.class); + private static final MethodHandle FLYING_MOVECONTROL_FLOAT_SETTER = NMS.getFirstSetter(FlyingMoveControl.class, + boolean.class); + private static final Location FROM_LOCATION = new Location(null, 0, 0, 0); + private static final MethodHandle HEAD_HEIGHT = NMS.getSetter(Entity.class, "bi"); + 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, "bk"); + private static final MethodHandle LOOK_CONTROL_SETTER = NMS.getFirstSetter(Mob.class, LookControl.class); + private static final MethodHandle MAKE_REQUEST = NMS.getMethodHandle(YggdrasilAuthenticationService.class, + "makeRequest", true, URL.class, Object.class, Class.class); + private static MethodHandle MOVE_CONTROLLER_OPERATION = NMS.getSetter(MoveControl.class, "k"); + private static final MethodHandle NAVIGATION_CREATE_PATHFINDER = NMS + .getFirstMethodHandleWithReturnType(PathNavigation.class, true, PathFinder.class, int.class); + private static MethodHandle NAVIGATION_PATH = NMS.getFirstGetter(PathNavigation.class, Path.class); + private static final MethodHandle NAVIGATION_PATHFINDER = NMS.getFirstFinalSetter(PathNavigation.class, + PathFinder.class); + private static final MethodHandle NAVIGATION_WORLD_FIELD = NMS.getFirstSetter(PathNavigation.class, Level.class); + private static final Location PACKET_CACHE_LOCATION = new Location(null, 0, 0, 0); + private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_GETTER = NMS.getFirstGetter(ChunkMap.class, + int.class); + private static final MethodHandle PLAYER_CHUNK_MAP_VIEW_DISTANCE_SETTER = NMS.getFirstSetter(ChunkMap.class, + int.class); + private static final MethodHandle PLAYER_INFO_ENTRIES_LIST = NMS + .getFirstFinalSetter(ClientboundPlayerInfoUpdatePacket.class, List.class); + private static final MethodHandle PLAYERINFO_ENTRIES = PLAYER_INFO_ENTRIES_LIST; + private static MethodHandle PORTAL_ENTRANCE_POS_GETTER = NMS.getGetter(Entity.class, "aw"); + private static MethodHandle PORTAL_ENTRANCE_POS_SETTER = NMS.getSetter(Entity.class, "aw"); + private static final MethodHandle POSITION_CODEC_GETTER = NMS.getFirstGetter(ServerEntity.class, + VecDeltaCodec.class); + private static final MethodHandle PUFFERFISH_C = NMS.getSetter(Pufferfish.class, "bT"); + private static final MethodHandle PUFFERFISH_D = NMS.getSetter(Pufferfish.class, "bU"); + private static EntityDataAccessor RABBIT_TYPE_DATAWATCHER = null; + private static final Random RANDOM = Util.getFastRandom(); + private static final MethodHandle SERVER_ENTITY_GETTER = NMS.getFirstGetter(TrackedEntity.class, + ServerEntity.class); + private static MethodHandle SET_PROFILE_METHOD; + private static final MethodHandle SIZE_FIELD_GETTER = NMS.getFirstGetter(Entity.class, EntityDimensions.class); + private static final MethodHandle SIZE_FIELD_SETTER = NMS.getFirstSetter(Entity.class, EntityDimensions.class); + private static MethodHandle SKULL_META_PROFILE; + private static MethodHandle TEAM_FIELD; + static { + try { + ENTITY_REGISTRY = new CustomEntityRegistry(BuiltInRegistries.ENTITY_TYPE); + ENTITY_REGISTRY_SETTER = NMS.getFinalSetter(BuiltInRegistries.class, "h"); + ENTITY_REGISTRY_SETTER.invoke(ENTITY_REGISTRY); + } catch (Throwable e) { + Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); + e.printStackTrace(); + } + try { + // Middle one + ENDERMAN_CREEPY = (EntityDataAccessor) NMS.getField(EnderMan.class, "bV").get(null); + } catch (Exception e) { + e.printStackTrace(); + } + try { + RABBIT_TYPE_DATAWATCHER = (EntityDataAccessor) NMS + .getFirstStaticGetter(Rabbit.class, EntityDataAccessor.class).invoke(); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PitchableLookControl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PitchableLookControl.java new file mode 100644 index 000000000..cc249647a --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PitchableLookControl.java @@ -0,0 +1,27 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.function.Supplier; + +import net.citizensnpcs.api.npc.NPC; +import net.citizensnpcs.npc.ai.NPCHolder; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.control.LookControl; + +public class PitchableLookControl extends LookControl { + private final Supplier resetOnTick; + + public PitchableLookControl(Mob var0) { + super(var0); + if (var0 instanceof NPCHolder) { + NPC npc = ((NPCHolder) var0).getNPC(); + resetOnTick = () -> npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, false); + } else { + resetOnTick = () -> true; + } + } + + @Override + public boolean resetXRotOnTick() { + return resetOnTick.get(); + } +} \ No newline at end of file diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PlayerAnimationImpl.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PlayerAnimationImpl.java new file mode 100644 index 000000000..a2ab1f2ae --- /dev/null +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/PlayerAnimationImpl.java @@ -0,0 +1,89 @@ +package net.citizensnpcs.nms.v1_20_R1.util; + +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; + +import com.google.common.collect.Maps; + +import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.util.PlayerAnimation; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientboundAnimatePacket; +import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket; +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +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 HURT: + sendPacketNearby(new ClientboundHurtAnimationPacket(player), player, radius); + break; + case SNEAK: + player.setPose(Pose.CROUCHING); + sendEntityData(radius, player); + break; + case START_ELYTRA: + player.startFallFlying(); + break; + case STOP_ELYTRA: + player.stopFallFlying(); + break; + case START_USE_MAINHAND_ITEM: + player.startUsingItem(InteractionHand.MAIN_HAND); + sendEntityData(radius, player); + player.getBukkitEntity().setMetadata("citizens-using-item-remaining-ticks", + new FixedMetadataValue(CitizensAPI.getPlugin(), player.getUseItemRemainingTicks())); + break; + case START_USE_OFFHAND_ITEM: + player.startUsingItem(InteractionHand.OFF_HAND); + sendEntityData(radius, player); + player.getBukkitEntity().setMetadata("citizens-using-item-remaining-ticks", + new FixedMetadataValue(CitizensAPI.getPlugin(), player.getUseItemRemainingTicks())); + break; + case STOP_SNEAKING: + player.setPose(Pose.STANDING); + sendEntityData(radius, player); + break; + case STOP_USE_ITEM: + player.stopUsingItem(); + sendEntityData(radius, player); + break; + default: + throw new UnsupportedOperationException(); + } + } + + protected static void playDefaultAnimation(ServerPlayer player, int radius, int code) { + sendPacketNearby(new ClientboundAnimatePacket(player, code), player, radius); + } + + private static void sendEntityData(int radius, final ServerPlayer player) { + if (!player.getEntityData().isDirty()) + return; + sendPacketNearby(new ClientboundSetEntityDataPacket(player.getId(), player.getEntityData().packDirty()), player, + radius); + } + + protected static void sendPacketNearby(Packet packet, ServerPlayer player, int radius) { + NMSImpl.sendPacketNearby(player.getBukkitEntity(), player.getBukkitEntity().getLocation(), packet, radius); + } + + private static Map DEFAULTS = Maps.newEnumMap(PlayerAnimation.class); + static { + DEFAULTS.put(PlayerAnimation.ARM_SWING, 0); + DEFAULTS.put(PlayerAnimation.LEAVE_BED, 2); + DEFAULTS.put(PlayerAnimation.ARM_SWING_OFFHAND, 3); + DEFAULTS.put(PlayerAnimation.CRIT, 4); + DEFAULTS.put(PlayerAnimation.MAGIC_CRIT, 5); + } +} diff --git a/v1_8_R3/pom.xml b/v1_8_R3/pom.xml index 851637b80..8c44f1ba2 100644 --- a/v1_8_R3/pom.xml +++ b/v1_8_R3/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.31-SNAPSHOT + 2.0.32-SNAPSHOT citizens-v1_8_R3