From 39364b30f3f167e1089c85475b2171fe59be1ee6 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Fri, 28 Jun 2024 23:25:33 +0800 Subject: [PATCH] Update to Minecraft 1.21 --- .github/workflows/gradle.yml | 4 +- .github/workflows/pr.yml | 4 +- README.md | 33 +- arclight-common/build.gradle | 2 +- .../common/bridge/bukkit/ItemMetaBridge.java | 13 - .../common/bridge/bukkit/MaterialBridge.java | 15 +- .../entity/AreaEffectCloudEntityBridge.java | 2 - .../bridge/core/entity/EntityBridge.java | 23 +- .../core/entity/LivingEntityBridge.java | 46 +- .../bridge/core/entity/MobEntityBridge.java | 3 - .../core/entity/item/ItemEntityBridge.java | 11 - .../entity/player/PlayerEntityBridge.java | 39 - .../player/ServerPlayerEntityBridge.java | 23 +- .../entity/projectile/ArrowEntityBridge.java | 3 - .../DamagingProjectileEntityBridge.java | 2 - .../inventory/container/ContainerBridge.java | 9 - .../common/DiscardedPayloadBridge.java | 10 + .../ServerCommonPacketListenerBridge.java | 5 +- .../login/ServerLoginNetHandlerBridge.java | 4 +- .../play/ServerPlayNetHandlerBridge.java | 4 + .../PlayerInteractionManagerBridge.java | 8 + .../server/management/PlayerListBridge.java | 3 + .../bridge/core/util/DamageSourceBridge.java | 12 + .../bridge/core/util/FoodStatsBridge.java | 6 +- .../bridge/core/world/TeleporterBridge.java | 10 +- .../common/bridge/core/world/WorldBridge.java | 7 - .../world/damagesource/CombatEntryBridge.java | 10 + .../damagesource/CombatTrackerBridge.java | 8 + .../bridge/core/world/item/ItemBridge.java | 5 - .../core/world/item/ItemStackBridge.java | 41 +- .../item/crafting/RecipeManagerBridge.java | 2 - .../core/world/level/block/BlockBridge.java | 31 +- .../StructureTemplateBridge.java | 15 - .../portal/DimensionTransitionBridge.java | 10 + .../core/world/spawner/BaseSpawnerBridge.java | 12 - .../core/world/storage/MapDataBridge.java | 3 +- .../world/storage/loot/LootContextBridge.java | 12 - .../mixin/bukkit/CraftEventFactoryMixin.java | 3 +- .../mixin/bukkit/CraftInventoryViewMixin.java | 2 +- .../mixin/bukkit/CraftItemStackMixin.java | 88 -- .../mixin/bukkit/CraftMetaItemMixin.java | 177 +--- .../common/mixin/bukkit/MaterialMixin.java | 3 +- .../mixin/bukkit/RecipeIteratorMixin.java | 43 - .../DataComponentPatch_BuilderMixin.java | 50 ++ .../mixin/core/fluid/FlowingFluidMixin.java | 20 +- .../ServerCommonPacketListenerImplMixin.java | 88 +- ...rConfigurationPacketListenerImplMixin.java | 17 + ...erGamePacketListenerImpl_HandlerMixin.java | 107 +++ .../ServerHandshakeNetHandlerMixin.java | 143 ++- .../network/ServerLoginNetHandlerMixin.java | 53 +- .../network/ServerPlayNetHandlerMixin.java | 583 +++++------- .../network/ServerStatusNetHandlerMixin.java | 2 +- .../core/network/SynchedEntityDataMixin.java | 12 +- .../protocol/PacketThreadUtilMixin.java | 25 +- .../common/CustomPayloadPacketMixin.java | 27 + .../common/custom/DiscardedPayloadMixin.java | 37 + .../ClientboundSystemChatPacketMixin.java | 3 +- .../core/server/MinecraftServerMixin.java | 177 ++-- .../core/server/PlayerAdvancementsMixin.java | 2 +- .../server/ServerAdvancementManagerMixin.java | 28 + .../core/server/level/ChunkHolderMixin.java | 32 +- .../core/server/level/ChunkMapMixin.java | 6 +- .../server/level/DistanceManagerMixin.java | 20 - .../core/server/level/ServerEntityMixin.java | 87 +- .../core/server/level/ServerLevelMixin.java | 78 +- .../level}/ServerPlayerMixin.java | 385 ++++---- .../ServerPlayer_RespawnPosAngleMixin.java | 33 + .../server/management/PlayerListMixin.java | 298 ++----- .../management/ServerPlayerGameModeMixin.java | 356 +++----- .../mixin/core/util/StringUtilMixin.java | 26 + .../util/thread/BlockableEventLoopMixin.java | 20 + .../world/damagesource/CombatEntryMixin.java | 22 + .../damagesource/CombatTrackerMixin.java | 46 + .../world/damagesource/DamageSourceMixin.java | 86 +- .../damagesource/DamageSourcesMixin.java | 18 + .../effect/HealOrHarmMobEffectMixin.java | 3 +- .../world/effect/HungerMobEffectMixin.java | 3 +- .../core/world/effect/MobEffectUtilMixin.java | 15 +- .../effect/RegenerationMobEffectMixin.java | 3 +- .../effect/SaturationMobEffectMixin.java | 10 +- .../entity/AreaEffectCloudEntityMixin.java | 231 +---- .../mixin/core/world/entity/EntityMixin.java | 482 ++++------ .../core/world/entity/EntityTypeMixin.java | 13 +- .../core/world/entity/ExperienceOrbMixin.java | 65 +- .../core/world/entity/LeashableMixin.java | 57 ++ .../core/world/entity/LivingEntityMixin.java | 831 +++++++----------- .../mixin/core/world/entity/MobMixin.java | 133 +-- .../core/world/entity/NeutralMobMixin.java | 38 + .../core/world/entity/PathfinderMobMixin.java | 4 - .../ai/behavior/StartAttackingMixin.java | 74 +- .../StopAttackingIfTargetInvalidMixin.java | 5 +- .../entity/ai/goal/FollowOwnerGoalMixin.java | 45 - .../core/world/entity/animal/AnimalMixin.java | 10 +- .../core/world/entity/animal/BeeMixin.java | 4 +- .../world/entity/animal/BucketableMixin.java | 3 +- .../core/world/entity/animal/CatMixin.java | 10 +- .../core/world/entity/animal/SheepMixin.java | 9 - .../entity/animal/TameableAnimalMixin.java | 18 +- .../core/world/entity/animal/WolfMixin.java | 8 +- .../animal/armadillo/ArmadilloMixin.java | 41 + .../world/entity/animal/camel/CamelMixin.java | 11 - .../entity/animal/frog/TadpoleMixin.java | 24 + .../animal/horse/AbstractHorseMixin.java | 57 ++ .../boss/enderdragon/EnderDragonMixin.java | 3 +- .../entity/boss/wither/WitherBossMixin.java | 171 +--- .../entity/decoration/ArmorStandMixin.java | 39 +- .../entity/decoration/ItemFrameMixin.java | 39 +- .../decoration/LeashFenceKnotEntityMixin.java | 49 +- .../entity/decoration/PaintingMixin.java | 40 + ...xin.java => BlockAttachedEntityMixin.java} | 20 +- .../world/entity/item/ItemEntityMixin.java | 106 +-- .../world/entity/item/PrimedTntMixin.java | 26 +- .../entity/monster/AbstractSkeletonMixin.java | 4 +- .../world/entity/monster/CreeperMixin.java | 8 +- .../world/entity/monster/EnderManMixin.java | 24 +- .../world/entity/monster/ShulkerMixin.java | 76 +- .../Silverfish_WakeUpFriendsGoalMixin.java | 56 +- .../core/world/entity/monster/SlimeMixin.java | 13 +- .../world/entity/monster/SpiderMixin.java | 3 +- .../core/world/entity/monster/WitchMixin.java | 18 +- .../world/entity/monster/ZombieMixin.java | 38 +- .../entity/monster/ZombieVillagerMixin.java | 6 +- .../core/world/entity/player/PlayerMixin.java | 297 ++----- .../entity/projectile/AbstractArrowMixin.java | 58 +- .../AbstractHurtingProjectileMixin.java | 37 +- .../entity/projectile/ArrowEntityMixin.java | 44 - .../entity/projectile/EyeOfEnderMixin.java | 7 - .../entity/projectile/FireballMixin.java | 10 - .../entity/projectile/FishingHookMixin.java | 178 ++-- .../entity/projectile/LargeFireballMixin.java | 14 +- .../entity/projectile/ProjectileMixin.java | 25 +- .../entity/projectile/SmallFireballMixin.java | 23 +- .../projectile/ThrowableProjectileMixin.java | 7 - .../entity/projectile/ThrownEggMixin.java | 8 + .../projectile/ThrownEnderpearlMixin.java | 2 +- .../ThrownExperienceBottleMixin.java | 4 +- .../entity/projectile/ThrownPotionMixin.java | 25 +- .../entity/projectile/ThrownTridentMixin.java | 12 - .../entity/projectile/WindChargeMixin.java | 24 - .../windcharge/AbstractWindChargeMixin.java | 30 + .../world/entity/raid/RaidManagerMixin.java | 6 +- .../core/world/entity/raid/RaidMixin.java | 14 +- .../core/world/entity/raider/RaiderMixin.java | 13 - .../entity/vehicle/AbstractMinecartMixin.java | 167 +--- .../core/world/entity/vehicle/BoatMixin.java | 9 +- .../entity/vehicle/VehicleEntityMixin.java | 86 +- .../mixin/core/world/food/FoodDataMixin.java | 36 +- .../inventory/AbstractContainerMenuMixin.java | 314 ++----- .../core/world/inventory/AnvilMenuMixin.java | 221 +---- .../inventory/CraftingContainerMixin.java | 19 + .../world/inventory/CraftingMenuMixin.java | 17 +- .../inventory/EnchantmentContainerMixin.java | 266 ++---- .../inventory/GrindstoneContainerMixin.java | 2 +- .../HorseInventoryContainerMixin.java | 4 +- .../SmithingTableContainerMixin.java | 11 +- .../mixin/core/world/item/ArmorItemMixin.java | 57 ++ .../core/world/item/ArmorStandItemMixin.java | 16 +- .../mixin/core/world/item/BlockItemMixin.java | 38 +- .../mixin/core/world/item/BoatItemMixin.java | 87 +- .../mixin/core/world/item/BowItemMixin.java | 65 -- .../core/world/item/ChorusFruitItemMixin.java | 69 +- .../core/world/item/CrossbowItemMixin.java | 55 -- .../mixin/core/world/item/DyeItemMixin.java | 15 +- .../mixin/core/world/item/EggItemMixin.java | 14 +- .../world/item/EnderCrystalItemMixin.java | 25 +- .../core/world/item/EnderEyeItemMixin.java | 14 +- .../core/world/item/EnderPearlItemMixin.java | 4 +- .../core/world/item/FishingRodItemMixin.java | 72 +- .../world/item/FlintAndSteelItemMixin.java | 5 +- .../mixin/core/world/item/ItemStackMixin.java | 59 +- .../mixin/core/world/item/LeadItemMixin.java | 68 +- .../mixin/core/world/item/MapItemMixin.java | 24 - .../core/world/item/MerchantOfferMixin.java | 23 +- .../core/world/item/MinecartItemMixin.java | 16 +- .../core/world/item/PotionItemMixin.java | 14 +- .../world/item/ProjectileWeaponItemMixin.java | 41 + .../core/world/item/SnowballItemMixin.java | 4 +- .../core/world/item/TridentItemMixin.java | 30 +- .../world/item/crafting/IngredientMixin.java | 36 +- .../item/crafting/RecipeManagerMixin.java | 114 +-- .../enchantment/DamageEnchantmentMixin.java | 20 - .../FrostWalkerEnchantmentMixin.java | 48 - .../effects/ApplyMobEffectMixin.java | 22 + .../item/enchantment/effects/IgniteMixin.java | 39 + .../effects/ReplaceBlockMixin.java | 21 + .../enchantment/effects/ReplaceDiskMixin.java | 21 + .../core/world/level/ExplosionMixin.java | 298 ++----- .../mixin/core/world/level/LevelMixin.java | 24 +- .../Level_ExplosionInteractionMixin.java | 2 +- .../world/level/block/BaseFireBlockMixin.java | 11 +- .../core/world/level/block/BedBlockMixin.java | 3 +- .../level/block/BigDripleafBlockMixin.java | 2 +- .../core/world/level/block/BlockMixin.java | 19 +- .../world/level/block/ButtonBlockMixin.java | 8 +- .../world/level/block/CampfireBlockMixin.java | 4 +- .../world/level/block/CommandBlockMixin.java | 47 +- .../level/block/ComposterBlockMixin.java | 45 +- .../level/block/DetectorRailBlockMixin.java | 30 +- .../level/block/DispenserBlockMixin.java | 24 + .../block/DispenserBlockMixin_Accessor.java | 18 - .../level/block/DragonEggBlockMixin.java | 30 +- .../world/level/block/DropperBlockMixin.java | 87 +- .../level/block/EndGatewayBlockMixin.java | 25 + .../level/block/EndPortalBlockMixin.java | 52 +- .../world/level/block/FireBlockMixin.java | 2 - .../world/level/block/LeverBlockMixin.java | 8 +- .../level/block/LightningRodBlockMixin.java | 13 - .../level/block/NetherPortalBlockMixin.java | 41 +- .../world/level/block/PortalInfoMixin.java | 34 - .../world/level/block/PortalShapeMixin.java | 73 +- .../level/block/RedstoneOreBlockMixin.java | 9 +- .../level/block/RespawnAnchorBlockMixin.java | 5 +- .../level/block/SculkSensorBlockMixin.java | 21 +- .../world/level/block/SignBlockMixin.java | 9 +- .../level/block/SweetBerryBushBlockMixin.java | 20 +- .../core/world/level/block/TntBlockMixin.java | 11 +- .../level/block/WitherSkullBlockMixin.java | 54 +- .../AbstractFurnaceBlockEntityMixin.java | 53 +- .../block/entity/BeaconTileEntityMixin.java | 15 +- .../block/entity/BeehiveBlockEntityMixin.java | 47 +- .../block/entity/BellBlockEntityMixin.java | 2 +- .../level/block/entity/BlockEntityMixin.java | 34 +- .../entity/BrewingStandBlockEntityMixin.java | 82 +- .../entity/BrushableBlockEntityMixin.java | 8 - .../entity/CampfireBlockEntityMixin.java | 68 +- .../ChiseledBookShelfBlockEntityMixin.java | 6 - .../block/entity/CommandBlockLogicMixin.java | 15 - .../entity/EndGatewayBlockEntityMixin.java | 74 -- .../block/entity/HopperBlockEntityMixin.java | 10 +- .../block/entity/JukeboxBlockEntityMixin.java | 19 +- .../entity/SculkCatalystBlockEntityMixin.java | 5 - .../trailspawner/TrialSpawnerMixin.java | 23 + .../block/state/BlockBehaviourMixin.java | 40 +- .../level/chunk/ChunkGeneratorMixin.java | 26 +- .../chunk/storage/ChunkSerializerMixin.java | 4 +- .../chunk/storage/RegionFileCacheMixin.java | 2 +- .../level/chunk/storage/RegionFileMixin.java | 47 + .../PersistentEntitySectionManagerMixin.java | 7 +- .../gameevent/GameEventDispatcherMixin.java | 32 +- .../vibrations/VibrationListenerMixin.java | 63 +- .../feature/EndPlatformFeatureMixin.java | 70 ++ .../structure/StructurePieceMixin.java | 13 +- .../StructureTemplateMixin.java | 236 +---- .../portal/DimensionTransitionMixin.java | 49 ++ .../world/level/portal/PortalForcerMixin.java | 47 +- .../level/redstone/NeighborUpdaterMixin.java | 56 +- .../level/saveddata/maps/MapDataMixin.java | 8 +- .../MapItemSavedData_HoldingPlayerMixin.java | 8 +- .../storage/loot/LootDataManagerMixin.java | 34 - .../level/storage/loot/LootDataTypeMixin.java | 24 + .../level/storage/loot/LootTableMixin.java | 14 +- .../functions/LootingEnchantBonusMixin.java | 51 -- .../loot/parameters/LootParametersMixin.java | 15 - .../RandomChanceWithLootingMixin.java | 33 - .../core/world/spawner/BaseSpawnerMixin.java | 158 +--- .../world/spawner/NaturalSpawnerMixin.java | 2 +- .../core/world/storage/PlayerDataMixin.java | 21 +- .../EntityDataManagerMixin_Optimize.java | 25 - ...ain_ServerShutdownThreadMixin_Vanilla.java | 6 +- .../animal/frog/TadpoleMixin_Vanilla.java | 23 - .../entity/monster/ZombieMixin_Vanilla.java | 19 - .../player/ServerPlayerMixin_Vanilla.java | 112 --- .../world/item/ItemStackMixin_Vanilla.java | 10 +- .../block/RedstoneOreBlockMixin_Vanilla.java | 14 - ...stractFurnaceBlockEntityMixin_Vanilla.java | 66 -- .../StructureTemplateMixin_Vanilla.java | 214 ----- .../common/mod/ArclightConstants.java | 3 - .../common/mod/ArclightMixinPlugin.java | 2 + .../common/mod/server/BukkitRegistry.java | 13 +- .../common/mod/server/RunnableInPlace.java | 12 + .../mod/server/block/DispenserBlockHooks.java | 28 + .../server/entity/ArclightModWindCharge.java | 12 + .../mod/server/entity/EntityClassLookup.java | 23 +- .../server/event/ArclightEventFactory.java | 48 +- .../mod/server/world/LevelPersistentData.java | 7 +- .../common/mod/util/ArclightCaptures.java | 10 + .../ArclightCustomQueryAnswerPayload.java | 13 + .../arclight/common/mod/util/Blackhole.java | 14 + .../arclight/common/mod/util/ClassDump.java | 13 + .../common/mod/util/DelegateWorldInfo.java | 58 +- .../mod/util/DiscardedPayloadCodec.java | 29 + .../common/mod/util/EntityDamageResult.java | 14 + .../common/mod/util/VelocitySupport.java | 3 +- .../src/main/resources/arclight.accesswidener | 109 ++- .../resources/mixins.arclight.bukkit.json | 1 - .../main/resources/mixins.arclight.core.json | 53 +- .../mixins.arclight.impl.optimization.json | 1 - ...rCommonPacketListenerImplMixin_Fabric.java | 13 +- ...urationPacketListenerImplMixin_Fabric.java | 25 + .../core/world/entity/EntityMixin_Fabric.java | 3 - .../player/ServerPlayerMixin_Fabric.java | 2 - .../level/block/FireBlockMixin_Fabric.java | 28 +- .../BrewingStandBlockEntityMixin_Fabric.java | 52 -- .../resources/mixins.arclight.fabric.json | 1 + arclight-forge/build.gradle | 12 +- .../mixin/bukkit/MaterialMixin_Forge.java | 16 - ...erCommonPacketListenerImplMixin_Forge.java | 4 - .../ServerLoginNetHandlerMixin_Forge.java | 7 - .../ServerPlayNetHandlerMixin_Forge.java | 2 +- ...undCustomQueryAnswerPacketMixin_Forge.java | 37 + .../ServerPlayerGameModeMixin_Forge.java | 2 +- .../core/world/entity/EntityMixin_Forge.java | 77 -- .../world/entity/LivingEntityMixin_Forge.java | 63 +- .../animal/frog/TadpoleMixin_Forge.java | 13 - .../entity/item/ItemEntityMixin_Forge.java | 18 - .../entity/monster/ZombieMixin_Forge.java | 20 - .../entity/player/PlayerMixin_Forge.java | 35 - .../player/ServerPlayerMixin_Forge.java | 211 ----- .../core/world/food/FoodDataMixin_Forge.java | 36 - .../AbstractContainerMenuMixin_Forge.java | 10 - .../core/world/item/ItemMixin_Forge.java | 6 - .../core/world/item/ItemStackMixin_Forge.java | 51 +- .../crafting/RecipeManagerMixin_Forge.java | 14 - .../world/level/BaseSpawnerMixin_Forge.java | 18 - .../core/world/level/LevelMixin_Forge.java | 6 - .../world/level/block/BlockMixin_Forge.java | 30 - .../level/block/FireBlockMixin_Forge.java | 2 +- .../level/block/TntBlockMixin_Forge.java | 9 +- ...AbstractFurnaceBlockEntityMixin_Forge.java | 67 -- .../BrewingStandBlockEntityMixin_Forge.java | 6 - .../StructureTemplateMixin_Forge.java | 14 - .../storage/loot/LootContextMixin_Forge.java | 10 - .../forge/RegisterChannelsTaskMixin.java | 2 +- .../mod/event/EntityEventDispatcher.java | 2 +- .../permission/ArclightPermissionHandler.java | 2 +- .../main/resources/mixins.arclight.forge.json | 1 + arclight-neoforge/build.gradle | 7 +- ...ommonPacketListenerImplMixin_NeoForge.java | 5 - ...ationPacketListenerImplMixin_NeoForge.java | 38 + .../ServerLoginNetHandlerMixin_NeoForge.java | 9 - .../CustomPayloadPacketMixin_NeoForge.java | 27 + ...CustomQueryAnswerPacketMixin_NeoForge.java | 37 + .../ServerPlayerGameModeMixin_NeoForge.java | 4 +- .../world/entity/EntityMixin_NeoForge.java | 85 -- .../entity/LivingEntityMixin_NeoForge.java | 64 +- .../animal/frog/TadpoleMixin_NeoForge.java | 13 - .../entity/item/ItemEntityMixin_NeoForge.java | 18 - .../entity/monster/ZombieMixin_NeoForge.java | 19 - .../entity/player/PlayerMixin_NeoForge.java | 36 - .../player/ServerPlayerMixin_NeoForge.java | 200 +---- .../world/food/FoodDataMixin_NeoForge.java | 36 - .../AbstractContainerMenuMixin_NeoForge.java | 10 - .../core/world/item/ItemMixin_NeoForge.java | 6 - .../world/item/ItemStackMixin_NeoForge.java | 81 +- .../world/item/ShearsItemMixin_NeoForge.java | 2 +- .../crafting/RecipeManagerMixin_NeoForge.java | 20 - .../level/BaseSpawnerMixin_NeoForge.java | 17 - .../core/world/level/LevelMixin_NeoForge.java | 8 +- .../level/block/BlockMixin_NeoForge.java | 35 +- .../level/block/CropBlockMixin_NeoForge.java | 4 +- .../level/block/TntBlockMixin_NeoForge.java | 5 +- ...tractFurnaceBlockEntityMixin_NeoForge.java | 67 -- ...BrewingStandBlockEntityMixin_NeoForge.java | 6 - .../StructureTemplateMixin_NeoForge.java | 14 - .../loot/LootContextMixin_NeoForge.java | 10 - .../mixin/forge/PacketDistributorMixin.java | 24 +- .../mod/event/BlockBreakEventDispatcher.java | 5 +- .../mod/event/EntityEventDispatcher.java | 2 +- .../permission/ArclightPermissionHandler.java | 2 +- .../mod/util/ArclightBlockSnapshot.java | 2 +- .../{mods.toml => neoforge.mods.toml} | 0 .../resources/mixins.arclight.neoforge.json | 3 + bootstrap/build.gradle | 23 +- .../io/izzel/arclight/server/Launcher.java | 4 +- .../arclight/boot/AbstractBootstrap.java | 2 +- .../izzel/arclight/boot/asm/AsyncCatcher.java | 5 +- .../arclight/boot/asm/EnumDefinalizer.java | 3 +- .../neoforge/mod/ArclightJarInJarAdaptor.java | 77 -- .../neoforge/mod/ArclightJarInJarFilter.java | 38 + .../neoforge/mod/ArclightLaunchHandler.java | 4 +- .../mod/ArclightLocator_Neoforge.java | 85 +- ...ed.neoforgespi.locating.IDependencyLocator | 1 + ...orgespi.locating.IModFileCandidateLocator} | 0 build.gradle | 21 +- .../izzel/arclight/i18n/conf/CompatSpec.java | 7 + .../src/main/resources/META-INF/arclight.conf | 1 + .../main/resources/META-INF/i18n/en_us.conf | 5 + .../main/resources/META-INF/i18n/zh_cn.conf | 5 + 378 files changed, 5490 insertions(+), 9869 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/DiscardedPayloadBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatEntryBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatTrackerBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/portal/DimensionTransitionBridge.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/RecipeIteratorMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/core/component/DataComponentPatch_BuilderMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerGamePacketListenerImpl_HandlerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/common/CustomPayloadPacketMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/common/custom/DiscardedPayloadMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/ServerAdvancementManagerMixin.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/{world/entity/player => server/level}/ServerPlayerMixin.java (69%) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayer_RespawnPosAngleMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/StringUtilMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/thread/BlockableEventLoopMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatEntryMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatTrackerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LeashableMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/NeutralMobMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/goal/FollowOwnerGoalMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/armadillo/ArmadilloMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/PaintingMixin.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/{HangingEntityMixin.java => BlockAttachedEntityMixin.java} (85%) delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/WindChargeMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/windcharge/AbstractWindChargeMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingContainerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorItemMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BowItemMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/CrossbowItemMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MapItemMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ProjectileWeaponItemMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/DamageEnchantmentMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/FrostWalkerEnchantmentMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ApplyMobEffectMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/IgniteMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceBlockMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceDiskMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin_Accessor.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndGatewayBlockMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalInfoMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/trailspawner/TrialSpawnerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/feature/EndPlatformFeatureMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/DimensionTransitionMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataManagerMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataTypeMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/functions/LootingEnchantBonusMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/parameters/LootParametersMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/predicates/RandomChanceWithLootingMixin.java delete mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/optimization/general/EntityDataManagerMixin_Optimize.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/server/RunnableInPlace.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/server/block/DispenserBlockHooks.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/ArclightModWindCharge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCustomQueryAnswerPayload.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ClassDump.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DiscardedPayloadCodec.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/util/EntityDamageResult.java create mode 100644 arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerConfigurationPacketListenerImplMixin_Fabric.java create mode 100644 arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_Forge.java create mode 100644 arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerConfigurationPacketListenerImplMixin_NeoForge.java create mode 100644 arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/common/CustomPayloadPacketMixin_NeoForge.java create mode 100644 arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_NeoForge.java rename arclight-neoforge/src/main/resources/META-INF/{mods.toml => neoforge.mods.toml} (100%) delete mode 100644 bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarAdaptor.java create mode 100644 bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarFilter.java create mode 100644 bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator rename bootstrap/src/neoforge/resources/META-INF/services/{net.neoforged.neoforgespi.locating.IModLocator => net.neoforged.neoforgespi.locating.IModFileCandidateLocator} (100%) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ec1a9d953..b638de2bc 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v1 with: - java-version: '17' + java-version: '21' - name: Cache Gradle User Files uses: actions/cache@v1 with: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4d8e3e9db..ef48b69b9 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v1 with: - java-version: '17' + java-version: '21' - name: Cache Gradle User Files uses: actions/cache@v1 with: diff --git a/README.md b/README.md index 5147eaed4..c0b814e60 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,30 @@ # Arclight -A Bukkit server implementation utilizing Mixin. +A Bukkit server implementation on common mod loaders. ![Downloads](https://img.shields.io/github/downloads/IzzelAliz/Arclight/total?style=flat-square) ![GitHub](https://img.shields.io/github/license/IzzelAliz/Arclight?style=flat-square) -| Release | Forge | NeoForge | Fabric | Status | Downloads | -|:---------------------|:--------|:---------|:-------|:------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| Whisper (1.20.4) | 49.0.49 | 20.4.234 | 0.97.0 | ACTIVE | [![1.20.4 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Whisper&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3AWhisper) | -| Trials (1.20-1.20.1) | 47.2.20 | - | - | LTS | [![1.20.1 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Trials&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3ATrials) | -| Horn (1.19-1.19.2) | 43.3.7 | - | - | LTS | [![Horn Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-19?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) | +| Release | Forge | NeoForge | Fabric | Status | Downloads | +|:---------------------|:--------|:------------|:--------|:------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| Feudal Kings (1.21) | 51.0.5 | 21.0.4-beta | 0.100.1 | ACTIVE | [![1.21 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=FeudalKings&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3AFeudalKings) | +| Whisper (1.20.4) | 49.0.49 | 20.4.234 | 0.97.0 | ACTIVE | [![1.20.4 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Whisper&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3AWhisper) | +| Trials (1.20-1.20.1) | 47.2.20 | - | - | LTS | [![1.20.1 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Trials&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3ATrials) | **Legacy versions**:
-| Release | Forge | Status | Build | -|:-------------------:|:-------:|:-------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| Net (1.20.2) | 48.1.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/Net%2F1.0.1) | [![1.20.2 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Net&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3ANet) | -| Executions (1.19.4) | 45.2.6 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/Executions%2F1.0.6) | [![1.19.4 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Executions&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3AExecutions) | -| Great Horn (1.19.3) | 44.1.22 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/GreatHorn/1.0.3) | [![1.19 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=GreatHorn&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) | -| 1.18.x | 40.2.14 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.18%2F1.0.10) | [![1.18 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=1.18&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) | -| 1.17.x | 37.1.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.17/1.0.2) | [![1.17 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-17?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-17) | -| 1.16.x | 36.2.39 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.16%2F1.0.25) | [![1.16 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=1.16&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) | -| 1.15.x | 31.2.48 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.15/1.0.19) | [![1.15 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-15?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-15) | -| 1.14.x | 28.2.0 | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.0.6) | [![1.14 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight) | +| Release | Forge | NeoForge | Fabric | Status | Downloads | +|:--------------------|:--------|:---------|:-------|:-------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| Net (1.20.2) | 48.1.0 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/Net%2F1.0.1) | [![1.20.2 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Net&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3ANet) | +| Executions (1.19.4) | 45.2.6 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/Executions%2F1.0.6) | [![1.19.4 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=Executions&style=flat-square)](https://github.com/IzzelAliz/Arclight/actions?query=branch%3AExecutions) | +| Great Horn (1.19.3) | 44.1.22 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/GreatHorn/1.0.3) | [![1.19 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=GreatHorn&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) | +| Horn (1.19-1.19.2) | 43.3.7 | - | - | LEGACY | [![Horn Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-19?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-19) | +| 1.18.x | 40.2.14 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.18%2F1.0.10) | [![1.18 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=1.18&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-18) | +| 1.17.x | 37.1.0 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.17/1.0.2) | [![1.17 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-17?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-17) | +| 1.16.x | 36.2.39 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.16%2F1.0.25) | [![1.16 Status](https://img.shields.io/github/actions/workflow/status/IzzelAliz/Arclight/gradle.yml?branch=1.16&style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-16) | +| 1.15.x | 31.2.48 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.15/1.0.19) | [![1.15 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight-15?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight-15) | +| 1.14.x | 28.2.0 | | | [LEGACY](https://github.com/IzzelAliz/Arclight/releases/tag/1.0.6) | [![1.14 Status](https://img.shields.io/appveyor/build/IzzelAliz/arclight?style=flat-square)](https://ci.appveyor.com/project/IzzelAliz/arclight) | * Legacy version still accepts pull requests. diff --git a/arclight-common/build.gradle b/arclight-common/build.gradle index a14cbfd39..ac2ef62e6 100644 --- a/arclight-common/build.gradle +++ b/arclight-common/build.gradle @@ -19,7 +19,7 @@ loom { arclight { mcVersion = minecraftVersion forgeVersion = project.ext.forgeVersion - bukkitVersion = 'v1_20_R3' + bukkitVersion = 'v1_21_R1' accessTransformer = project.file('bukkit.at') extraMapping = project(':arclight-common').file('extra_mapping.tsrg') } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/ItemMetaBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/ItemMetaBridge.java index b0675f26a..0797d623e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/ItemMetaBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/ItemMetaBridge.java @@ -1,18 +1,5 @@ package io.izzel.arclight.common.bridge.bukkit; -import java.util.Map; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; - public interface ItemMetaBridge { - CompoundTag bridge$getForgeCaps(); - - void bridge$setForgeCaps(CompoundTag nbt); - - void bridge$offerUnhandledTags(CompoundTag nbt); - - Map bridge$getUnhandledTags(); - - void bridge$setUnhandledTags(Map tags); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/MaterialBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/MaterialBridge.java index 201d04a3a..f7990bf70 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/MaterialBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/MaterialBridge.java @@ -1,6 +1,10 @@ package io.izzel.arclight.common.bridge.bukkit; import io.izzel.arclight.i18n.conf.MaterialPropertySpec; +import net.minecraft.core.component.DataComponents; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import org.bukkit.block.BlockState; import org.bukkit.craftbukkit.v.block.CraftBlock; @@ -8,9 +12,6 @@ import org.bukkit.inventory.meta.ItemMeta; import javax.annotation.Nullable; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; import java.util.function.Function; public interface MaterialBridge { @@ -40,19 +41,19 @@ public interface MaterialBridge { boolean bridge$shouldApplyStateFactory(); - default Item bridge$getCraftRemainingItem(Item item) { + default Item bridge$getCraftRemainingItem(Item item) { return item.getCraftingRemainingItem(); } default int bridge$forge$getMaxStackSize(Item item) { - return item.getMaxStackSize(); + return item.getDefaultMaxStackSize(); } default int bridge$forge$getDurability(Item item) { - return item.getMaxDamage(); + return item.components().getOrDefault(DataComponents.MAX_DAMAGE, 0); } - default int bridge$forge$getBurnTime(Item item) { + default int bridge$forge$getBurnTime(Item item) { var result = AbstractFurnaceBlockEntity.getFuel().get(item); return result != null ? result : 0; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/AreaEffectCloudEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/AreaEffectCloudEntityBridge.java index 964581e22..93b7c27f2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/AreaEffectCloudEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/AreaEffectCloudEntityBridge.java @@ -1,6 +1,4 @@ package io.izzel.arclight.common.bridge.core.entity; public interface AreaEffectCloudEntityBridge { - - void bridge$refreshEffects(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/EntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/EntityBridge.java index 8b3df1b2f..06d8191ad 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/EntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/EntityBridge.java @@ -5,22 +5,21 @@ import io.izzel.tools.product.Product; import io.izzel.tools.product.Product4; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftEntity; +import org.bukkit.craftbukkit.v.event.CraftPortalEvent; import org.bukkit.event.entity.EntityRemoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.projectiles.ProjectileSource; import java.util.List; public interface EntityBridge extends ICommandSourceBridge, InjectEntityBridge { - Entity bridge$teleportTo(ServerLevel world, Vec3 blockPos); - - void bridge$setOnFire(int tick, boolean callEvent); + void bridge$setOnFire(float seconds, boolean callEvent); CraftEntity bridge$getBukkitEntity(); @@ -52,10 +51,6 @@ public interface EntityBridge extends ICommandSourceBridge, InjectEntityBridge { void bridge$postTick(); - boolean bridge$removePassenger(Entity passenger); - - boolean bridge$addPassenger(Entity entity); - List bridge$getPassengers(); void bridge$setRideCooldown(int rideCooldown); @@ -66,12 +61,18 @@ public interface EntityBridge extends ICommandSourceBridge, InjectEntityBridge { void bridge$setLastLavaContact(BlockPos pos); - Vec3 bridge$getLastTpPos(); - void bridge$revive(); void bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause cause); + CraftPortalEvent bridge$callPortalEvent(Entity entity, Location exit, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius); + + boolean bridge$pluginRemoved(); + + boolean bridge$isForceDrops(); + + void bridge$setForceDrops(boolean b); + default boolean bridge$forge$isPartEntity() { return this instanceof EnderDragonPart; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/LivingEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/LivingEntityBridge.java index 04a37578f..7946c4acd 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/LivingEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/LivingEntityBridge.java @@ -1,8 +1,7 @@ package io.izzel.arclight.common.bridge.core.entity; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffect; @@ -14,13 +13,11 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.event.entity.EntityKnockbackEvent; import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityRegainHealthEvent; -import javax.annotation.Nullable; import java.util.Collection; import java.util.Optional; @@ -32,9 +29,7 @@ public interface LivingEntityBridge extends EntityBridge { boolean bridge$canPickUpLoot(); - boolean bridge$isForceDrops(); - - int bridge$getExpReward(); + int bridge$getExpReward(Entity entity); void bridge$setExpToDrop(int amount); @@ -48,7 +43,7 @@ public interface LivingEntityBridge extends EntityBridge { boolean bridge$addEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause); - boolean bridge$removeEffect(MobEffect effect, EntityPotionEffectEvent.Cause cause); + boolean bridge$removeEffect(Holder effect, EntityPotionEffectEvent.Cause cause); boolean bridge$removeAllEffects(EntityPotionEffectEvent.Cause cause); @@ -63,27 +58,6 @@ public interface LivingEntityBridge extends EntityBridge { return originalExperience; } - default boolean bridge$forge$mobEffectExpired(MobEffectInstance effect) { - return false; - } - - default boolean bridge$forge$mobEffectAdded(MobEffectInstance old, MobEffectInstance effect, Entity entity) { - return false; - } - - default float bridge$forge$onLivingHurt(LivingEntity entity, DamageSource src, float amount) { - return amount; - } - - default Product3 bridge$forge$onShieldBlock( - LivingEntity blocker, DamageSource source, float blocked) { - return Product.of(false, blocked, true); - } - - default float bridge$forge$onLivingDamage(LivingEntity entity, DamageSource src, float amount) { - return amount; - } - default boolean bridge$forge$onLivingUseTotem(LivingEntity entity, DamageSource damageSource, ItemStack totem, InteractionHand hand) { return true; } @@ -93,24 +67,12 @@ enum LivingTargetType { MOB_TARGET } - default @Nullable LivingEntity bridge$forge$onLivingChangeTarget(LivingEntity entity, LivingEntity originalTarget, LivingTargetType targetType) { - return originalTarget; - } - - default BlockPos bridge$forge$onEnderTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { - return BlockPos.containing(targetX, targetY, targetZ); - } - default void bridge$forge$onLivingConvert(LivingEntity entity, LivingEntity outcome) {} default boolean bridge$forge$canEntityDestroy(Level level, BlockPos pos, LivingEntity entity) { return true; } - default boolean bridge$forge$onEntityDestroyBlock(LivingEntity entity, BlockPos pos, BlockState state) { - return true; - } - void bridge$common$startCaptureDrops(); boolean bridge$common$isCapturingDrops(); @@ -119,5 +81,5 @@ enum LivingTargetType { Collection bridge$common$getCapturedDrops(); - void bridge$common$finishCaptureAndFireEvent(); + void bridge$common$finishCaptureAndFireEvent(DamageSource damageSource); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/MobEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/MobEntityBridge.java index c3ad3f212..f04f43921 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/MobEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/MobEntityBridge.java @@ -1,6 +1,5 @@ package io.izzel.arclight.common.bridge.core.entity; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.AgeableMob; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; @@ -20,8 +19,6 @@ public interface MobEntityBridge extends LivingEntityBridge { boolean bridge$lastGoalTargetResult(); - ResourceLocation bridge$getLootTable(); - boolean bridge$isPersistenceRequired(); void bridge$setPersistenceRequired(boolean value); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/item/ItemEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/item/ItemEntityBridge.java index c06fb7489..84c9e62c5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/item/ItemEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/item/ItemEntityBridge.java @@ -1,17 +1,6 @@ package io.izzel.arclight.common.bridge.core.entity.item; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; - public interface ItemEntityBridge { - default int bridge$forge$onItemPickup(Player player) { - return 0; - } - - default void bridge$forge$firePlayerItemPickupEvent(Player player, ItemStack clone) {} - default void bridge$forge$optimization$discardItemEntity() {} - - boolean bridge$common$itemDespawnEvent(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/PlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/PlayerEntityBridge.java index 6c0a23064..0b13060f7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/PlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/PlayerEntityBridge.java @@ -2,19 +2,9 @@ import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; -import io.izzel.tools.product.Product6; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.util.Unit; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.event.entity.EntityExhaustionEvent; @@ -31,35 +21,6 @@ public interface PlayerEntityBridge extends LivingEntityBridge { double bridge$platform$getBlockReach(); - boolean bridge$platform$isCloseEnough(Entity entity, double dist); - - boolean bridge$platform$canReach(BlockPos pos, double padding); - - boolean bridge$platform$canReach(Entity entity, double padding); - - boolean bridge$platform$canReach(Vec3 entityHitVec, double padding); - - default Float bridge$forge$getCriticalHit(Player player, Entity target, boolean vanillaCritical, float damageModifier) { - return damageModifier; - } - - default double bridge$forge$getEntityReach() { - return ((Player) this).isCreative() ? 6.0 : 3.0; - } - - default Product3 - bridge$platform$onLeftClickBlock(BlockPos pos, Direction direction, ServerboundPlayerActionPacket.Action action) { - return Product.of(false, false, false); - } - - default Product6 - bridge$platform$onRightClickBlock(InteractionHand hand, BlockPos pos, BlockHitResult hitResult) { - return Product.of(false, false, false, false, false, InteractionResult.PASS); - } - default boolean bridge$platform$mayfly() { return ((Player) this).getAbilities().mayfly; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java index 8b116f079..dc37dc6f8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java @@ -2,9 +2,9 @@ import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftPlayer; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerSpawnChangeEvent; import org.bukkit.event.player.PlayerTeleportEvent; @@ -21,6 +21,14 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge { Optional bridge$getTeleportCause(); + void bridge$pushRespawnReason(PlayerRespawnEvent.RespawnReason respawnReason); + + void bridge$setTransferCookieConnection(CraftPlayer.TransferCookieConnection transferCookieConnection); + + CraftPlayer.TransferCookieConnection bridge$getTransferCookieConnection(); + + void bridge$resendItemInHands(); + BlockPos bridge$getSpawnPoint(ServerLevel world); boolean bridge$isMovementBlocked(); @@ -31,11 +39,20 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge { void bridge$reset(); - Entity bridge$changeDimension(ServerLevel world, PlayerTeleportEvent.TeleportCause cause); - boolean bridge$initialized(); boolean bridge$isTrackerDirty(); void bridge$setTrackerDirty(boolean flag); + + interface RespawnPosAngleBridge { + + boolean bridge$isBedSpawn(); + + boolean bridge$isAnchorSpawn(); + + void bridge$setBedSpawn(boolean b); + + void bridge$setAnchorSpawn(boolean b); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/ArrowEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/ArrowEntityBridge.java index 5eaa54fd5..e24f11a46 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/ArrowEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/ArrowEntityBridge.java @@ -4,7 +4,4 @@ public interface ArrowEntityBridge extends EntityBridge { - void bridge$refreshEffects(); - - boolean bridge$isTipped(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/DamagingProjectileEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/DamagingProjectileEntityBridge.java index 1319b890e..8fbdf1d70 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/DamagingProjectileEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/projectile/DamagingProjectileEntityBridge.java @@ -5,6 +5,4 @@ public interface DamagingProjectileEntityBridge extends EntityBridge { void bridge$setBukkitYield(float yield); - - void bridge$setDirection(double d0, double d1, double d2); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/container/ContainerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/container/ContainerBridge.java index 58f77735e..e599704a3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/container/ContainerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/inventory/container/ContainerBridge.java @@ -1,12 +1,7 @@ package io.izzel.arclight.common.bridge.core.inventory.container; import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.SlotAccess; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickAction; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.inventory.InventoryView; @@ -21,8 +16,4 @@ public interface ContainerBridge { void bridge$setTitle(Component title); boolean bridge$isCheckReachable(); - - default boolean bridge$forge$onItemStackedOn(ItemStack carriedItem, ItemStack stackedOnItem, Slot slot, ClickAction action, Player player, SlotAccess carriedSlotAccess) { - return false; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/DiscardedPayloadBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/DiscardedPayloadBridge.java new file mode 100644 index 000000000..cadcfca09 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/DiscardedPayloadBridge.java @@ -0,0 +1,10 @@ +package io.izzel.arclight.common.bridge.core.network.common; + +import io.netty.buffer.ByteBuf; + +public interface DiscardedPayloadBridge { + + void bridge$setData(ByteBuf data); + + ByteBuf bridge$getData(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/ServerCommonPacketListenerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/ServerCommonPacketListenerBridge.java index afbef2fa6..04fa4388c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/ServerCommonPacketListenerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/common/ServerCommonPacketListenerBridge.java @@ -23,7 +23,10 @@ public interface ServerCommonPacketListenerBridge { void bridge$setPlayer(ServerPlayer player); default FriendlyByteBuf bridge$getDiscardedData(ServerboundCustomPayloadPacket packet) { - // Todo: use Mixin to save vanilla payload data. + var customPacketPayload = packet.payload(); + if (customPacketPayload instanceof DiscardedPayloadBridge b && b.bridge$getData() != null) { + return new FriendlyByteBuf(b.bridge$getData()); + } return null; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/login/ServerLoginNetHandlerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/login/ServerLoginNetHandlerBridge.java index 5108494b7..935032f1c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/login/ServerLoginNetHandlerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/login/ServerLoginNetHandlerBridge.java @@ -2,6 +2,7 @@ import com.mojang.authlib.GameProfile; import io.izzel.arclight.common.bridge.core.network.common.ServerCommonPacketListenerBridge; +import io.izzel.arclight.common.mod.util.ArclightCustomQueryAnswerPayload; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; @@ -15,8 +16,7 @@ public interface ServerLoginNetHandlerBridge extends ServerCommonPacketListenerB void bridge$preLogin(GameProfile authenticatedProfile) throws Exception; default FriendlyByteBuf bridge$getDiscardedQueryAnswerData(ServerboundCustomQueryAnswerPacket payload) { - // Todo: use Mixin to save vanilla payload data. - return null; + return new FriendlyByteBuf(((ArclightCustomQueryAnswerPayload) payload.payload()).buf()); } default void bridge$platform$onCustomQuery(ServerboundCustomQueryAnswerPacket payload) {} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/play/ServerPlayNetHandlerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/play/ServerPlayNetHandlerBridge.java index 55f80e082..a16b02a48 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/play/ServerPlayNetHandlerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/network/play/ServerPlayNetHandlerBridge.java @@ -20,6 +20,10 @@ public interface ServerPlayNetHandlerBridge extends ServerCommonPacketListenerBr void bridge$teleport(Location dest); + void bridge$pushNoTeleportEvent(); + + boolean bridge$teleportCancelled(); + default Product3 bridge$platform$canSwapHandItems(LivingEntity entity) { return Product.of(false, entity.getOffhandItem(), entity.getMainHandItem()); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerInteractionManagerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerInteractionManagerBridge.java index 5dcaac08b..07324bbab 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerInteractionManagerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerInteractionManagerBridge.java @@ -2,6 +2,8 @@ import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; public interface PlayerInteractionManagerBridge { @@ -14,4 +16,10 @@ public interface PlayerInteractionManagerBridge { void bridge$setInteractResult(boolean b); void bridge$handleBlockDrop(ArclightCaptures.BlockBreakEventContext breakEventContext, BlockPos pos); + + BlockPos bridge$getInteractPosition(); + + InteractionHand bridge$getInteractHand(); + + ItemStack bridge$getInteractItemStack(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerListBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerListBridge.java index a8493d07e..3c4637414 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerListBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/server/management/PlayerListBridge.java @@ -8,6 +8,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import org.bukkit.craftbukkit.v.CraftServer; +import org.bukkit.event.player.PlayerRespawnEvent; import java.net.SocketAddress; import java.util.List; @@ -24,6 +25,8 @@ public interface PlayerListBridge { void bridge$sendMessage(Component[] components); + void bridge$pushRespawnCause(PlayerRespawnEvent.RespawnReason respawnReason); + default boolean bridge$platform$onTravelToDimension(Player player, ResourceKey dimension) { return false; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/DamageSourceBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/DamageSourceBridge.java index b2600a5b6..5bf9aca36 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/DamageSourceBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/DamageSourceBridge.java @@ -15,13 +15,25 @@ public interface DamageSourceBridge { Entity bridge$getCausingEntity(); + Entity bridge$getCausingEntityDamager(); + DamageSource bridge$customCausingEntity(Entity entity); DamageSource bridge$setCustomCausingEntity(Entity entity); + DamageSource bridge$customCausingEntityDamager(Entity entity); + + DamageSource bridge$setCustomCausingEntityDamager(Entity entity); + org.bukkit.block.Block bridge$directBlock(); DamageSource bridge$directBlock(org.bukkit.block.Block block); DamageSource bridge$setDirectBlock(org.bukkit.block.Block block); + + org.bukkit.block.BlockState bridge$directBlockState(); + + DamageSource bridge$directBlockState(org.bukkit.block.BlockState block); + + DamageSource bridge$setDirectBlockState(org.bukkit.block.BlockState block); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/FoodStatsBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/FoodStatsBridge.java index 8df8fefe6..e1f1c4e58 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/FoodStatsBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/util/FoodStatsBridge.java @@ -1,8 +1,6 @@ package io.izzel.arclight.common.bridge.core.util; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.ItemStack; public interface FoodStatsBridge { @@ -11,7 +9,5 @@ public interface FoodStatsBridge { Player bridge$getEntityHuman(); - default FoodProperties bridge$forge$getFoodProperties(ItemStack stack, LivingEntity entity) { - return stack.getItem().getFoodProperties(); - } + void bridge$pushEatStack(ItemStack stack); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/TeleporterBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/TeleporterBridge.java index ab2c171eb..33b7d2c1b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/TeleporterBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/TeleporterBridge.java @@ -1,16 +1,10 @@ package io.izzel.arclight.common.bridge.core.world; -import net.minecraft.BlockUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.border.WorldBorder; - -import java.util.Optional; public interface TeleporterBridge { - Optional bridge$findPortal(BlockPos pos, WorldBorder worldborder, int searchRadius); + void bridge$pushSearchRadius(int searchRadius); - Optional bridge$createPortal(BlockPos pos, Direction.Axis axis, Entity entity, int createRadius); + void bridge$pushPortalCreate(Entity entity, int createRadius); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java index f989e87c6..6a06b15a9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java @@ -9,7 +9,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.PotionBrewing; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -33,8 +32,6 @@ public interface WorldBridge extends IWorldWriterBridge, IWorldBridge, InjectLev boolean bridge$isPvpMode(); - boolean bridge$isKeepSpawnInMemory(); - boolean bridge$isPopulating(); void bridge$setPopulating(boolean populating); @@ -65,10 +62,6 @@ public interface WorldBridge extends IWorldWriterBridge, IWorldBridge, InjectLev return ((Level) this).getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } - default ItemStack bridge$forge$potionBrewMix(ItemStack a, ItemStack b) { - return PotionBrewing.mix(a, b); - } - default void bridge$forge$onPotionBrewed(NonNullList stacks) {} default boolean bridge$forge$restoringBlockSnapshots() { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatEntryBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatEntryBridge.java new file mode 100644 index 000000000..0a42cd9ed --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatEntryBridge.java @@ -0,0 +1,10 @@ +package io.izzel.arclight.common.bridge.core.world.damagesource; + +import net.minecraft.network.chat.Component; + +public interface CombatEntryBridge { + + void bridge$setDeathMessage(Component component); + + Component bridge$getDeathMessage(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatTrackerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatTrackerBridge.java new file mode 100644 index 000000000..e682d954d --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/damagesource/CombatTrackerBridge.java @@ -0,0 +1,8 @@ +package io.izzel.arclight.common.bridge.core.world.damagesource; + +import net.minecraft.network.chat.Component; + +public interface CombatTrackerBridge { + + void bridge$setDeathMessage(Component component); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemBridge.java index 4420ba734..af2028a3d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemBridge.java @@ -23,11 +23,6 @@ public interface ItemBridge { return arrow; } - default boolean bridge$forge$isInfinite(ArrowItem item, ItemStack stack, ItemStack bow, Player player) { - int enchant = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, bow); - return enchant > 0 && item.getClass() == ArrowItem.class; - } - default boolean bridge$forge$onChorusFruitTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { return false; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemStackBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemStackBridge.java index 4353ef253..bf2519ca3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemStackBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/ItemStackBridge.java @@ -1,50 +1,15 @@ package io.izzel.arclight.common.bridge.core.world.item; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.component.DataComponentPatch; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.SwordItem; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.LevelReader; -import net.minecraft.world.phys.AABB; -import org.jetbrains.annotations.NotNull; public interface ItemStackBridge { - void bridge$convertStack(int version); - - default CompoundTag bridge$getForgeCaps() { - return null; - } - - default void bridge$setForgeCaps(CompoundTag caps) { - } - - default boolean bridge$forge$hasCraftingRemainingItem() { - return ((ItemStack) (Object) this).getItem().hasCraftingRemainingItem(); - } - - default ItemStack bridge$forge$getCraftingRemainingItem() { - var item = ((ItemStack) (Object) this).getItem().getCraftingRemainingItem(); - return item == null ? ItemStack.EMPTY : new ItemStack(item); - } - - enum ToolAction { - SWORD_SWEEP - } - - default boolean bridge$forge$canPerformAction(ToolAction action) { - return switch (action) { - case SWORD_SWEEP -> ((ItemStack) (Object) this).getItem() instanceof SwordItem; - }; - } - - default AABB bridge$forge$getSweepHitBox(@NotNull Player player, @NotNull Entity target) { - return target.getBoundingBox().inflate(1.0D, 0.25D, 1.0D); - } + void bridge$restorePatch(DataComponentPatch datacomponentpatch); default InteractionResult bridge$forge$onItemUseFirst(UseOnContext context) { return InteractionResult.PASS; @@ -53,6 +18,4 @@ enum ToolAction { default boolean bridge$forge$doesSneakBypassUse(LevelReader level, BlockPos pos, Player player) { return false; } - - default void bridge$platform$copyAdditionalFrom(ItemStack from) {} } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/crafting/RecipeManagerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/crafting/RecipeManagerBridge.java index f5abf1153..3bae9ef39 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/crafting/RecipeManagerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/item/crafting/RecipeManagerBridge.java @@ -9,6 +9,4 @@ public interface RecipeManagerBridge { void bridge$addRecipe(RecipeHolder recipe); void bridge$clearRecipes(); - - RecipeHolder bridge$platform$loadRecipe(ResourceLocation key, JsonElement element); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/block/BlockBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/block/BlockBridge.java index 48ed71237..74e9a6073 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/block/BlockBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/block/BlockBridge.java @@ -3,49 +3,24 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.entity.Entity; +import net.minecraft.util.valueproviders.IntProvider; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.boss.enderdragon.EnderDragon; -import net.minecraft.world.entity.boss.wither.WitherBoss; -import net.minecraft.world.entity.projectile.WitherSkull; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.DispenserBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface BlockBridge { int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack); + int bridge$tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider); + default boolean bridge$forge$onCropsGrowPre(Level level, BlockPos pos, BlockState state, boolean def) { return true; } default void bridge$forge$onCropsGrowPost(Level level, BlockPos pos, BlockState state) {} - default boolean bridge$forge$dropperInsertHook(Level level, BlockPos pos, DispenserBlockEntity dropper, int slot, @NotNull ItemStack stack) { - return true; - } - default void bridge$forge$onCaughtFire(BlockState state, Level level, BlockPos pos, @Nullable Direction direction, @Nullable LivingEntity igniter) {} - - default boolean bridge$forge$isActivatorRail(BlockState state) { - return state.is(Blocks.ACTIVATOR_RAIL); - } - - default boolean bridge$forge$canEntityDestroy(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { - if (entity instanceof EnderDragon) { - return !((Block) this).defaultBlockState().is(BlockTags.DRAGON_IMMUNE); - } else if ((entity instanceof WitherBoss) || - (entity instanceof WitherSkull)) { - return state.isAir() || WitherBoss.canDestroy(state); - } - return true; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/levelgen/structure/templatesystem/StructureTemplateBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/levelgen/structure/templatesystem/StructureTemplateBridge.java index e1e7741ed..7b7781961 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/levelgen/structure/templatesystem/StructureTemplateBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/levelgen/structure/templatesystem/StructureTemplateBridge.java @@ -1,19 +1,4 @@ package io.izzel.arclight.common.bridge.core.world.level.levelgen.structure.templatesystem; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; - -import javax.annotation.Nullable; -import java.util.List; - public interface StructureTemplateBridge { - - List bridge$platform$processBlockInfos(ServerLevelAccessor arg, BlockPos arg2, BlockPos arg3, StructurePlaceSettings arg4, List list2, @Nullable StructureTemplate template); - - void bridge$platform$placeEntities(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, Mirror mirror, Rotation rotation, BlockPos blockPos2, @org.jetbrains.annotations.Nullable BoundingBox boundingBox, boolean bl, StructurePlaceSettings placementIn); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/portal/DimensionTransitionBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/portal/DimensionTransitionBridge.java new file mode 100644 index 000000000..75645b7b7 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/level/portal/DimensionTransitionBridge.java @@ -0,0 +1,10 @@ +package io.izzel.arclight.common.bridge.core.world.level.portal; + +import org.bukkit.event.player.PlayerTeleportEvent; + +public interface DimensionTransitionBridge { + + void bridge$setTeleportCause(PlayerTeleportEvent.TeleportCause cause); + + PlayerTeleportEvent.TeleportCause bridge$getTeleportCause(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/spawner/BaseSpawnerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/spawner/BaseSpawnerBridge.java index c397280fd..ac267387d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/spawner/BaseSpawnerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/spawner/BaseSpawnerBridge.java @@ -1,17 +1,5 @@ package io.izzel.arclight.common.bridge.core.world.spawner; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.DifficultyInstance; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.SpawnGroupData; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.SpawnData; -import org.jetbrains.annotations.Nullable; - public interface BaseSpawnerBridge { - boolean bridge$forge$checkSpawnRules(Mob mob, ServerLevelAccessor level, MobSpawnType spawnType, SpawnData spawnData, boolean result); - - void bridge$forge$finalizeSpawnerSpawn(Mob mob, ServerLevelAccessor level, DifficultyInstance difficulty, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag spawnTag); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/MapDataBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/MapDataBridge.java index e9fa83a5d..63af98f26 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/MapDataBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/MapDataBridge.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.bridge.core.world.storage; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import org.bukkit.craftbukkit.v.map.CraftMapView; @@ -9,7 +10,7 @@ public interface MapDataBridge { CraftMapView bridge$getMapView(); - void bridge$setId(String id); + void bridge$setId(MapId id); List bridge$getCarriedBy(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/loot/LootContextBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/loot/LootContextBridge.java index 2f72a3960..4be76368a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/loot/LootContextBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/storage/loot/LootContextBridge.java @@ -1,16 +1,4 @@ package io.izzel.arclight.common.bridge.core.world.storage.loot; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.enchantment.EnchantmentHelper; - public interface LootContextBridge { - - default int bridge$forge$getLootingModifier(Entity entity) { - if (entity instanceof LivingEntity livingEntity) { - return EnchantmentHelper.getMobLooting(livingEntity); - } else { - return 0; - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftEventFactoryMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftEventFactoryMixin.java index efba49203..9c956da09 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftEventFactoryMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftEventFactoryMixin.java @@ -20,7 +20,6 @@ import org.bukkit.craftbukkit.v.block.data.CraftBlockData; import org.bukkit.craftbukkit.v.damage.CraftDamageSource; import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.bukkit.entity.Item; import org.bukkit.event.block.BlockFadeEvent; import org.bukkit.event.block.BlockFormEvent; @@ -159,7 +158,7 @@ public static boolean handleBlockFormEvent(Level world, BlockPos pos, net.minecr public static BlockFadeEvent callBlockFadeEvent(LevelAccessor world, BlockPos pos, net.minecraft.world.level.block.state.BlockState newBlock) { // Suppress during worldgen if (!(world instanceof Level) || !DistValidate.isValid(world)) { - return new BlockFadeEvent(CraftBlock.at(world, pos), CraftBlockStates.getBlockState(CraftMagicNumbers.getMaterial(newBlock.getBlock()), null)); + return new BlockFadeEvent(CraftBlock.at(world, pos), null); } CraftBlockState state = CraftBlockStates.getBlockState(world, pos); state.setData(newBlock); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftInventoryViewMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftInventoryViewMixin.java index b5e647912..27408c6a1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftInventoryViewMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftInventoryViewMixin.java @@ -17,7 +17,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(value = CraftInventoryView.class, remap = false) -public abstract class CraftInventoryViewMixin extends InventoryView { +public abstract class CraftInventoryViewMixin implements InventoryView { @Shadow @Final @Mutable private CraftInventory viewing; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java index ec6083abc..e11019f03 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftItemStackMixin.java @@ -1,24 +1,11 @@ package io.izzel.arclight.common.mixin.bukkit; import io.izzel.arclight.common.bridge.bukkit.CraftItemStackBridge; -import io.izzel.arclight.common.bridge.bukkit.ItemMetaBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import org.bukkit.Material; -import org.bukkit.craftbukkit.v.inventory.CraftItemFactory; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v.legacy.CraftLegacy; -import org.bukkit.inventory.meta.ItemMeta; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Desc; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Objects; @Mixin(value = CraftItemStack.class, remap = false) public abstract class CraftItemStackMixin implements CraftItemStackBridge { @@ -31,81 +18,6 @@ public abstract class CraftItemStackMixin implements CraftItemStackBridge { @Shadow static Material getType(ItemStack item) { throw new RuntimeException(); } // @formatter:on - @Desc(id = "getItemMeta", value = "getItemMeta", ret = ItemMeta.class, args = {ItemStack.class}) - @Inject(method = "@Desc(getItemMeta)", cancellable = true, at = @At(value = "INVOKE", target = "Lorg/bukkit/Material;ordinal()I")) - private static void arclight$noTag(ItemStack item, CallbackInfoReturnable cir) { - if (item.getTag() == null) { - var meta = CraftItemFactory.instance().getItemMeta(getType(item)); - ((ItemMetaBridge) meta).bridge$setForgeCaps(((ItemStackBridge) (Object) item).bridge$getForgeCaps()); - cir.setReturnValue(meta); - } - } - - @Desc(id = "getItemMeta", value = "getItemMeta", ret = ItemMeta.class, args = {ItemStack.class}) - @Inject(method = "@Desc(getItemMeta)", at = @At("RETURN")) - private static void arclight$offerCaps(ItemStack item, CallbackInfoReturnable cir) { - if (item == null) return; - ItemMeta meta = cir.getReturnValue(); - CompoundTag tag = item.getTag(); - if (tag != null) { - ((ItemMetaBridge) meta).bridge$offerUnhandledTags(tag); - } - ((ItemMetaBridge) meta).bridge$setForgeCaps(((ItemStackBridge) (Object) item).bridge$getForgeCaps()); - } - - @Desc(id = "setItemMeta", value = "setItemMeta", args = {ItemStack.class, ItemMeta.class}, ret = boolean.class) - @Inject(method = "@Desc(setItemMeta)", at = @At(value = "INVOKE", ordinal = 1, remap = true, target = "Lnet/minecraft/world/item/ItemStack;getItem()Lnet/minecraft/world/item/Item;")) - private static void arclight$setCaps(ItemStack item, ItemMeta itemMeta, CallbackInfoReturnable cir) { - CompoundTag forgeCaps = ((ItemMetaBridge) itemMeta).bridge$getForgeCaps(); - if (forgeCaps != null) { - ((ItemStackBridge) (Object) item).bridge$setForgeCaps(forgeCaps.copy()); - } - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - public boolean isSimilar(org.bukkit.inventory.ItemStack stack) { - if (stack == null) { - return false; - } - if (stack == (Object) this) { - return true; - } - if (!(stack instanceof CraftItemStack that)) { - return stack.getClass() == org.bukkit.inventory.ItemStack.class && stack.isSimilar((org.bukkit.inventory.ItemStack) (Object) this); - } - - if (handle == ((CraftItemStackBridge) (Object) that).bridge$getHandle()) { - return true; - } - if (handle == null || ((CraftItemStackBridge) (Object) that).bridge$getHandle() == null) { - return false; - } - Material comparisonType = CraftLegacy.fromLegacy(that.getType()); // This may be called from legacy item stacks, try to get the right material - if (!(comparisonType == this.getType() && getDurability() == that.getDurability())) { - return false; - } - return hasItemMeta() - ? (that.hasItemMeta() - && Objects.equals(handle.getTag(), ((CraftItemStackBridge) (Object) that).bridge$getHandle().getTag()) - && Objects.equals(((ItemStackBridge) (Object) handle).bridge$getForgeCaps(), ((ItemStackBridge) (Object) ((CraftItemStackBridge) (Object) that).bridge$getHandle()).bridge$getForgeCaps())) - : !that.hasItemMeta(); - } - - @Desc(id = "hasItemMeta", value = "hasItemMeta", args = ItemStack.class, ret = boolean.class) - @Inject(method = "@Desc(hasItemMeta)", cancellable = true, at = @At("HEAD")) - private static void arclight$hasMeta(ItemStack item, CallbackInfoReturnable cir) { - if (item != null) { - CompoundTag forgeCaps = ((ItemStackBridge) (Object) item).bridge$getForgeCaps(); - if (forgeCaps != null && !forgeCaps.isEmpty()) { - cir.setReturnValue(true); - } - } - } - @Override public ItemStack bridge$getHandle() { return handle; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java index fd0a67935..679295ca1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftMetaItemMixin.java @@ -1,189 +1,14 @@ package io.izzel.arclight.common.mixin.bukkit; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import io.izzel.arclight.common.bridge.bukkit.ItemMetaBridge; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtAccounter; -import net.minecraft.nbt.NbtIo; -import net.minecraft.nbt.Tag; -import org.apache.commons.codec.binary.Base64; -import org.apache.logging.log4j.LogManager; import org.bukkit.craftbukkit.v.inventory.CraftMetaItem; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Desc; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.Map; -import java.util.Set; @Mixin(value = CraftMetaItem.class, remap = false) public class CraftMetaItemMixin implements ItemMetaBridge { // @formatter:off - @Shadow(remap = false) @Final Map unhandledTags; - @Shadow(remap = false) private CompoundTag internalTag; + @Shadow(remap = false) protected net.minecraft.core.component.DataComponentPatch.Builder unhandledTags; // @formatter:on - - private static final Set EXTEND_TAGS = ImmutableSet.of( - "map_is_scaling", - "map", - "CustomPotionEffects", - "Potion", - "CustomPotionColor", - "SkullOwner", - "SkullProfile", - "EntityTag", - "BlockEntityTag", - "title", - "author", - "pages", - "resolved", - "generation", - "Fireworks", - "StoredEnchantments", - "Explosion", - "Recipes", - "BucketVariantTag", - "Charged", - "ChargedProjectiles", - "Effects", - "LodestoneDimension", - "LodestonePos", - "LodestoneTracked", - "Items", - "instrument" - ); - - @Desc(id = "compoundInit", value = "", args = CompoundTag.class) - @ModifyVariable(method = "@Desc(compoundInit)", at = @At(value = "INVOKE", target = "Lorg/bukkit/UnsafeValues;getDataVersion()I"), argsOnly = true) - private CompoundTag arclight$provideTag(CompoundTag tag) { - return tag == null ? new CompoundTag() : tag; - } - - @Redirect(method = "(Ljava/util/Map;)V", at = @At(value = "INVOKE", target = "Ljava/util/Set;contains(Ljava/lang/Object;)Z")) - private boolean arclight$forceDeserializeInternalTags(Set handledTags, Object key) { - if ((Object) this instanceof CraftMetaItem) { - // For mod items or vanilla items that usually don't depend on nbt tags, - // force internal tags to be deserialized into item nbt to avoid their vanilla tags being ignored by Bukkit. - // e.g. apotheosis:potion_charm{"Potion": ""} or minecraft:bread{"Potion": ""} - return false; - } else { - // For items that has corresponding ItemMeta representation in Bukkit, - // keep their behavior unchanged. - return handledTags.contains((String) key); - } - } - - private CompoundTag forgeCaps; - - @Override - public CompoundTag bridge$getForgeCaps() { - return this.forgeCaps; - } - - @Override - public void bridge$setForgeCaps(CompoundTag nbt) { - this.forgeCaps = nbt; - } - - @Override - public void bridge$offerUnhandledTags(CompoundTag nbt) { - if (getClass().equals(CraftMetaItem.class)) { - for (String s : nbt.getAllKeys()) { - if (EXTEND_TAGS.contains(s)) { - this.unhandledTags.put(s, nbt.get(s)); - } - } - } - } - - @Override - public Map bridge$getUnhandledTags() { - return this.unhandledTags; - } - - @Override - public void bridge$setUnhandledTags(Map tags) { - this.unhandledTags.putAll(tags); - } - - @Inject(method = "serialize(Lcom/google/common/collect/ImmutableMap$Builder;)Lcom/google/common/collect/ImmutableMap$Builder;", at = @At("RETURN")) - private void arclight$serializeForgeCaps(ImmutableMap.Builder builder, CallbackInfoReturnable> cir) throws IOException { - if (this.forgeCaps != null) { - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - NbtIo.writeCompressed(this.forgeCaps, buf); - builder.put("forgeCaps", Base64.encodeBase64String(buf.toByteArray())); - } - } - - @Inject(method = "clone*", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) - private void arclight$cloneTags(CallbackInfoReturnable cir, CraftMetaItem clone) { - if (this.unhandledTags != null) { - ((ItemMetaBridge) clone).bridge$getUnhandledTags().putAll(this.unhandledTags); - } - if (this.forgeCaps != null) { - ((ItemMetaBridge) clone).bridge$setForgeCaps(this.forgeCaps.copy()); - } - } - - @ModifyVariable(method = "applyHash", index = 1, at = @At("RETURN")) - private int arclight$applyForgeCapsHash(int hash) { - return 61 * hash + (this.forgeCaps != null ? this.forgeCaps.hashCode() : 0); - } - - @Inject(method = "isEmpty", cancellable = true, at = @At("HEAD")) - private void arclight$forgeCapsEmpty(CallbackInfoReturnable cir) { - if (this.forgeCaps != null && !this.forgeCaps.isEmpty()) { - cir.setReturnValue(false); - } - } - - @Inject(method = "equalsCommon", cancellable = true, at = @At("HEAD")) - private void arclight$forgeCapsEquals(CraftMetaItem that, CallbackInfoReturnable cir) { - CompoundTag forgeCaps = ((ItemMetaBridge) that).bridge$getForgeCaps(); - boolean ret; - if (this.forgeCaps == null) { - ret = forgeCaps != null && forgeCaps.size() != 0; - } else { - ret = forgeCaps == null ? this.forgeCaps.size() != 0 : !this.forgeCaps.equals(forgeCaps); - } - if (ret) { - cir.setReturnValue(false); - } - } - - @Inject(method = "(Ljava/util/Map;)V", at = @At("RETURN")) - private void arclight$extractForgeCaps(Map map, CallbackInfo ci) { - if (map.containsKey("forgeCaps")) { - Object forgeCaps = map.get("forgeCaps"); - try { - ByteArrayInputStream buf = new ByteArrayInputStream(Base64.decodeBase64(forgeCaps.toString())); - this.forgeCaps = NbtIo.readCompressed(buf, NbtAccounter.unlimitedHeap()); - } catch (IOException e) { - LogManager.getLogger(getClass()).error("Reading forge caps", e); - } - } - } - - @Inject(method = "*", at = @At("RETURN")) - private void arclight$copyForgeCaps(CraftMetaItem meta, CallbackInfo ci) { - if (meta != null) { - CompoundTag forgeCaps = ((ItemMetaBridge) meta).bridge$getForgeCaps(); - if (forgeCaps != null) { - this.forgeCaps = forgeCaps.copy(); - } - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/MaterialMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/MaterialMixin.java index a779cb64d..f426e07e7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/MaterialMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/MaterialMixin.java @@ -12,7 +12,6 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.FallingBlock; -import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.BlockState; @@ -223,7 +222,7 @@ public abstract class MaterialMixin implements MaterialBridge { @Inject(method = "getCraftingRemainingItem", cancellable = true, at = @At("HEAD")) private void arclight$getCraftingRemainingItem(CallbackInfoReturnable cir) { if (arclight$spec != null && arclight$spec.craftingRemainingItem != null) { - cir.setReturnValue(CraftMagicNumbers.getMaterial(BuiltInRegistries.ITEM.get(new ResourceLocation(arclight$spec.craftingRemainingItem)))); + cir.setReturnValue(CraftMagicNumbers.getMaterial(BuiltInRegistries.ITEM.get(ResourceLocation.parse(arclight$spec.craftingRemainingItem)))); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/RecipeIteratorMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/RecipeIteratorMixin.java deleted file mode 100644 index d394220e0..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/RecipeIteratorMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package io.izzel.arclight.common.mixin.bukkit; - -import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeHolderBridge; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeType; -import org.bukkit.craftbukkit.v.inventory.RecipeIterator; -import org.bukkit.inventory.Recipe; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Iterator; -import java.util.Map; - -@Mixin(value = RecipeIterator.class, remap = false) -public class RecipeIteratorMixin { - - // @formatter:off - @Shadow @Final private Iterator, Object2ObjectLinkedOpenHashMap>>> recipes; - @Shadow private Iterator> current; - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public Recipe next() { - if (current == null || !current.hasNext()) { - current = recipes.next().getValue().values().iterator(); - return next(); - } - var recipe = current.next(); - try { - return ((RecipeHolderBridge) (Object) recipe).bridge$toBukkitRecipe(); - } catch (Throwable e) { - throw new RuntimeException("Error converting recipe " + recipe.id(), e); - } - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/core/component/DataComponentPatch_BuilderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/core/component/DataComponentPatch_BuilderMixin.java new file mode 100644 index 000000000..1b4c6d9e8 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/core/component/DataComponentPatch_BuilderMixin.java @@ -0,0 +1,50 @@ +package io.izzel.arclight.common.mixin.core.core.component; + +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.DataComponentType; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Optional; + +@Mixin(DataComponentPatch.Builder.class) +public class DataComponentPatch_BuilderMixin { + + @Shadow @Final public Reference2ObjectMap, Optional> map; + + public void copy(DataComponentPatch orig) { + this.map.putAll(orig.map); + } + + public void clear(DataComponentType type) { + this.map.remove(type); + } + + public boolean isSet(DataComponentType type) { + return map.containsKey(type); + } + + public boolean isEmpty() { + return this.map.isEmpty(); + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + + if (object instanceof DataComponentPatch.Builder patch) { + return this.map.equals(patch.map); + } + + return false; + } + + @Override + public int hashCode() { + return this.map.hashCode(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/FlowingFluidMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/FlowingFluidMixin.java index 476176a5d..c8bd2da44 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/FlowingFluidMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/FlowingFluidMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.fluid; import io.izzel.arclight.common.mod.util.DistValidate; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; @@ -55,14 +57,16 @@ public abstract class FlowingFluidMixin { } } - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) - private boolean arclight$fluidLevelChange(Level world, BlockPos pos, BlockState newState, int flags) { - if (!DistValidate.isValid(world)) return world.setBlock(pos, newState, flags); - FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, newState); - if (event.isCancelled()) { - return false; - } else { - return world.setBlock(pos, ((CraftBlockData) event.getNewData()).getState(), flags); + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) + private boolean arclight$fluidLevelChange(Level world, BlockPos pos, BlockState newState, int flags) throws Throwable { + if (DistValidate.isValid(world)) { + FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, newState); + if (event.isCancelled()) { + return (boolean) DecorationOps.cancel().invoke(); + } else { + newState = ((CraftBlockData) event.getNewData()).getState(); + } } + return (boolean) DecorationOps.callsite().invoke(world, pos, newState, flags); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerCommonPacketListenerImplMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerCommonPacketListenerImplMixin.java index da2e96d8f..e9fae3a84 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerCommonPacketListenerImplMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerCommonPacketListenerImplMixin.java @@ -5,14 +5,21 @@ import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge; import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.ChatFormatting; import net.minecraft.network.Connection; +import net.minecraft.network.ConnectionProtocol; +import net.minecraft.network.DisconnectionDetails; +import net.minecraft.network.PacketListener; import net.minecraft.network.PacketSendListener; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketUtils; import net.minecraft.network.protocol.common.ClientboundDisconnectPacket; import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.network.protocol.common.ServerboundResourcePackPacket; +import net.minecraft.network.protocol.cookie.ServerboundCookieResponsePacket; import net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; @@ -31,7 +38,6 @@ import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Constant; @@ -43,15 +49,18 @@ import java.util.concurrent.ExecutionException; @Mixin(ServerCommonPacketListenerImpl.class) -public abstract class ServerCommonPacketListenerImplMixin implements ServerCommonPacketListenerBridge { +public abstract class ServerCommonPacketListenerImplMixin implements ServerCommonPacketListenerBridge, PacketListener, CraftPlayer.TransferCookieConnection { // @formatter:off @Shadow @Final protected Connection connection; @Shadow @Final protected MinecraftServer server; - @Shadow public abstract void onDisconnect(Component p_300550_); @Shadow public abstract void send(Packet p_300558_); @Shadow protected abstract boolean isSingleplayerOwner(); @Shadow @Final private static Logger LOGGER; + @Shadow @Final private boolean transferred; + @Shadow public abstract void disconnect(DisconnectionDetails disconnectionDetails); + @Shadow public abstract void onDisconnect(DisconnectionDetails disconnectionDetails); + @Shadow public abstract void disconnect(Component component); // @formatter:on protected ServerPlayer player; @@ -80,6 +89,7 @@ public CraftPlayer getCraftPlayer() { @Override public void bridge$setPlayer(ServerPlayer player) { this.player = player; + ((ServerPlayerEntityBridge) this.player).bridge$setTransferCookieConnection(this); } @Inject(method = "", at = @At("RETURN")) @@ -106,29 +116,26 @@ public final boolean isDisconnected() { return this.isDisconnected(); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void disconnect(Component textComponent) { - this.bridge$disconnect(CraftChatMessage.fromComponent(textComponent)); - } - public void disconnect(String s) { - bridge$disconnect(s); + this.disconnect(Component.literal(s)); } @Override public void bridge$disconnect(String s) { + disconnect(s); + } + + @Decorate(method = "disconnect(Lnet/minecraft/network/DisconnectionDetails;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;send(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketSendListener;)V")) + private void arclight$kickEvent(Connection instance, Packet packet, PacketSendListener packetSendListener, DisconnectionDetails disconnectionDetails) throws Throwable { if (this.processedDisconnect) { + DecorationOps.cancel().invoke(); return; } if (!this.cserver.isPrimaryThread()) { Waitable waitable = new Waitable<>() { @Override protected Object evaluate() { - bridge$disconnect(s); + disconnect(disconnectionDetails); return null; } }; @@ -142,31 +149,23 @@ protected Object evaluate() { } catch (ExecutionException e) { throw new RuntimeException(e); } + DecorationOps.cancel().invoke(); return; } String leaveMessage = ChatFormatting.YELLOW + this.player.getScoreboardName() + " left the game."; - PlayerKickEvent event = new PlayerKickEvent(getCraftPlayer(), s, leaveMessage); + PlayerKickEvent event = new PlayerKickEvent(getCraftPlayer(), CraftChatMessage.fromComponent(disconnectionDetails.reason()), leaveMessage); if (this.cserver.getServer().isRunning()) { this.cserver.getPluginManager().callEvent(event); } if (event.isCancelled()) { + DecorationOps.cancel().invoke(); return; } ArclightCaptures.captureQuitMessage(event.getLeaveMessage()); Component textComponent = CraftChatMessage.fromString(event.getReason(), true)[0]; - this.connection.send(new ClientboundDisconnectPacket(textComponent), PacketSendListener.thenRun(() -> this.connection.disconnect(textComponent))); - this.onDisconnect(textComponent); - this.connection.setReadOnly(); - this.server.executeBlocking(this.connection::handleDisconnection); - } - - @Inject(method = "onDisconnect", cancellable = true, at = @At("HEAD")) - private void arclight$returnIfProcessed(Component reason, CallbackInfo ci) { - if (processedDisconnect) { - ci.cancel(); - } else { - processedDisconnect = true; - } + Packet newPacket = new ClientboundDisconnectPacket(textComponent); + DecorationOps.callsite().invoke(instance, newPacket, packetSendListener); + this.onDisconnect(disconnectionDetails); } @Inject(method = "send(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketSendListener;)V", cancellable = true, at = @At("HEAD")) @@ -185,8 +184,16 @@ protected Object evaluate() { this.cserver.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(this.getCraftPlayer(), packetIn.id(), PlayerResourcePackStatusEvent.Status.values()[packetIn.action().ordinal()])); } - private static final ResourceLocation CUSTOM_REGISTER = new ResourceLocation("register"); - private static final ResourceLocation CUSTOM_UNREGISTER = new ResourceLocation("unregister"); + @Inject(method = "handleCookieResponse", cancellable = true, at = @At("HEAD")) + private void arclight$handleCookie(ServerboundCookieResponsePacket serverboundCookieResponsePacket, CallbackInfo ci) { + PacketUtils.ensureRunningOnSameThread(serverboundCookieResponsePacket, (ServerCommonPacketListenerImpl) (Object) this, this.server); + if (((CraftPlayer) this.player.bridge$getBukkitEntity()).handleCookieResponse(serverboundCookieResponsePacket)) { + ci.cancel(); + } + } + + private static final ResourceLocation CUSTOM_REGISTER = ResourceLocation.withDefaultNamespace("register"); + private static final ResourceLocation CUSTOM_UNREGISTER = ResourceLocation.withDefaultNamespace("unregister"); @Inject(method = "handleCustomPayload", at = @At("HEAD")) private void arclight$customPayload(ServerboundCustomPayloadPacket packet, CallbackInfo ci) { @@ -201,7 +208,7 @@ protected Object evaluate() { return; } if (this.connection.isConnected()) { - if (packet.payload().id().equals(CUSTOM_REGISTER)) { + if (packet.payload().type().id().equals(CUSTOM_REGISTER)) { try { String channels = new String(buf, StandardCharsets.UTF_8); for (String channel : channels.split("\0")) { @@ -213,7 +220,7 @@ protected Object evaluate() { LOGGER.error("Couldn't register custom payload", ex); this.bridge$disconnect("Invalid payload REGISTER!"); } - } else if (packet.payload().id().equals(CUSTOM_UNREGISTER)) { + } else if (packet.payload().type().id().equals(CUSTOM_UNREGISTER)) { try { final String channels = new String(buf, StandardCharsets.UTF_8); for (String channel : channels.split("\0")) { @@ -227,7 +234,7 @@ protected Object evaluate() { } } else { try { - this.bridge$getCraftServer().getMessenger().dispatchIncomingMessage(((ServerPlayerEntityBridge) this.bridge$getPlayer()).bridge$getBukkitEntity(), packet.payload().id().toString(), buf); + this.bridge$getCraftServer().getMessenger().dispatchIncomingMessage(((ServerPlayerEntityBridge) this.bridge$getPlayer()).bridge$getBukkitEntity(), packet.payload().type().id().toString(), buf); } catch (Exception ex) { LOGGER.error("Couldn't dispatch custom payload", ex); this.bridge$disconnect("Invalid custom payload!"); @@ -237,4 +244,19 @@ protected Object evaluate() { }); } } + + @Override + public boolean isTransferred() { + return this.transferred; + } + + @Override + public ConnectionProtocol getProtocol() { + return this.protocol(); + } + + @Override + public void sendPacket(Packet packet) { + this.send(packet); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerConfigurationPacketListenerImplMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerConfigurationPacketListenerImplMixin.java index 7d93407a4..103cef240 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerConfigurationPacketListenerImplMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerConfigurationPacketListenerImplMixin.java @@ -1,11 +1,19 @@ package io.izzel.arclight.common.mixin.core.network; import com.mojang.authlib.GameProfile; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.network.chat.Component; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerLinks; import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerConfigurationPacketListenerImpl; import net.minecraft.server.players.PlayerList; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.CraftServerLinks; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerLinksSendEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -15,6 +23,15 @@ @Mixin(ServerConfigurationPacketListenerImpl.class) public abstract class ServerConfigurationPacketListenerImplMixin extends ServerCommonPacketListenerImplMixin { + @Decorate(method = "startConfiguration", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;serverLinks()Lnet/minecraft/server/ServerLinks;")) + private ServerLinks arclight$sendLinksEvent(MinecraftServer instance) throws Throwable { + var links = (ServerLinks) DecorationOps.callsite().invoke(instance); + var wrapper = new CraftServerLinks(links); + var event = new PlayerLinksSendEvent((Player) player.bridge$getBukkitEntity(), wrapper); + Bukkit.getPluginManager().callEvent(event); + return wrapper.getServerLinks(); + } + @Redirect(method = "handleConfigurationFinished", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;")) private Component arclight$skipLoginCheck(PlayerList instance, SocketAddress address, GameProfile gameProfile) { return null; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerGamePacketListenerImpl_HandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerGamePacketListenerImpl_HandlerMixin.java new file mode 100644 index 000000000..51c210831 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerGamePacketListenerImpl_HandlerMixin.java @@ -0,0 +1,107 @@ +package io.izzel.arclight.common.mixin.core.network; + +import com.mojang.datafixers.util.Pair; +import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.animal.Bucketable; +import net.minecraft.world.entity.animal.allay.Allay; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Arrays; +import java.util.stream.Collectors; + +@Mixin(targets = "net/minecraft/server/network/ServerGamePacketListenerImpl$1") +public class ServerGamePacketListenerImpl_HandlerMixin { + + @Shadow(aliases = {"field_28963", "f_143671_", "this$0"}) private ServerGamePacketListenerImpl outerThis; + + @Unique private transient Vec3 arclight$interactVec; + + @Decorate(method = "performInteraction", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl$EntityInteraction;run(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) + private InteractionResult arclight$playerInteractEvent(ServerGamePacketListenerImpl.EntityInteraction instance, ServerPlayer player, Entity entity, InteractionHand interactionHand) throws Throwable { + PlayerInteractEntityEvent event; + if (arclight$interactVec != null) { + event = new PlayerInteractAtEntityEvent((Player) player.bridge$getBukkitEntity(), entity.bridge$getBukkitEntity(), + new org.bukkit.util.Vector(arclight$interactVec.x, arclight$interactVec.y, arclight$interactVec.z), (interactionHand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); + } else { + event = new PlayerInteractEntityEvent((Player) player.bridge$getBukkitEntity(), entity.bridge$getBukkitEntity(), + (interactionHand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND); + } + ItemStack itemInHand = player.getItemInHand(interactionHand); + boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; + Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); + + Bukkit.getPluginManager().callEvent(event); + + // Fish bucket - SPIGOT-4048 + if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { + entity.bridge$getBukkitEntity().update(player); + player.containerMenu.sendAllDataToRemote(); + } + + if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { + // Refresh the current leash state + player.connection.send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); + } + + if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { + // Refresh the current entity metadata + ((SynchedEntityDataBridge) entity.getEntityData()).bridge$refresh(player); + if (entity instanceof Allay) { + player.connection.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); + player.containerMenu.sendAllDataToRemote(); + } + } + + if (event.isCancelled()) { + return (InteractionResult) DecorationOps.cancel().invoke(); + } + var result = (InteractionResult) DecorationOps.callsite().invoke(instance, player, entity, interactionHand); + if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { + player.containerMenu.sendAllDataToRemote(); + } + return result; + } + + @Inject(method = "onInteraction(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/Vec3;)V", at = @At("HEAD")) + private void arclight$setInteractVec(InteractionHand interactionHand, Vec3 vec3, CallbackInfo ci) { + this.arclight$interactVec = vec3; + } + + @Inject(method = "onInteraction(Lnet/minecraft/world/InteractionHand;Lnet/minecraft/world/phys/Vec3;)V", at = @At("RETURN")) + private void arclight$resetInteractVec(InteractionHand interactionHand, Vec3 vec3, CallbackInfo ci) { + this.arclight$interactVec = null; + } + + @Decorate(method = "onAttack", inject = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/level/ServerPlayer;attack(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$sendDirty(@Local(ordinal = -1) ItemStack itemstack) { + if (!itemstack.isEmpty() && itemstack.getCount() <= -1) { + outerThis.player.containerMenu.sendAllDataToRemote(); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerHandshakeNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerHandshakeNetHandlerMixin.java index fb73482a2..6628bcb59 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerHandshakeNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerHandshakeNetHandlerMixin.java @@ -6,28 +6,23 @@ import io.izzel.arclight.common.bridge.core.network.NetworkManagerBridge; import io.izzel.arclight.common.bridge.core.network.handshake.ServerHandshakeNetHandlerBridge; import io.izzel.arclight.common.mod.util.VelocitySupport; -import net.minecraft.SharedConstants; import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.handshake.ClientIntent; import net.minecraft.network.protocol.handshake.ClientIntentionPacket; import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; -import net.minecraft.network.protocol.status.ServerStatus; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerHandshakePacketListenerImpl; -import net.minecraft.server.network.ServerLoginPacketListenerImpl; -import net.minecraft.server.network.ServerStatusPacketListenerImpl; import org.apache.logging.log4j.LogManager; import org.bukkit.Bukkit; import org.spigotmc.SpigotConfig; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.text.MessageFormat; import java.util.HashMap; @Mixin(ServerHandshakePacketListenerImpl.class) @@ -40,100 +35,68 @@ public abstract class ServerHandshakeNetHandlerMixin implements ServerHandshakeN // @formatter:off @Shadow @Final private Connection connection; - @Shadow @Final private MinecraftServer server; - @Shadow @Final private static Component IGNORE_STATUS_REASON; // @formatter:on - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleIntention(ClientIntentionPacket packetIn) { - if (!bridge$forge$handleSpecialLogin(packetIn)) { + @Inject(method = "handleIntention", at = @At("HEAD")) + private void arclight$setHostName(ClientIntentionPacket packet, CallbackInfo ci) { + // TODO + if (!bridge$forge$handleSpecialLogin(packet)) { return; } - ((NetworkManagerBridge) this.connection).bridge$setHostname(packetIn.hostName() + ":" + packetIn.port()); - switch (packetIn.intention()) { - case LOGIN: { - this.connection.setClientboundProtocolAfterHandshake(ClientIntent.LOGIN); - - try { - long currentTime = System.currentTimeMillis(); - long connectionThrottle = Bukkit.getServer().getConnectionThrottle(); - InetAddress address = ((InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); - synchronized (throttleTracker) { - if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { - throttleTracker.put(address, currentTime); - var component = Component.literal("Connection throttled! Please wait before reconnecting."); - this.connection.send(new ClientboundLoginDisconnectPacket(component)); - this.connection.disconnect(component); - return; - } - throttleTracker.put(address, currentTime); - ++throttleCounter; - if (throttleCounter > 200) { - throttleCounter = 0; - throttleTracker.entrySet().removeIf(entry -> entry.getValue() > connectionThrottle); - } - } - } catch (Throwable t) { - LogManager.getLogger().debug("Failed to check connection throttle", t); - } - + ((NetworkManagerBridge) this.connection).bridge$setHostname(packet.hostName() + ":" + packet.port()); + } - if (packetIn.protocolVersion() > SharedConstants.getCurrentVersion().getProtocolVersion()) { - var component = Component.translatable(MessageFormat.format(SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName())); + @Inject(method = "beginLogin", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/Connection;setupOutboundProtocol(Lnet/minecraft/network/ProtocolInfo;)V")) + private void arclight$throttler(ClientIntentionPacket packet, boolean bl, CallbackInfo ci) { + try { + long currentTime = System.currentTimeMillis(); + long connectionThrottle = Bukkit.getServer().getConnectionThrottle(); + InetAddress address = ((InetSocketAddress) this.connection.getRemoteAddress()).getAddress(); + synchronized (throttleTracker) { + if (throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - throttleTracker.get(address) < connectionThrottle) { + throttleTracker.put(address, currentTime); + var component = Component.literal("Connection throttled! Please wait before reconnecting."); this.connection.send(new ClientboundLoginDisconnectPacket(component)); this.connection.disconnect(component); - break; + ci.cancel(); + return; } - if (packetIn.protocolVersion() < SharedConstants.getCurrentVersion().getProtocolVersion()) { - var component = Component.translatable(MessageFormat.format(SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName())); - this.connection.send(new ClientboundLoginDisconnectPacket(component)); - this.connection.disconnect(component); - break; - } - this.connection.setListener(new ServerLoginPacketListenerImpl(this.server, this.connection)); - - if (!VelocitySupport.isEnabled()) { - String[] split = packetIn.hostName().split("\00"); - if (SpigotConfig.bungee) { - if ((split.length == 3 || split.length == 4) && (HOST_PATTERN.matcher(split[1]).matches())) { - ((NetworkManagerBridge) this.connection).bridge$setHostname(split[0]); - this.connection.address = new InetSocketAddress(split[1], ((InetSocketAddress) this.connection.getRemoteAddress()).getPort()); - ((NetworkManagerBridge) this.connection).bridge$setSpoofedUUID(UndashedUuid.fromStringLenient(split[2])); - } else { - var component = Component.literal("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!"); - this.connection.send(new ClientboundLoginDisconnectPacket(component)); - this.connection.disconnect(component); - return; - } - if (split.length == 4) { - ((NetworkManagerBridge) this.connection).bridge$setSpoofedProfile(gson.fromJson(split[3], Property[].class)); - } - } else if ((split.length == 3 || split.length == 4) && (HOST_PATTERN.matcher(split[1]).matches())) { - Component component = Component.literal("Unknown data in login hostname, did you forget to enable BungeeCord in spigot.yml?"); - this.connection.send(new ClientboundLoginDisconnectPacket(component)); - this.connection.disconnect(component); - return; - } + throttleTracker.put(address, currentTime); + ++throttleCounter; + if (throttleCounter > 200) { + throttleCounter = 0; + throttleTracker.entrySet().removeIf(entry -> entry.getValue() > connectionThrottle); } - - break; } - case STATUS: { - ServerStatus serverstatus = this.server.getStatus(); - if (this.server.repliesToStatus() && serverstatus != null) { - this.connection.setClientboundProtocolAfterHandshake(ClientIntent.STATUS); - this.connection.setListener(new ServerStatusPacketListenerImpl(serverstatus, this.connection)); + } catch (Throwable t) { + LogManager.getLogger().debug("Failed to check connection throttle", t); + } + } + + @Inject(method = "beginLogin", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/Connection;setupInboundProtocol(Lnet/minecraft/network/ProtocolInfo;Lnet/minecraft/network/PacketListener;)V")) + private void arclight$proxySupport(ClientIntentionPacket packet, boolean bl, CallbackInfo ci) { + if (!VelocitySupport.isEnabled()) { + String[] split = packet.hostName().split("\00"); + if (SpigotConfig.bungee) { + if ((split.length == 3 || split.length == 4) && (HOST_PATTERN.matcher(split[1]).matches())) { + ((NetworkManagerBridge) this.connection).bridge$setHostname(split[0]); + this.connection.address = new InetSocketAddress(split[1], ((InetSocketAddress) this.connection.getRemoteAddress()).getPort()); + ((NetworkManagerBridge) this.connection).bridge$setSpoofedUUID(UndashedUuid.fromStringLenient(split[2])); } else { - this.connection.disconnect(IGNORE_STATUS_REASON); + var component = Component.literal("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!"); + this.connection.send(new ClientboundLoginDisconnectPacket(component)); + this.connection.disconnect(component); + ci.cancel(); + return; } - break; - } - default: { - throw new UnsupportedOperationException("Invalid intention " + packetIn.intention()); + if (split.length == 4) { + ((NetworkManagerBridge) this.connection).bridge$setSpoofedProfile(gson.fromJson(split[3], Property[].class)); + } + } else if ((split.length == 3 || split.length == 4) && (HOST_PATTERN.matcher(split[1]).matches())) { + Component component = Component.literal("Unknown data in login hostname, did you forget to enable BungeeCord in spigot.yml?"); + this.connection.send(new ClientboundLoginDisconnectPacket(component)); + this.connection.disconnect(component); + ci.cancel(); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerLoginNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerLoginNetHandlerMixin.java index 59cc3ab08..926329251 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerLoginNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerLoginNetHandlerMixin.java @@ -13,8 +13,12 @@ import net.minecraft.Util; import net.minecraft.core.UUIDUtil; import net.minecraft.network.Connection; +import net.minecraft.network.ConnectionProtocol; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketUtils; +import net.minecraft.network.protocol.cookie.ServerboundCookieResponsePacket; import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; import net.minecraft.network.protocol.login.ClientboundHelloPacket; import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; @@ -29,10 +33,11 @@ import net.minecraft.server.players.PlayerList; import net.minecraft.util.Crypt; import net.minecraft.util.CryptException; -import net.minecraft.world.entity.player.Player; +import net.minecraft.util.StringUtil; import org.apache.commons.lang3.Validate; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftServer; +import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.util.Waitable; import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerPreLoginEvent; @@ -62,7 +67,7 @@ import java.util.concurrent.atomic.AtomicInteger; @Mixin(ServerLoginPacketListenerImpl.class) -public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandlerBridge { +public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandlerBridge, CraftPlayer.TransferCookieConnection { // @formatter:off @Shadow private ServerLoginPacketListenerImpl.State state; @@ -77,6 +82,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle @Shadow abstract void startClientVerification(GameProfile p_301095_); @Shadow protected abstract boolean isPlayerAlreadyInWorld(GameProfile p_298499_); @Shadow @Nullable private GameProfile authenticatedProfile; + @Shadow @Final private boolean transferred; // @formatter:on private static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}"); @@ -105,7 +111,7 @@ public void disconnect(final String s) { @Overwrite public void handleHello(ServerboundHelloPacket packetIn) { Validate.validState(this.state == ServerLoginPacketListenerImpl.State.HELLO, "Unexpected hello packet"); - Validate.validState(Player.isValidUsername(packetIn.name()), "Invalid characters in username"); + Validate.validState(StringUtil.isValidPlayerName(packetIn.name()), "Invalid characters in username"); this.requestedUsername = packetIn.name(); GameProfile gameprofile = this.server.getSingleplayerProfile(); if (gameprofile != null && this.requestedUsername.equalsIgnoreCase(gameprofile.getName())) { @@ -113,7 +119,7 @@ public void handleHello(ServerboundHelloPacket packetIn) { } else { if (this.server.usesAuthentication() && !this.connection.isMemoryConnection()) { this.state = ServerLoginPacketListenerImpl.State.KEY; - this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge)); + this.connection.send(new ClientboundHelloPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.challenge, true)); } else { if (VelocitySupport.isEnabled()) { this.arclight$velocityLoginId = ThreadLocalRandom.current().nextInt(); @@ -131,6 +137,7 @@ public void handleHello(ServerboundHelloPacket packetIn) { LOGGER.warn("Exception verifying {} ", requestedUsername, ex); } }); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); thread.start(); } } @@ -159,7 +166,9 @@ public void handleHello(ServerboundHelloPacket packetIn) { @Redirect(method = "verifyLoginAndFinishConnectionSetup", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;")) private Component arclight$canLogin(PlayerList instance, SocketAddress socketAddress, GameProfile gameProfile) { - this.player = ((PlayerListBridge) instance).bridge$canPlayerLogin(socketAddress, gameProfile, (ServerLoginPacketListenerImpl) (Object) this); + if (this.player == null) { + this.player = ((PlayerListBridge) instance).bridge$canPlayerLogin(socketAddress, gameProfile, (ServerLoginPacketListenerImpl) (Object) this); + } return null; } @@ -167,6 +176,10 @@ public void handleHello(ServerboundHelloPacket packetIn) { private void arclight$returnIfFail(GameProfile p_299507_, CallbackInfo ci) { if (this.player == null) { ci.cancel(); + } else { + if (((CraftPlayer) this.player.bridge$getBukkitEntity()).isAwaitingCookies()) { + ci.cancel(); + } } } @@ -175,11 +188,24 @@ public void handleHello(ServerboundHelloPacket packetIn) { return this.isPlayerAlreadyInWorld(Objects.requireNonNull(this.authenticatedProfile)); } - @Inject(method = "handleLoginAcknowledgement", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;setListener(Lnet/minecraft/network/PacketListener;)V")) + @Inject(method = "handleLoginAcknowledgement", at = @At("HEAD")) + private void arclight$mainThreadConfiguration(ServerboundLoginAcknowledgedPacket serverboundLoginAcknowledgedPacket, CallbackInfo ci) { + PacketUtils.ensureRunningOnSameThread(serverboundLoginAcknowledgedPacket, (ServerLoginPacketListenerImpl) (Object) this, this.server); + } + + @Inject(method = "handleLoginAcknowledgement", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/network/Connection;setupInboundProtocol(Lnet/minecraft/network/ProtocolInfo;Lnet/minecraft/network/PacketListener;)V")) private void arclight$setPlayer(ServerboundLoginAcknowledgedPacket p_298815_, CallbackInfo ci, CommonListenerCookie cookie, ServerConfigurationPacketListenerImpl listener) { ((ServerCommonPacketListenerBridge) listener).bridge$setPlayer(this.player); } + @Inject(method = "handleCookieResponse", cancellable = true, at = @At("HEAD")) + private void arclight$cookieResponse(ServerboundCookieResponsePacket packet, CallbackInfo ci) { + PacketUtils.ensureRunningOnSameThread(packet, (ServerLoginPacketListenerImpl) (Object) this, this.server); + if (this.player != null && ((CraftPlayer) this.player.bridge$getBukkitEntity()).handleCookieResponse(packet)) { + ci.cancel(); + } + } + /** * @author IzzelAliz * @reason @@ -336,4 +362,19 @@ protected PlayerPreLoginEvent.Result evaluate() { ci.cancel(); } } + + @Override + public boolean isTransferred() { + return this.transferred; + } + + @Override + public ConnectionProtocol getProtocol() { + return ConnectionProtocol.LOGIN; + } + + @Override + public void sendPacket(Packet packet) { + this.connection.send(packet); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java index 26c763e6c..7a00a44e4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java @@ -1,31 +1,30 @@ package io.izzel.arclight.common.mixin.core.network; import com.mojang.brigadier.ParseResults; -import com.mojang.datafixers.util.Pair; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; import io.izzel.arclight.common.bridge.core.network.play.TimestampedPacket; import io.izzel.arclight.common.bridge.core.server.MinecraftServerBridge; import io.izzel.arclight.common.bridge.core.server.management.PlayerInteractionManagerBridge; import io.izzel.arclight.common.bridge.core.server.management.PlayerListBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; import io.izzel.arclight.common.mod.ArclightConstants; import io.izzel.arclight.common.mod.server.ArclightServer; +import io.izzel.arclight.common.mod.server.RunnableInPlace; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import net.minecraft.ChatFormatting; -import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.commands.CommandSigningContext; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.StringTag; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.Connection; +import net.minecraft.network.DisconnectionDetails; import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.LastSeenMessages; @@ -34,17 +33,14 @@ import net.minecraft.network.chat.SignableCommand; import net.minecraft.network.chat.SignedMessageChain; import net.minecraft.network.protocol.PacketUtils; -import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.network.protocol.game.ClientboundMoveVehiclePacket; -import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket; import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket; -import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; -import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket; -import net.minecraft.network.protocol.game.ServerboundChatCommandPacket; +import net.minecraft.network.protocol.game.ServerboundChatCommandSignedPacket; import net.minecraft.network.protocol.game.ServerboundChatPacket; +import net.minecraft.network.protocol.game.ServerboundClientCommandPacket; import net.minecraft.network.protocol.game.ServerboundContainerButtonClickPacket; import net.minecraft.network.protocol.game.ServerboundContainerClickPacket; import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; @@ -69,7 +65,9 @@ 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.server.network.CommonListenerCookie; +import net.minecraft.server.network.Filterable; import net.minecraft.server.network.FilteredText; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.players.PlayerList; @@ -79,23 +77,19 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.RelativeMovement; -import net.minecraft.world.entity.animal.Bucketable; -import net.minecraft.world.entity.animal.allay.Allay; -import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.ChatVisiblity; -import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MerchantMenu; import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.item.component.WritableBookContent; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; @@ -134,20 +128,18 @@ import org.bukkit.event.player.PlayerAnimationType; import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerInteractAtEntityEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; import org.bukkit.event.player.PlayerToggleSprintEvent; import org.bukkit.inventory.CraftingInventory; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.SmithingInventory; +import org.objectweb.asm.Opcodes; import org.slf4j.Logger; import org.spigotmc.SpigotConfig; import org.spongepowered.asm.mixin.Final; @@ -163,7 +155,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -172,16 +163,13 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.function.Function; -import java.util.function.UnaryOperator; import java.util.logging.Level; -import java.util.stream.Collectors; @Mixin(ServerGamePacketListenerImpl.class) public abstract class ServerPlayNetHandlerMixin extends ServerCommonPacketListenerImplMixin implements ServerPlayNetHandlerBridge { // @formatter:off @Shadow public ServerPlayer player; - @Shadow public abstract void onDisconnect(Component reason); @Shadow private Entity lastVehicle; @Shadow private double vehicleFirstGoodX; @Shadow private double vehicleFirstGoodY; @@ -213,7 +201,6 @@ public abstract class ServerPlayNetHandlerMixin extends ServerCommonPacketListen @Shadow private static double clampVertical(double p_143654_) { return 0; } @Shadow private static boolean containsInvalidValues(double p_143664_, double p_143665_, double p_143666_, float p_143667_, float p_143668_) { return false; } @Shadow @Final @Mutable private FutureChain chatMessageChain; - @Shadow protected abstract void updateBookPages(List p_143635_, UnaryOperator p_143636_, ItemStack p_143637_); @Shadow public abstract void ackBlockChangesUpTo(int p_215202_); @Shadow private static boolean isChatMessageIllegal(String p_215215_) { return false; } @Shadow protected abstract CompletableFuture filterTextPacket(String p_243213_); @@ -221,9 +208,14 @@ public abstract class ServerPlayNetHandlerMixin extends ServerCommonPacketListen @Shadow protected abstract void detectRateSpam(); @Shadow protected abstract PlayerChatMessage getSignedMessage(ServerboundChatPacket p_251061_, LastSeenMessages p_250566_) throws SignedMessageChain.DecodeException; @Shadow protected abstract void handleMessageDecodeFailure(SignedMessageChain.DecodeException p_252068_); - @Shadow protected abstract Map collectSignedArguments(ServerboundChatCommandPacket p_249441_, SignableCommand p_250039_, LastSeenMessages p_249207_) throws SignedMessageChain.DecodeException; @Shadow protected abstract boolean isPlayerCollidingWithAnythingNew(LevelReader p_289008_, AABB p_288986_, double p_288990_, double p_288991_, double p_288967_); - @Shadow protected abstract Optional tryHandleChat(LastSeenMessages.Update p_249613_); + @Shadow protected abstract boolean updateAwaitingTeleport(); + @Shadow protected abstract Filterable filterableFromOutgoing(FilteredText filteredText); + @Shadow protected abstract Optional unpackAndApplyLastSeen(LastSeenMessages.Update update); + @Shadow protected abstract void tryHandleChat(String string, Runnable runnable); + @Shadow protected abstract Map collectSignedArguments(ServerboundChatCommandSignedPacket serverboundChatCommandSignedPacket, SignableCommand signableCommand, LastSeenMessages lastSeenMessages) throws SignedMessageChain.DecodeException; + @Shadow public abstract void sendDisguisedChatMessage(Component component, ChatType.Bound bound); + @Shadow public abstract void teleport(double d, double e, double f, float g, float h, Set set); // @formatter:on private static final int SURVIVAL_PLACE_DISTANCE_SQUARED = 6 * 6; @@ -257,7 +249,7 @@ public abstract class ServerPlayNetHandlerMixin extends ServerCommonPacketListen } @Inject(method = "onDisconnect", cancellable = true, at = @At("HEAD")) - private void arclight$returnIfProcessed(Component reason, CallbackInfo ci) { + private void arclight$returnIfProcessed(DisconnectionDetails disconnectionDetails, CallbackInfo ci) { if (processedDisconnect) { ci.cancel(); } else { @@ -287,7 +279,7 @@ public void handleMoveVehicle(final ServerboundMoveVehiclePacket packetplayinveh PacketUtils.ensureRunningOnSameThread(packetplayinvehiclemove, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); if (containsInvalidValues(packetplayinvehiclemove.getX(), packetplayinvehiclemove.getY(), packetplayinvehiclemove.getZ(), packetplayinvehiclemove.getYRot(), packetplayinvehiclemove.getXRot())) { this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement")); - } else { + } else if (!this.updateAwaitingTeleport()) { Entity entity = this.player.getRootVehicle(); if (entity != this.player && entity.getControllingPassenger() == this.player && entity == this.lastVehicle) { ServerLevel worldserver = this.player.serverLevel(); @@ -416,7 +408,9 @@ public void handleMoveVehicle(final ServerboundMoveVehiclePacket packetplayinveh } } this.player.serverLevel().getChunkSource().move(this.player); - this.player.checkMovementStatistics(this.player.getX() - d0, this.player.getY() - d2, this.player.getZ() - d3); + Vec3 vec3d = new Vec3(entity.getX() - d0, entity.getY() - d2, entity.getZ() - d3); + this.player.setKnownMovement(vec3d); + this.player.checkMovementStatistics(vec3d.x, vec3d.y, vec3d.z); this.clientVehicleIsFloating = d11 >= -0.03125D && !flag1 && !this.server.isFlightAllowed() && !entity.isNoGravity() && this.noBlocksAround(entity); this.vehicleLastGoodX = entity.getX(); this.vehicleLastGoodY = entity.getY(); @@ -468,40 +462,19 @@ public void handleMoveVehicle(final ServerboundMoveVehiclePacket packetplayinveh */ @Overwrite private void updateBookContents(List list, int slot) { - ItemStack old = this.player.getInventory().getItem(slot); - if (old.is(Items.WRITABLE_BOOK)) { - ItemStack itemstack = old.copy(); - this.updateBookPages(list, UnaryOperator.identity(), itemstack); - CraftEventFactory.handleEditBookEvent(player, slot, old, itemstack); + ItemStack handItem = this.player.getInventory().getItem(slot); + ItemStack itemStack = handItem.copy(); + if (itemStack.is(Items.WRITABLE_BOOK)) { + List> list2 = list.stream().map(this::filterableFromOutgoing).toList(); + itemStack.set(DataComponents.WRITABLE_BOOK_CONTENT, new WritableBookContent(list2)); + CraftEventFactory.handleEditBookEvent(player, slot, handItem, itemStack); // CraftBukkit } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private void signBook(FilteredText text, List list, int slot) { - ItemStack old = this.player.getInventory().getItem(slot); - if (old.is(Items.WRITABLE_BOOK)) { - ItemStack itemStack = new ItemStack(Items.WRITTEN_BOOK); - CompoundTag compoundtag = old.getTag(); - if (compoundtag != null) { - itemStack.setTag(compoundtag.copy()); - } - - itemStack.addTagElement("author", StringTag.valueOf(this.player.getName().getString())); - ((ItemStackBridge) (Object) itemStack).bridge$platform$copyAdditionalFrom(old); - if (this.player.isTextFilteringEnabled()) { - itemStack.addTagElement("title", StringTag.valueOf(text.filteredOrEmpty())); - } else { - itemStack.addTagElement("filtered_title", StringTag.valueOf(text.filteredOrEmpty())); - itemStack.addTagElement("title", StringTag.valueOf(text.raw())); - } - - this.updateBookPages(list, (p_143659_) -> Component.Serializer.toJson(Component.literal(p_143659_)), itemStack); - this.player.getInventory().setItem(slot, CraftEventFactory.handleEditBookEvent(this.player, slot, old, itemStack)); - } + @Decorate(method = "signBook", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Inventory;setItem(ILnet/minecraft/world/item/ItemStack;)V")) + private void arclight$editBookEvent(Inventory instance, int i, ItemStack stack, FilteredText text, List list, int slot, @Local(ordinal = 0) ItemStack handStack) throws Throwable { + CraftEventFactory.handleEditBookEvent(player, i, handStack, stack); + DecorationOps.callsite().invoke(instance, i, handStack); } /** @@ -519,13 +492,7 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) { if (this.tickCount == 0) { this.resetPosition(); } - if (this.awaitingPositionFromClient != null) { - if (this.tickCount - this.awaitingTeleportTime > 20) { - this.awaitingTeleportTime = this.tickCount; - this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); - } - this.allowedPlayerTicks = 20; - } else { + if (!this.updateAwaitingTeleport()) { this.awaitingTeleportTime = this.tickCount; double d0 = clampHorizontal(packetplayinflying.getX(this.player.getX())); double d1 = clampVertical(packetplayinflying.getY(this.player.getY())); @@ -561,6 +528,7 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) { } } else { + boolean fallFlying = this.player.isFallFlying(); if (worldserver.tickRateManager().runsNormally()) { ++this.receivedMovePacketCount; int i = this.receivedMovePacketCount - this.knownMovePacketCount; @@ -630,7 +598,8 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) { } if (!this.player.noPhysics && !this.player.isSleeping() && (flag1 && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2))) { - this.internalTeleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. + this.bridge$pushNoTeleportEvent(); + this.teleport(d3, d4, d5, f, f1, Collections.emptySet()); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet. this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packetplayinflying.isOnGround()); } else { // Reset to old location first @@ -681,22 +650,29 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) { } this.player.absMoveTo(d0, d1, d2, f, f1); // Copied from above + boolean autoSpinAttack = this.player.isAutoSpinAttack(); this.clientIsFloating = d12 >= -0.03125D && this.player.gameMode.getGameModeForPlayer() != GameType.SPECTATOR && !this.server.isFlightAllowed() && !(this.player.getAbilities().mayfly || ((ServerPlayerEntityBridge) this.player).bridge$platform$mayfly()) && !this.player.hasEffect(MobEffects.LEVITATION) - && !this.player.isFallFlying() - && this.noBlocksAround(this.player) - && !this.player.isAutoSpinAttack(); + && !fallFlying + && !autoSpinAttack + && this.noBlocksAround(this.player); // CraftBukkit end this.player.serverLevel().getChunkSource().move(this.player); + var vec3 = new Vec3(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5); + this.player.setOnGroundWithMovement(packetplayinflying.isOnGround(), vec3); this.player.doCheckFallDamage(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5, packetplayinflying.isOnGround()); - this.player.setOnGroundWithKnownMovement(packetplayinflying.isOnGround(), new Vec3(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5)); + this.player.setKnownMovement(vec3); if (flag) { this.player.resetFallDistance(); } + if (packetplayinflying.isOnGround() || this.player.hasLandedInLiquid() || this.player.onClimbable() || this.player.isSpectator() || fallFlying || autoSpinAttack) { + this.player.tryResetCurrentImpulseContext(); + } + this.player.checkMovementStatistics(this.player.getX() - d3, this.player.getY() - d4, this.player.getZ() - d5); this.lastGoodX = this.player.getX(); this.lastGoodY = this.player.getY(); @@ -709,6 +685,13 @@ public void handleMovePlayer(ServerboundMovePlayerPacket packetplayinflying) { } } + @Inject(method = "updateAwaitingTeleport", at = @At("RETURN")) + private void arclight$setAllowedTicks(CallbackInfoReturnable cir) { + if (cir.getReturnValue()) { + this.allowedPlayerTicks = 20; + } + } + /** * @author IzzelAliz * @reason @@ -828,66 +811,58 @@ private boolean checkLimit(long timestamp) { return true; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleUseItem(ServerboundUseItemPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); + @Inject(method = "handleUseItem", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/server/level/ServerLevel;)V")) + private void arclight$spamCheck(ServerboundUseItemPacket packet, CallbackInfo ci) { if (((ServerPlayerEntityBridge) this.player).bridge$isMovementBlocked()) { + ci.cancel(); return; } if (!this.checkLimit(((TimestampedPacket) packet).bridge$timestamp())) { + ci.cancel(); return; } - this.ackBlockChangesUpTo(packet.getSequence()); - ServerLevel worldserver = this.player.serverLevel(); - InteractionHand enumhand = packet.getHand(); - ItemStack itemstack = this.player.getItemInHand(enumhand); - this.player.resetLastActionTime(); - if (!itemstack.isEmpty() && itemstack.isItemEnabled(worldserver.enabledFeatures())) { - float f1 = this.player.getXRot(); - float f2 = this.player.getYRot(); - double d0 = this.player.getX(); - double d2 = this.player.getY() + this.player.getEyeHeight(); - double d3 = this.player.getZ(); - Vec3 vec3d = new Vec3(d0, d2, d3); - float f3 = Mth.cos(-f2 * 0.017453292f - 3.1415927f); - float f4 = Mth.sin(-f2 * 0.017453292f - 3.1415927f); - float f5 = -Mth.cos(-f1 * 0.017453292f); - float f6 = Mth.sin(-f1 * 0.017453292f); - float f7 = f4 * f5; - float f8 = f3 * f5; - double d4 = (this.player.gameMode.getGameModeForPlayer() == GameType.CREATIVE) ? 5.0 : 4.5; - Vec3 vec3d2 = vec3d.add(f7 * d4, f6 * d4, f8 * d4); - BlockHitResult movingobjectposition = this.player.level().clip(new ClipContext(vec3d, vec3d2, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); - boolean cancelled; - if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemstack, enumhand); - cancelled = (event.useItemInHand() == Event.Result.DENY); - } else if (((PlayerInteractionManagerBridge) this.player.gameMode).bridge$isFiredInteract()) { - ((PlayerInteractionManagerBridge) this.player.gameMode).bridge$setFiredInteract(false); - cancelled = ((PlayerInteractionManagerBridge) this.player.gameMode).bridge$getInteractResult(); + } + + @Decorate(method = "handleUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;useItem(Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/InteractionHand;)Lnet/minecraft/world/InteractionResult;")) + private InteractionResult arclight$playerInteractEvent(ServerPlayerGameMode instance, ServerPlayer serverPlayer, net.minecraft.world.level.Level level, ItemStack itemStack, InteractionHand interactionHand, ServerboundUseItemPacket packet) throws Throwable { + float f2 = Mth.wrapDegrees(packet.getYRot()); + float f1 = Mth.wrapDegrees(packet.getXRot()); + double d0 = this.player.getX(); + double d2 = this.player.getY() + this.player.getEyeHeight(); + double d3 = this.player.getZ(); + Vec3 vec3d = new Vec3(d0, d2, d3); + float f3 = Mth.cos(-f2 * 0.017453292f - 3.1415927f); + float f4 = Mth.sin(-f2 * 0.017453292f - 3.1415927f); + float f5 = -Mth.cos(-f1 * 0.017453292f); + float f6 = Mth.sin(-f1 * 0.017453292f); + float f7 = f4 * f5; + float f8 = f3 * f5; + double d4 = this.player.blockInteractionRange(); + Vec3 vec3d2 = vec3d.add(f7 * d4, f6 * d4, f8 * d4); + HitResult movingobjectposition = this.player.level().clip(new ClipContext(vec3d, vec3d2, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.player)); + boolean cancelled; + if (movingobjectposition == null || movingobjectposition.getType() != HitResult.Type.BLOCK) { + org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemStack, interactionHand); + cancelled = event.useItemInHand() == Event.Result.DENY; + } else { + BlockHitResult movingobjectpositionblock = (BlockHitResult) movingobjectposition; + if (((PlayerInteractionManagerBridge) player.gameMode).bridge$isFiredInteract() && ((PlayerInteractionManagerBridge) player.gameMode).bridge$getInteractPosition().equals(movingobjectpositionblock.getBlockPos()) && ((PlayerInteractionManagerBridge) player.gameMode).bridge$getInteractHand() == interactionHand && ItemStack.isSameItemSameComponents(((PlayerInteractionManagerBridge) player.gameMode).bridge$getInteractItemStack(), itemStack)) { + cancelled = ((PlayerInteractionManagerBridge) player.gameMode).bridge$getInteractResult(); } else { - // TODO 1.20 update this - BlockHitResult movingobjectpositionblock = movingobjectposition; - PlayerInteractEvent event2 = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemstack, true, enumhand, movingobjectpositionblock.getLocation()); - cancelled = (event2.useItemInHand() == Event.Result.DENY); - } - if (cancelled) { - ((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity().updateInventory(); - return; - } - itemstack = this.player.getItemInHand(enumhand); // Update in case it was changed in the event - if (itemstack.isEmpty()) { - return; - } - InteractionResult actionresulttype = this.player.gameMode.useItem(this.player, worldserver, itemstack, enumhand); - if (actionresulttype.shouldSwing()) { - this.player.swing(enumhand, true); + org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, movingobjectpositionblock.getBlockPos(), movingobjectpositionblock.getDirection(), itemStack, true, interactionHand, movingobjectpositionblock.getLocation()); + cancelled = event.useItemInHand() == Event.Result.DENY; } + ((PlayerInteractionManagerBridge) player.gameMode).bridge$setFiredInteract(false); + } + if (cancelled) { + ((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity().updateInventory(); + return (InteractionResult) DecorationOps.cancel().invoke(); } + itemStack = this.player.getItemInHand(interactionHand); // Update in case it was changed in the event + if (itemStack.isEmpty()) { + return (InteractionResult) DecorationOps.cancel().invoke(); + } + return (InteractionResult) DecorationOps.callsite().invoke(instance, serverPlayer, level, itemStack, interactionHand); } @Inject(method = "handleTeleportToEntityPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDFF)V")) @@ -895,35 +870,29 @@ public void handleUseItem(ServerboundUseItemPacket packet) { ((ServerPlayerEntityBridge) this.player).bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause.SPECTATE); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); + @Inject(method = "handleSetCarriedItem", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/server/level/ServerLevel;)V")) + private void arclight$carriedItemBlocked(ServerboundSetCarriedItemPacket packet, CallbackInfo ci) { if (((ServerPlayerEntityBridge) this.player).bridge$isMovementBlocked()) { - return; + ci.cancel(); } - if (packet.getSlot() >= 0 && packet.getSlot() < net.minecraft.world.entity.player.Inventory.getSelectionSize()) { - PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); - this.cserver.getPluginManager().callEvent(event); - if (event.isCancelled()) { - this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); - this.player.resetLastActionTime(); - return; - } - if (this.player.getInventory().selected != packet.getSlot() && this.player.getUsedItemHand() == InteractionHand.MAIN_HAND) { - this.player.stopUsingItem(); - } - this.player.getInventory().selected = packet.getSlot(); + } + + @Inject(method = "handleSetCarriedItem", cancellable = true, at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/entity/player/Inventory;selected:I")) + private void arclight$itemHeldEvent(ServerboundSetCarriedItemPacket packet, CallbackInfo ci) { + PlayerItemHeldEvent event = new PlayerItemHeldEvent(this.getCraftPlayer(), this.player.getInventory().selected, packet.getSlot()); + this.cserver.getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.send(new ClientboundSetCarriedItemPacket(this.player.getInventory().selected)); this.player.resetLastActionTime(); - } else { - LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString()); - this.bridge$disconnect("Invalid hotbar selection (Hacking?)"); + ci.cancel(); } } + @Inject(method = "handleSetCarriedItem", at = @At(value = "INVOKE", shift = At.Shift.AFTER, remap = false, target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V")) + private void arclight$kickOutOfBoundClick(ServerboundSetCarriedItemPacket serverboundSetCarriedItemPacket, CallbackInfo ci) { + this.bridge$disconnect("Invalid hotbar selection (Hacking?)"); + } + /** * @author IzzelAliz * @reason @@ -933,11 +902,9 @@ public void handleChat(ServerboundChatPacket packet) { if (this.server.isStopped()) { return; } - if (isChatMessageIllegal(packet.message())) { - this.disconnect(Component.translatable("multiplayer.disconnect.illegal_characters")); - } else { - var optional = this.tryHandleChat(packet.lastSeenMessages()); - if (optional.isPresent()) { + Optional optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages()); + if (!optional.isEmpty()) { + this.tryHandleChat(packet.message(), RunnableInPlace.wrap(() -> { PlayerChatMessage playerchatmessage; try { @@ -957,24 +924,45 @@ public void handleChat(ServerboundChatPacket packet) { this.broadcastChatMessage(playerchatmessage1); } ); - } + })); } } - @Inject(method = "*", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) - private void arclight$rejectIfDisconnect(CallbackInfo ci) { + @Inject(method = "performSignedChatCommand", cancellable = true, at = @At("HEAD")) + private void arclight$rejectIfDisconnectSigned(CallbackInfo ci) { if (this.player.hasDisconnected()) { ci.cancel(); } } + @Decorate(method = "performUnsignedChatCommand", inject = true, at = @At("HEAD")) + private void arclight$commandPreprocessEvent(String s) throws Throwable { + if (this.player.hasDisconnected()) { + DecorationOps.cancel().invoke(); + return; + } + String command = "/" + s; + LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); + + PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); + this.cserver.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + DecorationOps.cancel().invoke(); + return; + } + s = event.getMessage().substring(1); + DecorationOps.blackhole().invoke(s); + } + /** * @author IzzelAliz * @reason */ @Overwrite - private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMessages lastseenmessages) { - String command = "/" + packet.command(); + private void performSignedChatCommand(ServerboundChatCommandSignedPacket serverboundchatcommandsignedpacket, LastSeenMessages lastseenmessages) { + // CraftBukkit start + String command = "/" + serverboundchatcommandsignedpacket.command(); LOGGER.info(this.player.getScoreboardName() + " issued server command: " + command); PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(getCraftPlayer(), command, new LazyPlayerSet(server)); @@ -986,27 +974,30 @@ private void performChatCommand(ServerboundChatCommandPacket packet, LastSeenMes command = event.getMessage().substring(1); ParseResults parseresults = this.parseCommand(command); + // CraftBukkit end - Map map; + Map map; try { - map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastseenmessages) : Collections.emptyMap(); // CraftBukkit - } catch (SignedMessageChain.DecodeException e) { - this.handleMessageDecodeFailure(e); + map = (serverboundchatcommandsignedpacket.command().equals(command)) ? this.collectSignedArguments(serverboundchatcommandsignedpacket, SignableCommand.of(parseresults), lastseenmessages) : Collections.emptyMap(); // CraftBukkit + } catch (SignedMessageChain.DecodeException signedmessagechain_a) { + this.handleMessageDecodeFailure(signedmessagechain_a); return; } - CommandSigningContext.SignedArguments arguments = new CommandSigningContext.SignedArguments(map); + CommandSigningContext.SignedArguments commandsigningcontext_a = new CommandSigningContext.SignedArguments(map); - parseresults = Commands.mapSource(parseresults, (stack) -> stack.withSigningContext(arguments, this.chatMessageChain)); - this.server.getCommands().performCommand(parseresults, command); + parseresults = Commands.mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error + return commandlistenerwrapper.withSigningContext(commandsigningcontext_a, this.chatMessageChain); + }); + this.server.getCommands().performCommand(parseresults, command); // CraftBukkit } - @Inject(method = "tryHandleChat", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;unpackAndApplyLastSeen(Lnet/minecraft/network/chat/LastSeenMessages$Update;)Ljava/util/Optional;")) - private void arclight$deadMenTellNoTales(LastSeenMessages.Update p_249613_, CallbackInfoReturnable> cir) { + @Inject(method = "tryHandleChat", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;getChatVisibility()Lnet/minecraft/world/entity/player/ChatVisiblity;")) + private void arclight$deadMenTellNoTales(String string, Runnable runnable, CallbackInfo ci) { if (this.player.isRemoved()) { this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false)); - cir.setReturnValue(Optional.empty()); + ci.cancel(); } } @@ -1130,17 +1121,23 @@ private void broadcastChatMessage(PlayerChatMessage playerchatmessage) { this.detectRateSpam(); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleAnimate(ServerboundSwingPacket packet) { - PacketUtils.ensureRunningOnSameThread(packet, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); + @Inject(method = "sendPlayerChatMessage", cancellable = true, at = @At("HEAD")) + private void arclight$cantSee(PlayerChatMessage playerChatMessage, ChatType.Bound bound, CallbackInfo ci) { + if (!getCraftPlayer().canSeePlayer(playerChatMessage.link().sender())) { + sendDisguisedChatMessage(playerChatMessage.decoratedContent(), bound); + ci.cancel(); + } + } + + @Inject(method = "handleAnimate", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/server/level/ServerLevel;)V")) + private void arclight$interactCheck(ServerboundSwingPacket packet, CallbackInfo ci) { if (((ServerPlayerEntityBridge) this.player).bridge$isMovementBlocked()) { - return; + ci.cancel(); } - this.player.resetLastActionTime(); + } + + @Inject(method = "handleAnimate", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;swing(Lnet/minecraft/world/InteractionHand;)V")) + private void arclight$animateEvents(ServerboundSwingPacket packet, CallbackInfo ci) { float f1 = this.player.getXRot(); float f2 = this.player.getYRot(); double d0 = this.player.getX(); @@ -1158,9 +1155,8 @@ public void handleAnimate(ServerboundSwingPacket packet) { PlayerAnimationEvent event = new PlayerAnimationEvent(this.getCraftPlayer(), packet.getHand() == InteractionHand.MAIN_HAND ? PlayerAnimationType.ARM_SWING : PlayerAnimationType.OFF_ARM_SWING); this.cserver.getPluginManager().callEvent(event); if (event.isCancelled()) { - return; + ci.cancel(); } - this.player.swing(packet.getHand()); } @Inject(method = "handlePlayerCommand", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;resetLastActionTime()V")) @@ -1184,124 +1180,28 @@ public void handleAnimate(ServerboundSwingPacket packet) { } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleInteract(final ServerboundInteractPacket packetIn) { - PacketUtils.ensureRunningOnSameThread(packetIn, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); + @Inject(method = "handleInteract", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/server/level/ServerLevel;)V")) + private void arclight$interactCheck(ServerboundInteractPacket packet, CallbackInfo ci) { if (((ServerPlayerEntityBridge) this.player).bridge$isMovementBlocked()) { + ci.cancel(); return; } final ServerLevel world = this.player.serverLevel(); - final Entity entity = packetIn.getTarget(world); + final Entity entity = packet.getTarget(world); if (entity == player && !player.isSpectator()) { bridge$disconnect("Cannot interact with self!"); - return; + ci.cancel(); } - this.player.resetLastActionTime(); - this.player.setShiftKeyDown(packetIn.isUsingSecondaryAction()); - if (entity != null) { - if (!world.getWorldBorder().isWithinBounds(entity.blockPosition())) { - return; - } - class Handler implements ServerboundInteractPacket.Handler { - - private void performInteraction(InteractionHand hand, ServerGamePacketListenerImpl.EntityInteraction interaction, PlayerInteractEntityEvent event) { // CraftBukkit - var stack = player.getItemInHand(hand); - if (!stack.isItemEnabled(world.enabledFeatures())) - return; - ItemStack itemstack = stack.copy(); - // CraftBukkit start - ItemStack itemInHand = player.getItemInHand(hand); - boolean triggerLeashUpdate = itemInHand != null && itemInHand.getItem() == Items.LEAD && entity instanceof Mob; - Item origItem = player.getInventory().getSelected() == null ? null : player.getInventory().getSelected().getItem(); - - cserver.getPluginManager().callEvent(event); - - // Fish bucket - SPIGOT-4048 - if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { - send(new ClientboundAddEntityPacket((LivingEntity) entity)); - player.containerMenu.sendAllDataToRemote(); - } - - if (triggerLeashUpdate && (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem)) { - // Refresh the current leash state - send(new ClientboundSetEntityLinkPacket(entity, ((Mob) entity).getLeashHolder())); - } - - if (event.isCancelled() || player.getInventory().getSelected() == null || player.getInventory().getSelected().getItem() != origItem) { - // Refresh the current entity metadata - ((SynchedEntityDataBridge) entity.getEntityData()).bridge$refresh(player); - if (entity instanceof Allay) { - send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()))); - player.containerMenu.sendAllDataToRemote(); - } - } - - if (event.isCancelled()) { - return; - } - // CraftBukkit end - - InteractionResult enuminteractionresult = interaction.run(player, entity, hand); - - // CraftBukkit start - if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { - player.containerMenu.sendAllDataToRemote(); - } - // CraftBukkit end - - if (enuminteractionresult.consumesAction()) { - CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(player, itemstack, entity); - if (enuminteractionresult.shouldSwing()) { - player.swing(hand, true); - } - } - - } - - @Override - public void onInteraction(InteractionHand hand) { - this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, - new PlayerInteractEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), - (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); - } - - @Override - public void onInteraction(InteractionHand hand, Vec3 vec) { - this.performInteraction(hand, (player, e, h) -> { - var onInteractEntityAtResult = bridge$platform$onInteractEntityAt(player, entity, vec, hand); - if (onInteractEntityAtResult != null) { - return onInteractEntityAtResult; - } - return e.interactAt(player, vec, h); - }, - new PlayerInteractAtEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), - new org.bukkit.util.Vector(vec.x, vec.y, vec.z), (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); - } + } - @Override - public void onAttack() { - if (!(entity instanceof ItemEntity) && !(entity instanceof ExperienceOrb) && !(entity instanceof AbstractArrow) && (entity != player || player.isSpectator())) { - ItemStack itemInHand = player.getMainHandItem(); - if (!itemInHand.isItemEnabled(world.enabledFeatures())) return; - if (((PlayerEntityBridge) player).bridge$platform$canReach(entity, 3)) { //Forge: Perform attack range check. Original check was dist < 6, range is 3, so vanilla used padding=3 - player.attack(entity); - } + @Inject(method = "handleClientCommand", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/players/PlayerList;respawn(Lnet/minecraft/server/level/ServerPlayer;ZLnet/minecraft/world/entity/Entity$RemovalReason;)Lnet/minecraft/server/level/ServerPlayer;")) + private void arclight$respawnChangeDim(ServerboundClientCommandPacket packet, CallbackInfo ci) { + ((PlayerListBridge) this.server.getPlayerList()).bridge$pushRespawnCause(PlayerRespawnEvent.RespawnReason.END_PORTAL); + } - if (!itemInHand.isEmpty() && itemInHand.getCount() <= -1) { - player.containerMenu.sendAllDataToRemote(); - } - } else { - disconnect(Component.translatable("multiplayer.disconnect.invalid_entity_attacked")); - LOGGER.warn("Player {} tried to attack an invalid entity", player.getName().getString()); - } - } - } - packetIn.dispatch(new Handler()); - } + @Inject(method = "handleClientCommand", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/server/players/PlayerList;respawn(Lnet/minecraft/server/level/ServerPlayer;ZLnet/minecraft/world/entity/Entity$RemovalReason;)Lnet/minecraft/server/level/ServerPlayer;")) + private void arclight$respawnKilled(ServerboundClientCommandPacket packet, CallbackInfo ci) { + ((PlayerListBridge) this.server.getPlayerList()).bridge$pushRespawnCause(PlayerRespawnEvent.RespawnReason.DEATH); } @Inject(method = "handleContainerClose", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;doCloseContainer()V")) @@ -1377,7 +1277,7 @@ public void handleContainerClick(ServerboundContainerClickPacket packet) { if (cursor.isEmpty()) { action = packet.getButtonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF; } else if (slot.mayPlace(cursor)) { - if (ItemStack.isSameItemSameTags(clickedItem, cursor)) { + if (ItemStack.isSameItemSameComponents(clickedItem, cursor)) { int toPlace = packet.getButtonNum() == 0 ? cursor.getCount() : 1; toPlace = Math.min(toPlace, clickedItem.getMaxStackSize() - clickedItem.getCount()); toPlace = Math.min(toPlace, slot.container.getMaxStackSize() - clickedItem.getCount()); @@ -1393,7 +1293,7 @@ public void handleContainerClick(ServerboundContainerClickPacket packet) { } else if (cursor.getCount() <= slot.getMaxStackSize()) { action = InventoryAction.SWAP_WITH_CURSOR; } - } else if (ItemStack.isSameItemSameTags(cursor, clickedItem)) { + } else if (ItemStack.isSameItemSameComponents(cursor, clickedItem)) { if (clickedItem.getCount() >= 0) { if (clickedItem.getCount() + cursor.getCount() <= cursor.getMaxStackSize()) { // As of 1.5, this is result slots only @@ -1663,34 +1563,35 @@ public void handleContainerClick(ServerboundContainerClickPacket packet) { public void handleSetCreativeModeSlot(final ServerboundSetCreativeModeSlotPacket packetplayinsetcreativeslot) { PacketUtils.ensureRunningOnSameThread(packetplayinsetcreativeslot, (ServerGamePacketListenerImpl) (Object) this, this.player.serverLevel()); if (this.player.gameMode.isCreative()) { - final boolean flag = packetplayinsetcreativeslot.getSlotNum() < 0; - ItemStack itemstack = packetplayinsetcreativeslot.getItem(); - final CompoundTag nbttagcompound = BlockItem.getBlockEntityData(itemstack); - if (!itemstack.isEmpty() && nbttagcompound != null && nbttagcompound.contains("x") && nbttagcompound.contains("y") && nbttagcompound.contains("z")) { - BlockPos blockpos = BlockEntity.getPosFromTag(nbttagcompound); + final boolean flag = packetplayinsetcreativeslot.slotNum() < 0; + ItemStack itemstack = packetplayinsetcreativeslot.itemStack(); + CustomData customdata = (CustomData) itemstack.getOrDefault(DataComponents.BLOCK_ENTITY_DATA, CustomData.EMPTY); + + if (customdata.contains("x") && customdata.contains("y") && customdata.contains("z") && this.player.bridge$getBukkitEntity().hasPermission("minecraft.nbt.copy")) { + BlockPos blockpos = BlockEntity.getPosFromTag(customdata.getUnsafe()); if (this.player.level().isLoaded(blockpos)) { BlockEntity blockentity = this.player.level().getBlockEntity(blockpos); if (blockentity != null) { - blockentity.saveToItem(itemstack); + blockentity.saveToItem(itemstack, this.player.level().registryAccess()); } } } - final boolean flag2 = packetplayinsetcreativeslot.getSlotNum() >= 1 && packetplayinsetcreativeslot.getSlotNum() <= 45; + final boolean flag2 = packetplayinsetcreativeslot.slotNum() >= 1 && packetplayinsetcreativeslot.slotNum() <= 45; boolean flag3 = itemstack.isEmpty() || (itemstack.getDamageValue() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty()); - if (flag || (flag2 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem(), packetplayinsetcreativeslot.getItem()))) { + if (flag || (flag2 && !ItemStack.matches(this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.slotNum()).getItem(), packetplayinsetcreativeslot.itemStack()))) { final InventoryView inventory = ((ContainerBridge) this.player.inventoryMenu).bridge$getBukkitView(); - final org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.getItem()); + final org.bukkit.inventory.ItemStack item = CraftItemStack.asBukkitCopy(packetplayinsetcreativeslot.itemStack()); InventoryType.SlotType type = InventoryType.SlotType.QUICKBAR; if (flag) { type = InventoryType.SlotType.OUTSIDE; - } else if (packetplayinsetcreativeslot.getSlotNum() < 36) { - if (packetplayinsetcreativeslot.getSlotNum() >= 5 && packetplayinsetcreativeslot.getSlotNum() < 9) { + } else if (packetplayinsetcreativeslot.slotNum() < 36) { + if (packetplayinsetcreativeslot.slotNum() >= 5 && packetplayinsetcreativeslot.slotNum() < 9) { type = InventoryType.SlotType.ARMOR; } else { type = InventoryType.SlotType.CONTAINER; } } - final InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetplayinsetcreativeslot.getSlotNum(), item); + final InventoryCreativeEvent event = new InventoryCreativeEvent(inventory, type, flag ? -999 : packetplayinsetcreativeslot.slotNum(), item); this.cserver.getPluginManager().callEvent(event); itemstack = CraftItemStack.asNMSCopy(event.getCursor()); switch (event.getResult()) { @@ -1701,8 +1602,8 @@ public void handleSetCreativeModeSlot(final ServerboundSetCreativeModeSlotPacket case DEFAULT: break; case DENY: { - if (packetplayinsetcreativeslot.getSlotNum() >= 0) { - this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinsetcreativeslot.getSlotNum(), this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).getItem())); + if (packetplayinsetcreativeslot.slotNum() >= 0) { + this.player.connection.send(new ClientboundContainerSetSlotPacket(this.player.inventoryMenu.containerId, this.player.inventoryMenu.incrementStateId(), packetplayinsetcreativeslot.slotNum(), this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.slotNum()).getItem())); this.player.connection.send(new ClientboundContainerSetSlotPacket(-1, this.player.inventoryMenu.incrementStateId(), -1, ItemStack.EMPTY)); } return; @@ -1710,7 +1611,7 @@ public void handleSetCreativeModeSlot(final ServerboundSetCreativeModeSlotPacket } } if (flag2 && flag3) { - this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.getSlotNum()).setByPlayer(itemstack); + this.player.inventoryMenu.getSlot(packetplayinsetcreativeslot.slotNum()).setByPlayer(itemstack); this.player.inventoryMenu.broadcastChanges(); } else if (flag && flag3 && this.dropSpamTickCount < 200) { this.dropSpamTickCount += 20; @@ -1744,18 +1645,17 @@ public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) { } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void teleport(double x, double y, double z, float yaw, float pitch, Set relativeSet) { + private transient boolean arclight$noTeleportEvent; + private transient boolean arclight$teleportCancelled; + + @Decorate(method = "teleport(DDDFFLjava/util/Set;)V", inject = true, at = @At("HEAD")) + private void arclight$teleportEvent(double x, double y, double z, float yaw, float pitch, Set relativeSet) throws Throwable { PlayerTeleportEvent.TeleportCause cause = arclight$cause == null ? PlayerTeleportEvent.TeleportCause.UNKNOWN : arclight$cause; arclight$cause = null; Player player = this.getCraftPlayer(); Location from = player.getLocation(); Location to = new Location(this.getCraftPlayer().getWorld(), x, y, z, yaw, pitch); - if (!from.equals(to)) { + if (!arclight$noTeleportEvent && !from.equals(to)) { PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), cause); this.cserver.getPluginManager().callEvent(event); if (event.isCancelled() || !to.equals(event.getTo())) { @@ -1767,7 +1667,11 @@ public void teleport(double x, double y, double z, float yaw, float pitch, Set set, CallbackInfo ci) { + this.lastPosX = this.awaitingPositionFromClient.x; + this.lastPosY = this.awaitingPositionFromClient.y; + this.lastPosZ = this.awaitingPositionFromClient.z; + this.lastYaw = yaw; + this.lastPitch = pitch; } public void teleport(double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { @@ -1787,35 +1701,15 @@ public void teleport(double d0, double d1, double d2, float f, float f1, Set set) { - if (Float.isNaN(f)) { - f = 0.0f; - } - if (Float.isNaN(f1)) { - f1 = 0.0f; - } - this.justTeleported = true; - double d3 = set.contains(RelativeMovement.X) ? this.player.getX() : 0.0; - double d4 = set.contains(RelativeMovement.Y) ? this.player.getY() : 0.0; - double d5 = set.contains(RelativeMovement.Z) ? this.player.getZ() : 0.0; - float f2 = set.contains(RelativeMovement.Y_ROT) ? this.player.getYRot() : 0.0f; - float f3 = set.contains(RelativeMovement.X_ROT) ? this.player.getXRot() : 0.0f; - this.awaitingPositionFromClient = new Vec3(d0, d1, d2); - if (++this.awaitingTeleport == Integer.MAX_VALUE) { - this.awaitingTeleport = 0; - } - this.lastPosX = this.awaitingPositionFromClient.x; - this.lastPosY = this.awaitingPositionFromClient.y; - this.lastPosZ = this.awaitingPositionFromClient.z; - this.lastYaw = f; - this.lastPitch = f1; - this.awaitingTeleportTime = this.tickCount; - this.player.absMoveTo(d0, d1, d2, f, f1); - this.player.connection.send(new ClientboundPlayerPositionPacket(d0 - d3, d1 - d4, d2 - d5, f - f2, f1 - f3, set, this.awaitingTeleport)); + public void teleport(Location dest) { + arclight$noTeleportEvent = true; + this.teleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); + arclight$noTeleportEvent = false; } - public void teleport(Location dest) { - this.internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet()); + @Override + public void bridge$pushNoTeleportEvent() { + arclight$noTeleportEvent = true; } private transient PlayerTeleportEvent.TeleportCause arclight$cause; @@ -1829,4 +1723,9 @@ public void teleport(Location dest) { public void bridge$teleport(Location dest) { teleport(dest); } + + @Override + public boolean bridge$teleportCancelled() { + return arclight$teleportCancelled; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerStatusNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerStatusNetHandlerMixin.java index 46cbfad98..1630fde6b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerStatusNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerStatusNetHandlerMixin.java @@ -49,7 +49,7 @@ public class ServerStatusNetHandlerMixin implements ServerStatusPacketListenerBr Collections.shuffle(profiles); profiles = profiles.subList(0, Math.min(profiles.size(), SpigotConfig.playerSample)); } - ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), profiles.size(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); + ServerStatus.Players playerSample = new ServerStatus.Players(event.getMaxPlayers(), event.getNumPlayers(), (server.hidesOnlinePlayers()) ? Collections.emptyList() : profiles); ServerStatus ping = bridge$platform$createServerStatus( CraftChatMessage.fromString(event.getMotd(), true)[0], Optional.of(playerSample), diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/SynchedEntityDataMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/SynchedEntityDataMixin.java index 1741f8531..070c02648 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/SynchedEntityDataMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/SynchedEntityDataMixin.java @@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.SyncedDataHolder; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; @@ -25,9 +26,8 @@ public abstract class SynchedEntityDataMixin implements SynchedEntityDataBridge // @formatter:off @Shadow protected abstract SynchedEntityData.DataItem getItem(EntityDataAccessor key); @Shadow private boolean isDirty; - @Shadow @Final private Entity entity; + @Shadow @Final private SyncedDataHolder entity; @Shadow @Nullable public abstract List> getNonDefaultValues(); - @Shadow public abstract boolean isEmpty(); // @formatter:on @Inject(method = "set(Lnet/minecraft/network/syncher/EntityDataAccessor;Ljava/lang/Object;Z)V", at = @At("HEAD")) @@ -51,11 +51,9 @@ public void markDirty(EntityDataAccessor key) { } public void refresh(ServerPlayer player) { - if (!this.isEmpty()) { - var list = this.getNonDefaultValues(); - if (list != null) { - player.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list)); - } + var list = this.getNonDefaultValues(); + if (list != null && this.entity instanceof Entity entity) { + player.connection.send(new ClientboundSetEntityDataPacket(entity.getId(), list)); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/PacketThreadUtilMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/PacketThreadUtilMixin.java index 48d8d14d4..673e8f352 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/PacketThreadUtilMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/PacketThreadUtilMixin.java @@ -1,12 +1,12 @@ package io.izzel.arclight.common.mixin.core.network.protocol; import io.izzel.arclight.common.bridge.core.network.common.ServerCommonPacketListenerBridge; -import net.minecraft.CrashReport; import net.minecraft.ReportedException; import net.minecraft.network.PacketListener; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketUtils; import net.minecraft.server.RunningOnDifferentThreadException; +import net.minecraft.server.network.ServerCommonPacketListenerImpl; import net.minecraft.util.thread.BlockableEventLoop; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; @@ -15,9 +15,12 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(PacketUtils.class) -public class PacketThreadUtilMixin { +public abstract class PacketThreadUtilMixin { + // @formatter:off @Shadow @Final private static Logger LOGGER; + @Shadow public static ReportedException makeReportedException(Exception exception, Packet packet, T packetListener) { throw new RuntimeException(); } + // @formatter:on /** * @author IzzelAliz @@ -27,7 +30,7 @@ public class PacketThreadUtilMixin { public static void ensureRunningOnSameThread(Packet packetIn, T processor, BlockableEventLoop executor) throws RunningOnDifferentThreadException { if (!executor.isSameThread()) { executor.executeIfPossible(() -> { - if (processor instanceof ServerCommonPacketListenerBridge && ((ServerCommonPacketListenerBridge) processor).bridge$processedDisconnect()) { + if (processor instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerBridge) processor).bridge$processedDisconnect()) { return; } if (processor.isAcceptingMessages()) { @@ -36,23 +39,13 @@ public static void ensureRunningOnSameThread(Packet CustomPacketPayload.FallbackProvider arclight$fallbackBukkit(CustomPacketPayload.FallbackProvider arg) { + return resourceLocation -> { + if (Bukkit.getMessenger().getIncomingChannels().contains(resourceLocation.toString()) + || Bukkit.getMessenger().getOutgoingChannels().contains(resourceLocation.toString())) { + return DiscardedPayloadCodec.codec(resourceLocation, 32767); + } else { + return arg.create(resourceLocation); + } + }; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/common/custom/DiscardedPayloadMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/common/custom/DiscardedPayloadMixin.java new file mode 100644 index 000000000..db2f6c553 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/common/custom/DiscardedPayloadMixin.java @@ -0,0 +1,37 @@ +package io.izzel.arclight.common.mixin.core.network.protocol.common.custom; + +import io.izzel.arclight.common.bridge.core.network.common.DiscardedPayloadBridge; +import io.izzel.arclight.common.mod.mixins.annotation.CreateConstructor; +import io.izzel.arclight.common.mod.mixins.annotation.ShadowConstructor; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.protocol.common.custom.DiscardedPayload; +import net.minecraft.resources.ResourceLocation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(DiscardedPayload.class) +public class DiscardedPayloadMixin implements DiscardedPayloadBridge { + + @ShadowConstructor + public void arclight$constructor(ResourceLocation rl) { + throw new RuntimeException(); + } + + @CreateConstructor + public void arclight$constructor(ResourceLocation rl, ByteBuf data) { + this.arclight$constructor(rl); + this.data = data; + } + + @Unique private ByteBuf data; + + @Override + public void bridge$setData(ByteBuf data) { + this.data = data; + } + + @Override + public ByteBuf bridge$getData() { + return this.data; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/ClientboundSystemChatPacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/ClientboundSystemChatPacketMixin.java index bb218cb7c..79ab1dc3a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/ClientboundSystemChatPacketMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/protocol/game/ClientboundSystemChatPacketMixin.java @@ -6,6 +6,7 @@ import net.md_5.bungee.chat.ComponentSerializer; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundSystemChatPacket; +import org.bukkit.craftbukkit.v.util.CraftChatMessage; import org.spongepowered.asm.mixin.Mixin; @Mixin(ClientboundSystemChatPacket.class) @@ -18,6 +19,6 @@ public class ClientboundSystemChatPacketMixin { @CreateConstructor public void arclight$constructor(BaseComponent[] content, boolean overlay) { - arclight$constructor(Component.Serializer.fromJson(ComponentSerializer.toString(content)), overlay); + arclight$constructor(CraftChatMessage.fromJSON(ComponentSerializer.toString(content)), overlay); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java index d98e04aad..7f453168c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/MinecraftServerMixin.java @@ -14,6 +14,7 @@ import io.izzel.arclight.common.mod.util.BukkitOptionParser; import io.izzel.arclight.mixin.Decorate; import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import it.unimi.dsi.fastutil.longs.LongIterator; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -39,19 +40,16 @@ import net.minecraft.server.WorldStem; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.TicketType; import net.minecraft.server.level.progress.ChunkProgressListener; import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.players.PlayerList; -import net.minecraft.util.TimeUtil; -import net.minecraft.util.Unit; +import net.minecraft.util.Mth; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.util.profiling.jfr.JvmProfiler; import net.minecraft.util.thread.ReentrantBlockableEventLoop; import net.minecraft.world.level.ChunkPos; -import net.minecraft.world.level.DataPackConfig; import net.minecraft.world.level.ForcedChunksSavedData; +import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.levelgen.WorldOptions; @@ -63,6 +61,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.RemoteConsoleCommandSender; +import org.bukkit.craftbukkit.v.CraftRegistry; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.scoreboard.CraftScoreboardManager; import org.bukkit.event.server.ServerLoadEvent; @@ -83,7 +82,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; -import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.Proxy; @@ -112,7 +110,6 @@ public abstract class MinecraftServerMixin extends ReentrantBlockableEventLoop OVERLOADED_THRESHOLD_NANOS + 20L * i && this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * i) { - long k = j / i; - - if (server.getWarnOnOverload()) // CraftBukkit - MinecraftServer.LOGGER.warn("Can't keep up! Is the server overloaded? Running {}ms or {} ticks behind", j / TimeUtil.NANOSECONDS_PER_MILLISECOND, k); - this.nextTickTimeNanos += k * i; - this.lastOverloadWarningNanos = this.nextTickTimeNanos; - } - } - - if (tickCount++ % SAMPLE_INTERVAL == 0) { - long curTime = Util.getMillis(); - double currentTps = 1E3 / (curTime - tickSection) * SAMPLE_INTERVAL; - recentTps[0] = calcTps(recentTps[0], 0.92, currentTps); // 1/exp(5sec/1min) - recentTps[1] = calcTps(recentTps[1], 0.9835, currentTps); // 1/exp(5sec/5min) - recentTps[2] = calcTps(recentTps[2], 0.9945, currentTps); // 1/exp(5sec/15min) - tickSection = curTime; - } - - boolean flag = i == 0L; - - currentTick = (int) (System.currentTimeMillis() / 50); - - if (this.debugCommandProfilerDelayStart) { - this.debugCommandProfilerDelayStart = false; - this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount); - } - - this.nextTickTimeNanos += i; - this.startMetricsRecordingTick(); - this.profiler.push("tick"); - this.tickServer(flag ? () -> false : this::haveTime); - this.profiler.popPush("nextTickWait"); - this.mayHaveDelayedTasks = true; - this.delayedTasksMaxNextTickTimeNanos = Math.max(Util.getNanos() + i, this.nextTickTimeNanos); - this.waitUntilNextTick(); - if (flag) { - this.tickRateManager.endTickWork(); - } - this.profiler.pop(); - this.endMetricsRecordingTick(); - this.isReady = true; - JvmProfiler.INSTANCE.onServerTick(this.smoothedTickTimeMillis); - } - this.bridge$platform$serverStopping(); - this.bridge$forge$expectServerStopped(); // has to come before finalTick to avoid race conditions - } catch (Throwable throwable1) { - LOGGER.error("Encountered an unexpected exception", throwable1); - CrashReport crashreport = constructOrExtractCrashReport(throwable1); - this.fillSystemReport(crashreport.getSystemReport()); - File file1 = new File(new File(this.getServerDirectory(), "crash-reports"), "crash-" + Util.getFilenameFormattedDateTime() + "-server.txt"); - if (crashreport.saveToFile(file1)) { - LOGGER.error("This crash report has been saved to: {}", file1.getAbsolutePath()); - } else { - LOGGER.error("We were unable to save this crash report to disk."); - } + @Decorate(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;buildServerStatus()Lnet/minecraft/network/protocol/status/ServerStatus;")) + private ServerStatus arclight$initTickParam(MinecraftServer instance, @Local(allocate = "tickSection") long tickSection, @Local(allocate = "tickCount") long tickCount) throws Throwable { + var serverStatus = (ServerStatus) DecorationOps.callsite().invoke(instance); + Arrays.fill(recentTps, 20); + tickSection = Util.getMillis(); + tickCount = 1; + DecorationOps.blackhole().invoke(tickSection, tickCount); + return serverStatus; + } + + @Decorate(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;startMetricsRecordingTick()V")) + private void arclight$updateTickParam(MinecraftServer instance, @Local(allocate = "tickSection") long tickSection, @Local(allocate = "tickCount") long tickCount) throws Throwable { + if (tickCount++ % SAMPLE_INTERVAL == 0) { + long curTime = Util.getMillis(); + double currentTps = 1E3 / (curTime - tickSection) * SAMPLE_INTERVAL; + recentTps[0] = calcTps(recentTps[0], 0.92, currentTps); // 1/exp(5sec/1min) + recentTps[1] = calcTps(recentTps[1], 0.9835, currentTps); // 1/exp(5sec/5min) + recentTps[2] = calcTps(recentTps[2], 0.9945, currentTps); // 1/exp(5sec/15min) + tickSection = curTime; + } + DecorationOps.blackhole().invoke(tickSection, tickCount); + currentTick = (int) (System.currentTimeMillis() / 50); + DecorationOps.callsite().invoke(instance); + } - this.bridge$forge$expectServerStopped(); // Forge: Has to come before MinecraftServer#onServerCrash to avoid race conditions - this.onServerCrash(crashreport); - } finally { - try { - this.stopped = true; - this.stopServer(); - } catch (Throwable throwable) { - LOGGER.error("Exception stopping the server", throwable); - } finally { - if (this.services.profileCache() != null) { - this.services.profileCache().clearExecutor(); - } - WatchdogThread.doStop(); - this.bridge$platform$serverStopped(); - this.onServerExit(); - } + @Decorate(method = "runServer", at = @At(value = "INVOKE", remap = false, target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V")) + private void arclight$warnOnLoad(Logger instance, String s, Object o, Object o2) throws Throwable { + if (server.getWarnOnOverload()) { + DecorationOps.callsite().invoke(instance, s, o, o2); } } + @Inject(method = "runServer", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;onServerExit()V")) + private void arclight$watchdogExit(CallbackInfo ci) { + WatchdogThread.doStop(); + } + private static double calcTps(double avg, double exp, double tps) { return (avg * exp) + (tps * (1 - exp)); } @@ -391,9 +320,13 @@ public final void prepareLevels(ChunkProgressListener listener) { listener.updateSpawnPos(new ChunkPos(blockpos)); ServerChunkCache serverchunkprovider = serverworld.getChunkSource(); this.nextTickTimeNanos = Util.getNanos(); - serverchunkprovider.addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE); + serverworld.setDefaultSpawnPos(blockpos, serverworld.getSharedSpawnAngle()); + int i = serverworld.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); // CraftBukkit - per-world + int j = i > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(i)) : 0; - while (serverchunkprovider.getTickingGenerated() < 441) { + while (serverchunkprovider.getTickingGenerated() < j) { + // CraftBukkit start + // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; this.executeModerately(); } @@ -406,8 +339,8 @@ public final void prepareLevels(ChunkProgressListener listener) { LongIterator longiterator = forcedchunkssavedata.getChunks().iterator(); while (longiterator.hasNext()) { - long i = longiterator.nextLong(); - ChunkPos chunkpos = new ChunkPos(i); + long k = longiterator.nextLong(); + ChunkPos chunkpos = new ChunkPos(k); serverWorld.getChunkSource().updateChunkForced(chunkpos, true); } this.bridge$forge$reinstatePersistentChunks(serverWorld, forcedchunkssavedata); @@ -465,9 +398,13 @@ public void prepareLevels(ChunkProgressListener listener, ServerLevel serverWorl listener.updateSpawnPos(new ChunkPos(blockpos)); ServerChunkCache serverchunkprovider = serverWorld.getChunkSource(); this.nextTickTimeNanos = Util.getNanos(); - serverchunkprovider.addRegionTicket(TicketType.START, new ChunkPos(blockpos), 11, Unit.INSTANCE); + serverWorld.setDefaultSpawnPos(blockpos, serverWorld.getSharedSpawnAngle()); + int i = serverWorld.getGameRules().getInt(GameRules.RULE_SPAWN_CHUNK_RADIUS); // CraftBukkit - per-world + int j = i > 0 ? Mth.square(ChunkProgressListener.calculateDiameter(i)) : 0; - while (serverchunkprovider.getTickingGenerated() < 441) { + while (serverchunkprovider.getTickingGenerated() < j) { + // CraftBukkit start + // this.nextTickTimeNanos = SystemUtils.getNanos() + MinecraftServer.PREPARE_LEVELS_DEFAULT_DELAY_NANOS; this.executeModerately(); } @@ -478,8 +415,8 @@ public void prepareLevels(ChunkProgressListener listener, ServerLevel serverWorl LongIterator longiterator = forcedchunkssavedata.getChunks().iterator(); while (longiterator.hasNext()) { - long i = longiterator.nextLong(); - ChunkPos chunkpos = new ChunkPos(i); + long k = longiterator.nextLong(); + ChunkPos chunkpos = new ChunkPos(k); serverWorld.getChunkSource().updateChunkForced(chunkpos, true); } this.bridge$forge$reinstatePersistentChunks(serverWorld, forcedchunkssavedata); @@ -523,7 +460,7 @@ public void removeLevel(ServerLevel level) { cir.setReturnValue(!this.levels.isEmpty()); } - @Inject(method = "desc=/V$/", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/packs/repository/PackRepository;setSelected(Ljava/util/Collection;)V")) + @Inject(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/WorldData;setDataConfiguration(Lnet/minecraft/world/level/WorldDataConfiguration;)V")) private void arclight$syncCommand(CallbackInfo ci) { this.server.syncCommands(); } @@ -585,5 +522,11 @@ public boolean isDebugging() { private static MinecraftServer getServer() { return Bukkit.getServer() instanceof CraftServer ? ((CraftServer) Bukkit.getServer()).getServer() : null; } + + @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) + @Deprecated + private static RegistryAccess getDefaultRegistryAccess() { + return CraftRegistry.getMinecraftRegistry(); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/PlayerAdvancementsMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/PlayerAdvancementsMixin.java index 784eb9aad..b3a2d8ac0 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/PlayerAdvancementsMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/PlayerAdvancementsMixin.java @@ -21,6 +21,6 @@ public class PlayerAdvancementsMixin { @Inject(method = "award", at = @At(value = "INVOKE", target = "Lnet/minecraft/advancements/AdvancementRewards;grant(Lnet/minecraft/server/level/ServerPlayer;)V")) public void arclight$callEvent(AdvancementHolder advancementHolder, String criterionKey, CallbackInfoReturnable cir) { - Bukkit.getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent((Player) ((EntityBridge) this.player).bridge$getBukkitEntity(), ((AdvancementBridge) (Object) advancementHolder).bridge$getBukkit())); + Bukkit.getPluginManager().callEvent(new org.bukkit.event.player.PlayerAdvancementDoneEvent((Player) this.player.bridge$getBukkitEntity(), ((AdvancementBridge) (Object) advancementHolder).bridge$getBukkit())); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/ServerAdvancementManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/ServerAdvancementManagerMixin.java new file mode 100644 index 000000000..745cd7bb9 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/ServerAdvancementManagerMixin.java @@ -0,0 +1,28 @@ +package io.izzel.arclight.common.mixin.core.server; + +import com.google.gson.JsonElement; +import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.ServerAdvancementManager; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.HashMap; +import java.util.Map; + +@Mixin(ServerAdvancementManager.class) +public class ServerAdvancementManagerMixin { + + @Shadow public Map advancements; + + @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At(value = "FIELD", shift = At.Shift.AFTER, opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/server/ServerAdvancementManager;advancements:Ljava/util/Map;")) + private void arclight$buildMutable(Map map, ResourceManager resourceManager, ProfilerFiller profilerFiller, CallbackInfo ci) { + this.advancements = new HashMap<>(this.advancements); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkHolderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkHolderMixin.java index eac14bd7d..19dd23ee2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkHolderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkHolderMixin.java @@ -1,6 +1,5 @@ package io.izzel.arclight.common.mixin.core.server.level; -import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.core.world.chunk.ChunkBridge; import io.izzel.arclight.common.bridge.core.world.server.ChunkHolderBridge; import io.izzel.arclight.common.bridge.core.world.server.ChunkMapBridge; @@ -10,12 +9,13 @@ import net.minecraft.server.level.ChunkHolder; import net.minecraft.server.level.ChunkLevel; import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ChunkResult; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.GenerationChunkHolder; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.LevelHeightAccessor; -import net.minecraft.world.level.chunk.ChunkAccess; -import net.minecraft.world.level.chunk.ChunkStatus; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.status.ChunkStatus; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -29,29 +29,27 @@ import java.util.concurrent.Executor; @Mixin(ChunkHolder.class) -public abstract class ChunkHolderMixin implements ChunkHolderBridge { +public abstract class ChunkHolderMixin extends GenerationChunkHolder implements ChunkHolderBridge { // @formatter:off @Shadow public int oldTicketLevel; - @Shadow public abstract CompletableFuture> getFutureIfPresentUnchecked(ChunkStatus p_219301_1_); - @Shadow @Final ChunkPos pos; @Shadow @Final private ShortSet[] changedBlocksPerSection; @Shadow @Final private LevelHeightAccessor levelHeightAccessor; @Shadow private int ticketLevel; - @Override @Accessor("oldTicketLevel") public abstract int bridge$getOldTicketLevel(); + @Shadow public abstract CompletableFuture> getFullChunkFuture();@Override @Accessor("oldTicketLevel") public abstract int bridge$getOldTicketLevel(); // @formatter:on + public ChunkHolderMixin(ChunkPos chunkPos) { + super(chunkPos); + } + public LevelChunk getFullChunkNow() { - if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) { - return null; // note: using oldTicketLevel for isLoaded checks - } + if (!ChunkLevel.fullStatus(this.oldTicketLevel).isOrAfter(FullChunkStatus.FULL)) return null; return this.getFullChunkNowUnchecked(); } public LevelChunk getFullChunkNowUnchecked() { - CompletableFuture> statusFuture = this.getFutureIfPresentUnchecked(ChunkStatus.FULL); - Either either = statusFuture.getNow(null); - return (either == null) ? null : (LevelChunk) either.left().orElse(null); + return (LevelChunk) this.getChunkIfPresentUnchecked(ChunkStatus.FULL); } @Override @@ -78,8 +76,8 @@ public LevelChunk getFullChunkNowUnchecked() { FullChunkStatus fullChunkStatus = ChunkLevel.fullStatus(this.oldTicketLevel); FullChunkStatus fullChunkStatus2 = ChunkLevel.fullStatus(this.ticketLevel); if (fullChunkStatus.isOrAfter(FullChunkStatus.FULL) && !fullChunkStatus2.isOrAfter(FullChunkStatus.FULL)) { - this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { - LevelChunk chunk = (LevelChunk) either.left().orElse(null); + this.getFullChunkFuture().thenAccept((either) -> { + LevelChunk chunk = either.orElse(null); if (chunk != null) { ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> { chunk.setUnsaved(true); @@ -103,8 +101,8 @@ public LevelChunk getFullChunkNowUnchecked() { FullChunkStatus fullChunkStatus2 = ChunkLevel.fullStatus(this.ticketLevel); this.oldTicketLevel = this.ticketLevel; if (!fullChunkStatus.isOrAfter(FullChunkStatus.FULL) && fullChunkStatus2.isOrAfter(FullChunkStatus.FULL)) { - this.getFutureIfPresentUnchecked(ChunkStatus.FULL).thenAccept((either) -> { - LevelChunk chunk = (LevelChunk) either.left().orElse(null); + this.getFullChunkFuture().thenAccept((either) -> { + LevelChunk chunk = either.orElse(null); if (chunk != null) { ((ChunkMapBridge) chunkManager).bridge$getCallbackExecutor().execute( ((ChunkBridge) chunk)::bridge$loadCallback diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkMapMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkMapMixin.java index 4dd678fc0..dfea80a45 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkMapMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ChunkMapMixin.java @@ -43,7 +43,6 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { @Shadow @Nullable protected abstract ChunkHolder getUpdatingChunkIfPresent(long chunkPosIn); @Shadow protected abstract Iterable getChunks(); @Shadow protected abstract void tick(); - @Shadow @Mutable public ChunkGenerator generator; @Shadow @Final public ServerLevel level; @Shadow @Final @Mutable private RandomState randomState; @Invoker("tick") public abstract void bridge$tick(BooleanSupplier hasMoreTime); @@ -51,8 +50,8 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { // @formatter:on @Inject(method = "", at = @At("RETURN")) - private void arclight$updateRandom(ServerLevel p_214836_, LevelStorageSource.LevelStorageAccess p_214837_, DataFixer p_214838_, StructureTemplateManager p_214839_, Executor p_214840_, BlockableEventLoop p_214841_, LightChunkGetter p_214842_, ChunkGenerator p_214843_, ChunkProgressListener p_214844_, ChunkStatusUpdateListener p_214845_, Supplier p_214846_, int p_214847_, boolean p_214848_, CallbackInfo ci) { - this.bridge$setChunkGenerator(this.generator); + private void arclight$updateRandom(ServerLevel p_214836_, LevelStorageSource.LevelStorageAccess p_214837_, DataFixer p_214838_, StructureTemplateManager p_214839_, Executor p_214840_, BlockableEventLoop p_214841_, LightChunkGetter p_214842_, ChunkGenerator chunkGenerator, ChunkProgressListener p_214844_, ChunkStatusUpdateListener p_214845_, Supplier p_214846_, int p_214847_, boolean p_214848_, CallbackInfo ci) { + this.bridge$setChunkGenerator(chunkGenerator); } @Redirect(method = "upgradeChunkTag", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;dimension()Lnet/minecraft/resources/ResourceKey;")) @@ -84,7 +83,6 @@ public abstract class ChunkMapMixin implements ChunkMapBridge { @Override public void bridge$setChunkGenerator(ChunkGenerator generator) { - this.generator = generator; if (generator instanceof CustomChunkGenerator custom) { generator = custom.getDelegate(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/DistanceManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/DistanceManagerMixin.java index 05b14b355..980bf449a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/DistanceManagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/DistanceManagerMixin.java @@ -42,26 +42,6 @@ public abstract class DistanceManagerMixin implements TicketManagerBridge { } } - @Redirect(method = "runAllUpdates", require = 0, at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Set;forEach(Ljava/util/function/Consumer;)V")) - private void arclight$safeIter(Set instance, Consumer consumer) { - // Iterate pending chunk updates with protection against concurrent modification exceptions - var iter = instance.iterator(); - var expectedSize = instance.size(); - do { - var chunkHolder = iter.next(); - iter.remove(); - expectedSize--; - - consumer.accept(chunkHolder); - - // Reset iterator if set was modified using add() - if (instance.size() != expectedSize) { - expectedSize = instance.size(); - iter = instance.iterator(); - } - } while (iter.hasNext()); - } - public boolean addRegionTicketAtDistance(TicketType type, ChunkPos pos, int level, T value) { var ticket = new Ticket<>(type, 33 - level, value); var ret = this.addTicket(pos.toLong(), ticket); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerEntityMixin.java index ed40c0a32..735959420 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerEntityMixin.java @@ -5,8 +5,11 @@ import io.izzel.arclight.common.mod.ArclightConstants; import io.izzel.arclight.common.mod.mixins.annotation.CreateConstructor; import io.izzel.arclight.common.mod.mixins.annotation.ShadowConstructor; +import net.minecraft.core.component.DataComponents; 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.ClientboundProjectilePowerPacket; import net.minecraft.network.protocol.game.ClientboundRotateHeadPacket; import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.network.protocol.game.ClientboundSetPassengersPacket; @@ -23,8 +26,10 @@ import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.MapItem; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; @@ -61,18 +66,18 @@ public abstract class ServerEntityMixin implements ServerEntityBridge { @Shadow @Final private ServerLevel level; @Shadow protected abstract void sendDirtyEntityData(); @Shadow @Final private int updateInterval; - @Shadow private int yRotp; - @Shadow private int xRotp; @Shadow @Final private VecDeltaCodec positionCodec; @Shadow private boolean wasRiding; @Shadow private int teleportDelay; @Shadow private boolean wasOnGround; @Shadow @Final private boolean trackDelta; - @Shadow private Vec3 ap; - @Shadow private int yHeadRotp; @Shadow protected abstract void broadcastAndSend(Packet packet); @Shadow @Nullable private List> trackedDataValues; @Shadow private static Stream removedPassengers(List p_277592_, List p_277658_) { return null; } + @Shadow private int lastSentYRot; + @Shadow private int lastSentXRot; + @Shadow private Vec3 lastSentMovement; + @Shadow private int lastSentYHeadRot; // @formatter:on private Set trackedPlayers; @@ -126,12 +131,13 @@ public void sendChanges() { if (this.entity instanceof ItemFrame itemFrame) { ItemStack itemstack = itemFrame.getItem(); if (this.tickCount / 10 != this.lastMapUpdate && itemstack.getItem() instanceof MapItem) { - MapItemSavedData mapdata = MapItem.getSavedData(itemstack, this.level); + MapId mapId = itemstack.get(DataComponents.MAP_ID); + MapItemSavedData mapdata = MapItem.getSavedData(mapId, this.level); if (mapdata != null) { for (ServerPlayerConnection connection : this.trackedPlayers) { var serverplayerentity = connection.getPlayer(); mapdata.tickCarriedBy(serverplayerentity, itemstack); - Packet ipacket = ((MapItem) itemstack.getItem()).getUpdatePacket(itemstack, this.level, serverplayerentity); + Packet ipacket = mapdata.getUpdatePacket(mapId, serverplayerentity); if (ipacket != null) { serverplayerentity.connection.send(ipacket); } @@ -144,11 +150,11 @@ public void sendChanges() { if (this.entity.isPassenger()) { int i1 = Mth.floor(this.entity.getYRot() * 256.0F / 360.0F); int l1 = Mth.floor(this.entity.getXRot() * 256.0F / 360.0F); - boolean flag2 = Math.abs(i1 - this.yRotp) >= 1 || Math.abs(l1 - this.xRotp) >= 1; + boolean flag2 = Math.abs(i1 - this.lastSentYRot) >= 1 || Math.abs(l1 - this.lastSentXRot) >= 1; if (flag2) { this.broadcast.accept(new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) i1, (byte) l1, this.entity.onGround())); - this.yRotp = i1; - this.xRotp = l1; + this.lastSentYRot = i1; + this.lastSentXRot = l1; } this.positionCodec.setBase(this.entity.trackingPosition()); this.sendDirtyEntityData(); @@ -161,40 +167,42 @@ public void sendChanges() { boolean flag3 = this.positionCodec.delta(vector3d).lengthSqr() >= 7.62939453125E-6D; Packet ipacket1 = null; boolean flag4 = flag3 || this.tickCount / 60 != this.lastPosUpdate; - boolean flag = Math.abs(l - this.yRotp) >= 1 || Math.abs(k1 - this.xRotp) >= 1; + boolean flag = Math.abs(l - this.lastSentYRot) >= 1 || Math.abs(k1 - this.lastSentXRot) >= 1; boolean pos = false; boolean rot = false; - if (this.tickCount > 0 || this.entity instanceof AbstractArrow) { - long i = this.positionCodec.encodeX(vector3d); - long j = this.positionCodec.encodeY(vector3d); - long k = this.positionCodec.encodeZ(vector3d); - boolean flag1 = i < -32768L || i > 32767L || j < -32768L || j > 32767L || k < -32768L || k > 32767L; - if (!flag1 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { - if ((!flag4 || !flag) && !(this.entity instanceof AbstractArrow)) { - if (flag4) { - ipacket1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) i), (short) ((int) j), (short) ((int) k), this.entity.onGround()); - pos = true; - } else if (flag) { - ipacket1 = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) l, (byte) k1, this.entity.onGround()); - rot = true; - } - } else { - ipacket1 = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short) ((int) i), (short) ((int) j), (short) ((int) k), (byte) l, (byte) k1, this.entity.onGround()); - pos = rot = true; + long i = this.positionCodec.encodeX(vector3d); + long j = this.positionCodec.encodeY(vector3d); + long k = this.positionCodec.encodeZ(vector3d); + boolean flag1 = i < -32768L || i > 32767L || j < -32768L || j > 32767L || k < -32768L || k > 32767L; + if (!flag1 && this.teleportDelay <= 400 && !this.wasRiding && this.wasOnGround == this.entity.onGround()) { + if ((!flag4 || !flag) && !(this.entity instanceof AbstractArrow)) { + if (flag4) { + ipacket1 = new ClientboundMoveEntityPacket.Pos(this.entity.getId(), (short) ((int) i), (short) ((int) j), (short) ((int) k), this.entity.onGround()); + pos = true; + } else if (flag) { + ipacket1 = new ClientboundMoveEntityPacket.Rot(this.entity.getId(), (byte) l, (byte) k1, this.entity.onGround()); + rot = true; } } else { - this.wasOnGround = this.entity.onGround(); - this.teleportDelay = 0; - ipacket1 = new ClientboundTeleportEntityPacket(this.entity); + ipacket1 = new ClientboundMoveEntityPacket.PosRot(this.entity.getId(), (short) ((int) i), (short) ((int) j), (short) ((int) k), (byte) l, (byte) k1, this.entity.onGround()); pos = rot = true; } + } else { + this.wasOnGround = this.entity.onGround(); + this.teleportDelay = 0; + ipacket1 = new ClientboundTeleportEntityPacket(this.entity); + pos = rot = true; } if ((this.trackDelta || this.entity.hasImpulse || this.entity instanceof LivingEntity && ((LivingEntity) this.entity).isFallFlying()) && this.tickCount > 0) { Vec3 vector3d1 = this.entity.getDeltaMovement(); - double d0 = vector3d1.distanceToSqr(this.ap); + double d0 = vector3d1.distanceToSqr(this.lastSentMovement); if (d0 > 1.0E-7D || d0 > 0.0D && vector3d1.lengthSqr() == 0.0D) { - this.ap = vector3d1; - this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.ap)); + this.lastSentMovement = vector3d1; + if ( this.entity instanceof AbstractHurtingProjectile entityfireball) { + this.broadcast.accept(new ClientboundBundlePacket(List.of(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement), new ClientboundProjectilePowerPacket(entityfireball.getId(), entityfireball.accelerationPower)))); + } else { + this.broadcast.accept(new ClientboundSetEntityMotionPacket(this.entity.getId(), this.lastSentMovement)); + } } } if (ipacket1 != null) { @@ -205,15 +213,15 @@ public void sendChanges() { this.positionCodec.setBase(vector3d); } if (rot) { - this.yRotp = l; - this.xRotp = k1; + this.lastSentYRot = l; + this.lastSentXRot = k1; } this.wasRiding = false; } int j1 = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F); - if (Math.abs(j1 - this.yHeadRotp) >= 1) { + if (Math.abs(j1 - this.lastSentYHeadRot) >= 1) { this.broadcast.accept(new ClientboundRotateHeadPacket(this.entity, (byte) j1)); - this.yHeadRotp = j1; + this.lastSentYHeadRot = j1; } this.entity.hasImpulse = false; } @@ -234,10 +242,11 @@ public void sendChanges() { player.setVelocity(event.getVelocity()); } } - if (!cancelled) { - this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); + if (cancelled) { + return; } this.entity.hurtMarked = false; + this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity)); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java index 61699cce4..28563f646 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerLevelMixin.java @@ -5,7 +5,6 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.core.world.ExplosionBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.bridge.core.world.server.ServerChunkProviderBridge; import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.bridge.core.world.storage.DerivedWorldInfoBridge; @@ -22,7 +21,11 @@ import io.izzel.arclight.common.mod.util.DelegateWorldInfo; import io.izzel.arclight.common.mod.util.DistValidate; import io.izzel.arclight.i18n.ArclightConfig; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; @@ -34,26 +37,23 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.progress.ChunkProgressListener; -import net.minecraft.sounds.SoundEvent; import net.minecraft.util.ProgressListener; import net.minecraft.world.Container; import net.minecraft.world.RandomSequences; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.level.CustomSpawner; import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.level.storage.DerivedLevelData; import net.minecraft.world.level.storage.DimensionDataStorage; @@ -63,11 +63,9 @@ import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator; -import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; import org.bukkit.craftbukkit.v.util.CraftNamespacedKey; import org.bukkit.craftbukkit.v.util.WorldUUID; import org.bukkit.entity.HumanEntity; @@ -76,14 +74,12 @@ import org.bukkit.event.server.MapInitializeEvent; import org.bukkit.event.weather.LightningStrikeEvent; import org.bukkit.event.world.GenericGameEvent; -import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.event.world.TimeSkipEvent; import org.bukkit.event.world.WorldSaveEvent; import org.objectweb.asm.Opcodes; import org.spigotmc.SpigotWorldConfig; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -91,7 +87,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nonnull; import java.util.List; @@ -115,6 +110,7 @@ public abstract class ServerLevelMixin extends LevelMixin implements ServerWorld @Shadow @Final public ServerLevelData serverLevelData; @Shadow @Final private PersistentEntitySectionManager entityManager; @Shadow public abstract DimensionDataStorage getDataStorage(); + @Shadow protected abstract void addPlayer(ServerPlayer serverPlayer); // @formatter:on @SuppressWarnings({"FieldCanBeLocal", "unused"}) @@ -188,10 +184,10 @@ public ResourceKey getTypeKey() { } @Inject(method = "gameEvent", cancellable = true, at = @At("HEAD")) - private void arclight$gameEventEvent(GameEvent gameEvent, Vec3 pos, GameEvent.Context context, CallbackInfo ci) { + private void arclight$gameEventEvent(Holder holder, Vec3 pos, GameEvent.Context context, CallbackInfo ci) { var entity = context.sourceEntity(); - var i = gameEvent.getNotificationRadius(); - GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(gameEvent))), new Location(this.getWorld(), pos.x(), pos.y(), pos.z()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread()); + var i = holder.value().notificationRadius(); + GenericGameEvent event = new GenericGameEvent(org.bukkit.GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(holder.value()))), new Location(this.getWorld(), pos.x(), pos.y(), pos.z()), (entity == null) ? null : entity.bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread()); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { ci.cancel(); @@ -274,7 +270,7 @@ public boolean strikeLightning(Entity entity, LightningStrikeEvent.Cause cause) private void arclight$saveLevelDat(ProgressListener progress, boolean flush, boolean skipSave, CallbackInfo ci) { if (this.serverLevelData instanceof PrimaryLevelData worldInfo) { worldInfo.setWorldBorder(this.getWorldBorder().createSettings()); - worldInfo.setCustomBossEvents(this.getServer().getCustomBossEvents().save()); + worldInfo.setCustomBossEvents(this.getServer().getCustomBossEvents().save(this.registryAccess())); this.convertable.saveDataTag(this.getServer().registryAccess(), worldInfo, this.getServer().getPlayerList().getSingleplayerData()); } } @@ -363,7 +359,11 @@ public boolean addWithUUID(Entity entity, CreatureSpawnEvent.SpawnReason reason) } public void addDuringTeleport(Entity entity, CreatureSpawnEvent.SpawnReason reason) { - addFreshEntity(entity, reason); + if (entity instanceof ServerPlayer player) { + this.addPlayer(player); + } else { + this.addFreshEntity(entity, reason); + } } @Override @@ -383,17 +383,17 @@ public boolean tryAddFreshEntityWithPassengers(Entity entity, CreatureSpawnEvent return tryAddFreshEntityWithPassengers(entity, reason); } - @Inject(method = "explode", cancellable = true, at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/Explosion;interactsWithBlocks()Z"), locals = LocalCapture.CAPTURE_FAILHARD) - private void arclight$doExplosion(Entity p_256039_, DamageSource p_255778_, ExplosionDamageCalculator p_256002_, double p_256067_, double p_256370_, double p_256153_, float p_256045_, boolean p_255686_, Level.ExplosionInteraction p_255827_, ParticleOptions p_310962_, ParticleOptions p_310322_, SoundEvent p_309795_, - CallbackInfoReturnable cir, Explosion explosion) { + @Decorate(method = "explode", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Explosion;interactsWithBlocks()Z")) + private void arclight$doExplosion(@Local(ordinal = -1) Explosion explosion) throws Throwable { if (((ExplosionBridge) explosion).bridge$wasCancelled()) { - cir.setReturnValue(explosion); + DecorationOps.cancel().invoke(explosion); + return; } + DecorationOps.blackhole().invoke(); } @Inject(method = "getMapData", at = @At("RETURN")) - private void arclight$mapSetId(String id, CallbackInfoReturnable cir) { + private void arclight$mapSetId(MapId id, CallbackInfoReturnable cir) { var data = cir.getReturnValue(); if (data != null) { ((MapDataBridge) data).bridge$setId(id); @@ -401,7 +401,7 @@ public boolean tryAddFreshEntityWithPassengers(Entity entity, CreatureSpawnEvent } @Inject(method = "setMapData", at = @At("HEAD")) - private void arclight$mapSetId(String id, MapItemSavedData data, CallbackInfo ci) { + private void arclight$mapSetId(MapId id, MapItemSavedData data, CallbackInfo ci) { ((MapDataBridge) data).bridge$setId(id); MapInitializeEvent event = new MapInitializeEvent(((MapDataBridge) data).bridge$getMapView()); Bukkit.getServer().getPluginManager().callEvent(event); @@ -444,40 +444,6 @@ public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { return (ServerLevel) (Object) this; } - /** - * @author IzzelAliz - * @reason - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - @Overwrite - public static void makeObsidianPlatform(ServerLevel world) { - BlockPos blockpos = END_SPAWN_POINT; - int i = blockpos.getX(); - int j = blockpos.getY() - 2; - int k = blockpos.getZ(); - BlockStateListPopulator blockList = new BlockStateListPopulator(world); - BlockPos.betweenClosed(i - 2, j + 1, k - 2, i + 2, j + 3, k + 2).forEach((pos) -> { - blockList.setBlock(pos, Blocks.AIR.defaultBlockState(), 3); - }); - BlockPos.betweenClosed(i - 2, j, k - 2, i + 2, j, k + 2).forEach((pos) -> { - blockList.setBlock(pos, Blocks.OBSIDIAN.defaultBlockState(), 3); - }); - if (!DistValidate.isValid(world)) { - blockList.updateList(); - ArclightCaptures.getEndPortalEntity(); - return; - } - CraftWorld bworld = ((WorldBridge) world).bridge$getWorld(); - boolean spawnPortal = ArclightCaptures.getEndPortalSpawn(); - Entity entity = ArclightCaptures.getEndPortalEntity(); - PortalCreateEvent portalEvent = new PortalCreateEvent((List) blockList.getList(), bworld, entity == null ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM); - portalEvent.setCancelled(!spawnPortal); - Bukkit.getPluginManager().callEvent(portalEvent); - if (!portalEvent.isCancelled()) { - blockList.updateList(); - } - } - @ModifyVariable(method = "tickBlock", ordinal = 0, argsOnly = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;tick(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/util/RandomSource;)V")) private BlockPos arclight$captureTickingBlock(BlockPos pos) { ArclightCaptures.captureTickingBlock((ServerLevel) (Object) this, pos); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayerMixin.java similarity index 69% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java rename to arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayerMixin.java index 44bf55efd..ed3b859b2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayerMixin.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.world.entity.player; +package io.izzel.arclight.common.mixin.core.server.level; import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; @@ -7,27 +7,23 @@ import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; -import io.izzel.arclight.common.bridge.core.world.TeleporterBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; +import io.izzel.arclight.common.bridge.core.world.damagesource.CombatTrackerBridge; +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; +import io.izzel.arclight.common.mixin.core.world.entity.player.PlayerMixin; import io.izzel.arclight.common.mod.mixins.annotation.RenameInto; import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.server.block.ChestBlockDoubleInventoryHacks; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.BlockUtil; -import net.minecraft.ChatFormatting; +import io.izzel.arclight.common.mod.util.Blackhole; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.core.GlobalPos; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.PacketSendListener; -import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.protocol.game.ClientboundGameEventPacket; -import net.minecraft.network.protocol.game.ClientboundHorseScreenOpenPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerCombatKillPacket; import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; import net.minecraft.resources.ResourceKey; @@ -39,7 +35,6 @@ import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.stats.Stat; -import net.minecraft.stats.Stats; import net.minecraft.util.Mth; import net.minecraft.util.Unit; import net.minecraft.world.Container; @@ -48,7 +43,6 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.HumanoidArm; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.entity.animal.horse.AbstractHorse; import net.minecraft.world.entity.item.ItemEntity; @@ -57,22 +51,18 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodData; import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerSynchronizer; import net.minecraft.world.inventory.HorseInventoryMenu; +import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.NetherPortalBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.portal.PortalInfo; +import net.minecraft.world.level.portal.DimensionTransition; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.ScoreAccess; import net.minecraft.world.scores.ScoreHolder; import net.minecraft.world.scores.Scoreboard; -import net.minecraft.world.scores.Team; import net.minecraft.world.scores.criteria.ObjectiveCriteria; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -86,30 +76,31 @@ import org.bukkit.craftbukkit.v.event.CraftPortalEvent; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.craftbukkit.v.scoreboard.CraftScoreboardManager; -import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; import org.bukkit.craftbukkit.v.util.CraftChatMessage; +import org.bukkit.craftbukkit.v.util.CraftLocation; import org.bukkit.event.entity.EntityExhaustionEvent; import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerBedLeaveEvent; import org.bukkit.event.player.PlayerChangedMainHandEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerLocaleChangeEvent; import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerSpawnChangeEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerToggleSneakEvent; -import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.inventory.MainHand; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; import java.util.ArrayList; @@ -150,7 +141,6 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla @Shadow @Nullable public abstract BlockPos getRespawnPosition(); @Shadow public abstract float getRespawnAngle(); @Shadow protected abstract void tellNeutralMobsThatIDied(); - @Shadow protected abstract void createEndPlatform(ServerLevel p_242110_1_, BlockPos p_242110_2_); @Shadow public abstract boolean isCreative(); @Shadow protected abstract boolean bedBlocked(BlockPos p_241156_1_, Direction p_241156_2_); @Shadow protected abstract boolean bedInRange(BlockPos p_241147_1_, Direction p_241147_2_); @@ -164,8 +154,14 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla @Shadow private boolean respawnForced; @Shadow public abstract void setServerLevel(ServerLevel p_284971_); @Shadow public abstract CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel p_301182_); + @Shadow public abstract boolean isRespawnForced(); + @Shadow public abstract ResourceKey getRespawnDimension(); + @Shadow public static Optional findRespawnAndUseSpawnBlock(ServerLevel serverLevel, BlockPos blockPos, float f, boolean bl, boolean bl2) { return Optional.empty(); } + @Shadow @Final private ContainerSynchronizer containerSynchronizer; + @Shadow public abstract void setRespawnPosition(ResourceKey arg, @org.jetbrains.annotations.Nullable BlockPos arg2, float f, boolean bl, boolean bl2); // @formatter:on + public CraftPlayer.TransferCookieConnection transferCookieConnection; public String displayName; public Component listName; public org.bukkit.Location compassTarget; @@ -192,6 +188,28 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla this.arclight$initialized = true; } + @Override + public void bridge$setTransferCookieConnection(CraftPlayer.TransferCookieConnection transferCookieConnection) { + this.transferCookieConnection = transferCookieConnection; + } + + @Override + public CraftPlayer.TransferCookieConnection bridge$getTransferCookieConnection() { + return this.transferCookieConnection; + } + + public void resendItemInHands() { + containerMenu.findSlot(getInventory(), getInventory().selected).ifPresent(s -> { + containerSynchronizer.sendSlotChange(containerMenu, s, getMainHandItem()); + }); + containerSynchronizer.sendSlotChange(inventoryMenu, InventoryMenu.SHIELD_SLOT, getOffhandItem()); + } + + @Override + public void bridge$resendItemInHands() { + this.resendItemInHands(); + } + @Override public boolean bridge$initialized() { return this.arclight$initialized; @@ -267,7 +285,7 @@ public void spawnIn(Level world) { this.bridge$revive(); Vec3 position = null; if (this.respawnDimension != null && (world = ArclightServer.getMinecraftServer().getLevel(this.respawnDimension)) != null && this.getRespawnPosition() != null) { - position = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).orElse(null); + position = ServerPlayer.findRespawnAndUseSpawnBlock((ServerLevel) world, this.getRespawnPosition(), this.getRespawnAngle(), false, false).map(ServerPlayer.RespawnPosAngle::position).orElse(null); } if (world == null || position == null) { world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle(); @@ -319,19 +337,16 @@ public void spawnIn(Level world) { } @Override - public void bridge$common$finishCaptureAndFireEvent() { + public void bridge$common$finishCaptureAndFireEvent(DamageSource damageSource) { } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void die(DamageSource damagesource) { - this.gameEvent(GameEvent.ENTITY_DIE); - boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); + @Decorate(method = "die", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/GameRules;getBoolean(Lnet/minecraft/world/level/GameRules$Key;)Z"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/GameRules;RULE_SHOWDEATHMESSAGES:Lnet/minecraft/world/level/GameRules$Key;"))) + private boolean arclight$firePlayerDeath(GameRules instance, GameRules.Key key, DamageSource damagesource, + @Local(allocate = "keepInventory") boolean keepInv) throws Throwable { + var flag = (boolean) DecorationOps.callsite().invoke(instance, key); if (this.isRemoved()) { - return; + return (boolean) DecorationOps.cancel().invoke(); } boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator(); Inventory copyInv; @@ -341,7 +356,7 @@ public void die(DamageSource damagesource) { copyInv = new Inventory((ServerPlayer) (Object) this); copyInv.replaceWith(this.getInventory()); } - this.dropAllDeathLoot(damagesource); + this.dropAllDeathLoot(this.serverLevel(), damagesource); Component defaultMessage = this.getCombatTracker().getDeathMessage(); String deathmessage = defaultMessage.getString(); @@ -357,69 +372,36 @@ public void die(DamageSource damagesource) { if (!keepInventory) { this.getInventory().replaceWith(copyInv); } - PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent((ServerPlayer) (Object) this, loot, deathmessage, keepInventory); + PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent((ServerPlayer) (Object) this, damagesource, loot, deathmessage, keepInventory); if (this.containerMenu != this.inventoryMenu) { this.closeContainer(); } String deathMessage = event.getDeathMessage(); - if (deathMessage != null && deathMessage.length() > 0 && flag) { - Component itextcomponent; - if (deathMessage.equals(deathmessage)) { - itextcomponent = this.getCombatTracker().getDeathMessage(); - } else { - itextcomponent = CraftChatMessage.fromStringOrNull(deathMessage); - } - this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), itextcomponent), PacketSendListener.exceptionallySend(() -> { - String s = itextcomponent.getString(256); - Component component1 = Component.translatable("death.attack.message_too_long", Component.literal(s).withStyle(ChatFormatting.YELLOW)); - Component component2 = Component.translatable("death.attack.even_more_magic", this.getDisplayName()).withStyle((p_143420_) -> { - return p_143420_.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, component1)); - }); - return new ClientboundPlayerCombatKillPacket(this.getId(), component2); - })); - Team scoreboardteambase = this.getTeam(); - if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != Team.Visibility.ALWAYS) { - if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OTHER_TEAMS) { - this.server.getPlayerList().broadcastSystemToTeam((ServerPlayer) (Object) this, itextcomponent); - } else if (scoreboardteambase.getDeathMessageVisibility() == Team.Visibility.HIDE_FOR_OWN_TEAM) { - this.server.getPlayerList().broadcastSystemToAllExceptTeam((ServerPlayer) (Object) this, itextcomponent); - } - } else { - this.server.getPlayerList().broadcastSystemMessage(itextcomponent, false); + if (deathMessage != null && !deathMessage.isEmpty() && flag) { + if (!deathmessage.equals(deathMessage)) { + ((CombatTrackerBridge) this.getCombatTracker()).bridge$setDeathMessage(CraftChatMessage.fromStringOrNull(deathMessage)); } } else { - this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY)); - } - this.removeEntitiesOnShoulder(); - - if (this.level().getGameRules().getBoolean(GameRules.RULE_FORGIVE_DEAD_PLAYERS)) { - this.tellNeutralMobsThatIDied(); + flag = false; } + keepInv = event.getKeepInventory(); + DecorationOps.blackhole().invoke(keepInv); + return flag; + } - this.dropExperience(); - - if (!event.getKeepInventory()) { + @Decorate(method = "die", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isSpectator()Z")) + private boolean arclight$postDeathEvent(ServerPlayer instance, DamageSource damagesource, @Local(allocate = "keepInventory") boolean keepInv) throws Throwable { + this.dropExperience(damagesource.getEntity()); + if (!keepInv) { this.getInventory().clearContent(); } this.setCamera((ServerPlayer) (Object) this); - ((CraftScoreboardManager) Bukkit.getScoreboardManager()).forAllObjectives(ObjectiveCriteria.DEATH_COUNT, (ServerPlayer) (Object) this, ScoreAccess::increment); - - LivingEntity entityliving = this.getKillCredit(); - if (entityliving != null) { - this.awardStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); - entityliving.awardKillScore((ServerPlayer) (Object) this, this.deathScore, damagesource); - this.createWitherRose(entityliving); - } + return !Blackhole.actuallyFalse() || (boolean) DecorationOps.callsite().invoke(instance); + } - this.level().broadcastEntityEvent((ServerPlayer) (Object) this, (byte) 3); - this.awardStat(Stats.DEATHS); - this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_DEATH)); - this.resetStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)); - this.clearFire(); - this.setTicksFrozen(0); - this.setSharedFlagOnFire(false); - this.getCombatTracker().recheckStatus(); - this.setLastDeathLocation(Optional.of(GlobalPos.of(this.level().dimension(), this.blockPosition()))); + @Redirect(method = "die", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/scores/Scoreboard;forAllObjectives(Lnet/minecraft/world/scores/criteria/ObjectiveCriteria;Lnet/minecraft/world/scores/ScoreHolder;Ljava/util/function/Consumer;)V")) + private void arclight$usePluginScore(Scoreboard instance, ObjectiveCriteria objectiveCriteria, ScoreHolder scoreHolder, Consumer consumer) { + ((CraftScoreboardManager) Bukkit.getScoreboardManager()).forAllObjectives(objectiveCriteria, scoreHolder, consumer); } @Redirect(method = "awardKillScore", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/scores/Scoreboard;forAllObjectives(Lnet/minecraft/world/scores/criteria/ObjectiveCriteria;Lnet/minecraft/world/scores/ScoreHolder;Ljava/util/function/Consumer;)V")) @@ -437,30 +419,62 @@ public void die(DamageSource damagesource) { cir.setReturnValue(((WorldBridge) this.level()).bridge$isPvpMode()); } - /** - * @author IzzelAliz - * @reason - */ - @Nullable - @Overwrite - protected PortalInfo findDimensionEntryPoint(ServerLevel level) { - PortalInfo portalinfo = super.findDimensionEntryPoint(level); - level = portalinfo == null || ((PortalInfoBridge) portalinfo).bridge$getWorld() == null ? level : ((PortalInfoBridge) portalinfo).bridge$getWorld(); - if (portalinfo != null && ((WorldBridge) this.level()).bridge$getTypeKey() == LevelStem.OVERWORLD && ((WorldBridge) level).bridge$getTypeKey() == LevelStem.END) { - Vec3 vector3d = portalinfo.pos.add(0.0D, -1.0D, 0.0D); - PortalInfo newInfo = new PortalInfo(vector3d, Vec3.ZERO, 90.0F, 0.0F); - ((PortalInfoBridge) newInfo).bridge$setWorld(level); - ((PortalInfoBridge) newInfo).bridge$setPortalEventInfo(((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo()); - return newInfo; - } else { - return portalinfo; + @Unique private PlayerRespawnEvent.RespawnReason arclight$respawnReason; + + @Override + public void bridge$pushRespawnReason(PlayerRespawnEvent.RespawnReason respawnReason) { + arclight$respawnReason = respawnReason; + } + + @Decorate(method = "findRespawnPositionAndUseSpawnBlock", inject = true, at = @At("HEAD")) + private void arclight$initLocals(@Local(allocate = "isBedSpawn") boolean isBedSpawn, @Local(allocate = "isAnchorSpawn") boolean isAnchorSpawn) throws Throwable { + isBedSpawn = false; + isAnchorSpawn = false; + DecorationOps.blackhole().invoke(isBedSpawn, isAnchorSpawn); + } + + @SuppressWarnings("unchecked") + @Decorate(method = "findRespawnPositionAndUseSpawnBlock", at = @At(value = "INVOKE", target = "Ljava/util/Optional;get()Ljava/lang/Object;")) + private T arclight$setLocals(Optional instance, @Local(allocate = "isBedSpawn") boolean isBedSpawn, @Local(allocate = "isAnchorSpawn") boolean isAnchorSpawn) throws Throwable { + T value = (T) DecorationOps.callsite().invoke(instance); + ServerPlayer.RespawnPosAngle respawnPosAngle = (ServerPlayer.RespawnPosAngle) value; + isBedSpawn = ((RespawnPosAngleBridge) (Object) respawnPosAngle).bridge$isBedSpawn(); + isAnchorSpawn = ((RespawnPosAngleBridge) (Object) respawnPosAngle).bridge$isAnchorSpawn(); + DecorationOps.blackhole().invoke(isBedSpawn, isAnchorSpawn); + return value; + } + + @Decorate(method = "findRespawnPositionAndUseSpawnBlock", at = @At("RETURN")) + private void arclight$respawnEvent(DimensionTransition dimensionTransition, @Local(allocate = "isBedSpawn") boolean isBedSpawn, @Local(allocate = "isAnchorSpawn") boolean isAnchorSpawn) throws Throwable { + if (arclight$respawnReason != null) { + org.bukkit.entity.Player respawnPlayer = this.getBukkitEntity(); + Location location = CraftLocation.toBukkit(dimensionTransition.pos(), dimensionTransition.newLevel().bridge$getWorld(), dimensionTransition.yRot(), dimensionTransition.xRot()); + + PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn, isAnchorSpawn, arclight$respawnReason); + Bukkit.getPluginManager().callEvent(respawnEvent); + if (((ServerPlayNetHandlerBridge) this.connection).bridge$isDisconnected()) { + DecorationOps.cancel().invoke((DimensionTransition) null); + return; + } + location = respawnEvent.getRespawnLocation(); + var cause = ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$getTeleportCause(); + dimensionTransition = new DimensionTransition(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toVec3D(location), dimensionTransition.speed(), location.getYaw(), location.getPitch(), dimensionTransition.missingRespawnBlock(), dimensionTransition.postDimensionTransition()); + ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$setTeleportCause(cause); + arclight$respawnReason = null; } + DecorationOps.callsite().invoke(dimensionTransition); } - @Override - public Entity bridge$changeDimension(ServerLevel world, PlayerTeleportEvent.TeleportCause cause) { - this.arclight$cause = cause; - return changeDimension(world); + @Inject(method = "findRespawnAndUseSpawnBlock", at = @At(value = "RETURN", ordinal = 0), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/BedBlock;findStandUpPosition(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/CollisionGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;F)Ljava/util/Optional;"))) + private static void arclight$setBedSpawn(ServerLevel serverLevel, BlockPos blockPos, float f, boolean bl, boolean bl2, CallbackInfoReturnable> cir) { + cir.getReturnValue().ifPresent(respawnPosAngle -> ((RespawnPosAngleBridge) (Object) respawnPosAngle).bridge$setBedSpawn(true)); + } + + @Inject(method = "findRespawnAndUseSpawnBlock", at = @At(value = "RETURN", ordinal = 0), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/RespawnAnchorBlock;findStandUpPosition(Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/CollisionGetter;Lnet/minecraft/core/BlockPos;)Ljava/util/Optional;"))) + private static void arclight$setAnchorSpawn(ServerLevel serverLevel, BlockPos blockPos, float f, boolean bl, boolean bl2, CallbackInfoReturnable> cir) { + cir.getReturnValue().ifPresent(respawnPosAngle -> ((RespawnPosAngleBridge) (Object) respawnPosAngle).bridge$setAnchorSpawn(true)); } private transient PlayerTeleportEvent.TeleportCause arclight$cause; @@ -478,9 +492,8 @@ public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double } @Override - protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { + public CraftPortalEvent callPortalEvent(Entity entity, Location exit, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { Location enter = this.getBukkitEntity().getLocation(); - Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.x(), exitPosition.y(), exitPosition.z(), this.getYRot(), this.getXRot()); PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause, 128, true, creationRadius); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null) { @@ -489,41 +502,35 @@ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldS return new CraftPortalEvent(event); } - @Override - protected Optional getExitPortal(ServerLevel worldserver, BlockPos blockposition, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { - Optional optional = super.getExitPortal(worldserver, blockposition, flag, worldborder, searchRadius, canCreatePortal, createRadius); - if (optional.isPresent() || !canCreatePortal) { - return optional; - } - Direction.Axis enumdirection_enumaxis = this.level().getBlockState(this.portalEntrancePos).getOptionalValue(NetherPortalBlock.AXIS).orElse(Direction.Axis.X); - Optional optional1 = ((TeleporterBridge) worldserver.getPortalForcer()).bridge$createPortal(blockposition, enumdirection_enumaxis, (ServerPlayer) (Object) this, createRadius); - if (!optional1.isPresent()) { - // LOGGER.error("Unable to create a portal, likely target out of worldborder"); + @Inject(method = "changeDimension", cancellable = true, at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;teleport(DDDFF)V")) + private void arclight$cancelledTeleport(DimensionTransition dimensionTransition, CallbackInfoReturnable cir) { + if (((ServerPlayNetHandlerBridge) this.connection).bridge$teleportCancelled()) { + cir.setReturnValue(null); } - return optional1; } - private transient BlockStateListPopulator arclight$populator; - - @Inject(method = "createEndPlatform", at = @At("HEAD")) - private void arclight$playerCreatePortalBegin(ServerLevel level, BlockPos pos, CallbackInfo ci) { - arclight$populator = new BlockStateListPopulator(level); - } - - @Redirect(method = "createEndPlatform", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) - private boolean arclight$playerCreatePortal(ServerLevel instance, BlockPos pos, BlockState blockState) { - return arclight$populator.setBlock(pos, blockState, 3); + @Decorate(method = "changeDimension", inject = true, at = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerPlayer;isChangingDimension:Z")) + private void arclight$fireTeleportEvent(DimensionTransition dimensionTransition, @Local(ordinal = 0) ServerLevel newLevel, @Local(ordinal = 1) ServerLevel oldLevel) throws Throwable { + Location enter = this.getBukkitEntity().getLocation(); + Location exit = (newLevel == null) ? null : CraftLocation.toBukkit(dimensionTransition.pos(), newLevel.bridge$getWorld(), dimensionTransition.yRot(), dimensionTransition.xRot()); + PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$getTeleportCause()); + Bukkit.getServer().getPluginManager().callEvent(tpEvent); + if (tpEvent.isCancelled() || tpEvent.getTo() == null) { + DecorationOps.cancel().invoke((Entity) null); + return; + } + exit = tpEvent.getTo(); + newLevel = ((CraftWorld) exit.getWorld()).getHandle(); + dimensionTransition = new DimensionTransition(newLevel, new Vec3(exit.getX(), exit.getY(), exit.getZ()), dimensionTransition.speed(), exit.getYaw(), exit.getPitch(), dimensionTransition.postDimensionTransition()); + ((ServerPlayNetHandlerBridge) this.connection).bridge$pushNoTeleportEvent(); + DecorationOps.blackhole().invoke(newLevel, dimensionTransition); } - @Inject(method = "createEndPlatform", at = @At("RETURN")) - private void arclight$playerCreatePortalEnd(ServerLevel level, BlockPos pos, CallbackInfo ci) { - var blockList = arclight$populator; - arclight$populator = null; - var portalEvent = new PortalCreateEvent((List) (List) blockList.getList(), ((WorldBridge) level).bridge$getWorld(), this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM); - Bukkit.getPluginManager().callEvent(portalEvent); - if (!portalEvent.isCancelled()) { - blockList.updateList(); - } + @Decorate(method = "changeDimension", inject = true, at = @At("RETURN"), + slice = @Slice(from = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/portal/DimensionTransition$PostDimensionTransition;onTransition(Lnet/minecraft/world/entity/Entity;)V"))) + private void arclight$fireChangeWorldEvent(DimensionTransition dimensionTransition, @Local(ordinal = 0) ServerLevel newLevel, @Local(ordinal = 1) ServerLevel oldLevel) { + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), oldLevel.bridge$getWorld()); + Bukkit.getPluginManager().callEvent(changeEvent); } private Either getBedResult(BlockPos blockposition, Direction enumdirection) { @@ -555,7 +562,7 @@ private Either getBedResult(BlockPos blockposit return Either.left(Player.BedSleepingProblem.OTHER_PROBLEM); } - @Redirect(method = "startSleepInBed", at = @At(value = "INVOKE", remap = false, target = "Lcom/mojang/datafixers/util/Either;left(Ljava/lang/Object;)Lcom/mojang/datafixers/util/Either;")) + @Redirect(method = "startSleepInBed", require = 0, at = @At(value = "INVOKE", remap = false, target = "Lcom/mojang/datafixers/util/Either;left(Ljava/lang/Object;)Lcom/mojang/datafixers/util/Either;")) private Either arclight$failSleep(L value, BlockPos pos) { Either either = Either.left(value); return arclight$fireBedEvent(either, pos); @@ -566,7 +573,7 @@ private Either getBedResult(BlockPos blockposit return arclight$fireBedEvent(either, pos).ifRight(consumer); } - @Inject(method = "startSleepInBed", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) + @Inject(method = "startSleepInBed", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) private void arclight$bedCause(BlockPos p_9115_, CallbackInfoReturnable> cir) { this.bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.BED); } @@ -617,26 +624,21 @@ private Either getBedResult(BlockPos blockposit return this.containerCounter; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void openHorseInventory(final AbstractHorse entityhorseabstract, final Container iinventory) { + @Decorate(method = "openHorseInventory", inject = true, at = @At("HEAD")) + private void arclight$openHorseInv(final AbstractHorse entityhorseabstract, final Container iinventory) throws Throwable { this.nextContainerCounter(); - AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), iinventory, entityhorseabstract); + AbstractContainerMenu container = new HorseInventoryMenu(this.containerCounter, this.getInventory(), iinventory, entityhorseabstract, entityhorseabstract.getInventoryColumns()); ((ContainerBridge) container).bridge$setTitle(entityhorseabstract.getDisplayName()); container = CraftEventFactory.callInventoryOpenEvent((ServerPlayer) (Object) this, container); if (container == null) { iinventory.stopOpen((ServerPlayer) (Object) this); return; } - if (this.containerMenu != this.inventoryMenu) { - this.closeContainer(); - } - this.connection.send(new ClientboundHorseScreenOpenPacket(this.containerCounter, iinventory.getContainerSize(), entityhorseabstract.getId())); - this.containerMenu = container; - this.initMenu(this.containerMenu); + DecorationOps.blackhole().invoke(); + } + + @Redirect(method = "openHorseInventory", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;nextContainerCounter()V")) + private void arclight$skipSwitchHorse(ServerPlayer instance) { } @Inject(method = "doCloseContainer", at = @At("HEAD")) @@ -823,52 +825,59 @@ public void setRespawnPosition(ResourceKey p_9159_, @Nullable BlockPos p_ this.setRespawnPosition(p_9159_, p_9160_, p_9161_, p_9162_, p_9163_); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void setRespawnPosition(ResourceKey p_9159_, @Nullable BlockPos p_9160_, float p_9161_, boolean p_9162_, boolean p_9163_) { + @Decorate(method = "setRespawnPosition", inject = true, at = @At("HEAD")) + private void arclight$spawnChangeEvent(ResourceKey resourceKey, BlockPos blockPos, float yaw, boolean forced) throws Throwable { var cause = arclight$spawnChangeCause == null ? PlayerSpawnChangeEvent.Cause.UNKNOWN : arclight$spawnChangeCause; arclight$spawnChangeCause = null; - var newWorld = this.server.getLevel(p_9159_); - Location newSpawn = (p_9160_ != null) ? new Location(((ServerWorldBridge) newWorld).bridge$getWorld(), p_9160_.getX(), p_9160_.getY(), p_9160_.getZ(), p_9161_, 0) : null; + ServerLevel newWorld = this.server.getLevel(resourceKey); + Location newSpawn = (blockPos != null) ? CraftLocation.toBukkit(blockPos, newWorld.bridge$getWorld(), yaw, 0) : null; - PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, p_9162_, cause); + PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, forced, cause); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; } newSpawn = event.getNewSpawn(); - p_9162_ = event.isForced(); + forced = event.isForced(); if (newSpawn != null) { - p_9159_ = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); - p_9160_ = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); - p_9161_ = newSpawn.getYaw(); + resourceKey = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); + blockPos = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); + yaw = newSpawn.getYaw(); } else { - p_9159_ = Level.OVERWORLD; - p_9160_ = null; - p_9161_ = 0.0F; + resourceKey = Level.OVERWORLD; + blockPos = null; + yaw = 0.0F; } + DecorationOps.blackhole().invoke(resourceKey, blockPos, yaw, forced); + } - if (p_9160_ != null) { - boolean flag = p_9160_.equals(this.respawnPosition) && p_9159_.equals(this.respawnDimension); - if (p_9163_ && !flag) { - this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); - } - - this.respawnPosition = p_9160_; - this.respawnDimension = p_9159_; - this.respawnAngle = p_9161_; - this.respawnForced = p_9162_; - } else { - this.respawnPosition = null; - this.respawnDimension = Level.OVERWORLD; - this.respawnAngle = 0.0F; - this.respawnForced = false; + @Decorate(method = "openMenu*", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;closeContainer()V")) + private void arclight$skipSwitch(ServerPlayer serverPlayer) throws Throwable { + if (Blackhole.actuallyFalse()) { + DecorationOps.callsite().invoke(serverPlayer); } + } + @Decorate(method = "openMenu*", inject = true, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/MenuProvider;createMenu(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/inventory/AbstractContainerMenu;")) + private void arclight$invOpen(MenuProvider iTileInventory, @Local(ordinal = 0) AbstractContainerMenu container) throws Throwable { + if (container != null) { + ((ContainerBridge) container).bridge$setTitle(iTileInventory.getDisplayName()); + boolean cancelled = false; + ArclightCaptures.captureContainerOwner((ServerPlayer) (Object) this); + container = CraftEventFactory.callInventoryOpenEvent((ServerPlayer) (Object) this, container, cancelled); + ArclightCaptures.resetContainerOwner(); + if (container == null && !cancelled) { + if (iTileInventory instanceof Container) { + ((Container) iTileInventory).stopOpen((ServerPlayer) (Object) this); + } else if (ChestBlockDoubleInventoryHacks.isInstance(iTileInventory)) { + ChestBlockDoubleInventoryHacks.get(iTileInventory).stopOpen((ServerPlayer) (Object) this); + } + DecorationOps.cancel().invoke(OptionalInt.empty()); + return; + } + } + DecorationOps.blackhole().invoke(); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayer_RespawnPosAngleMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayer_RespawnPosAngleMixin.java new file mode 100644 index 000000000..78fa49f23 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerPlayer_RespawnPosAngleMixin.java @@ -0,0 +1,33 @@ +package io.izzel.arclight.common.mixin.core.server.level; + +import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import net.minecraft.server.level.ServerPlayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ServerPlayer.RespawnPosAngle.class) +public class ServerPlayer_RespawnPosAngleMixin implements ServerPlayerEntityBridge.RespawnPosAngleBridge { + + @Unique private boolean isBedSpawn; + @Unique private boolean isAnchorSpawn; + + @Override + public boolean bridge$isBedSpawn() { + return isBedSpawn; + } + + @Override + public boolean bridge$isAnchorSpawn() { + return isAnchorSpawn; + } + + @Override + public void bridge$setBedSpawn(boolean b) { + isBedSpawn = b; + } + + @Override + public void bridge$setAnchorSpawn(boolean b) { + isAnchorSpawn = b; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java index 96761f253..088bb69a9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java @@ -3,7 +3,6 @@ import com.google.common.collect.Lists; import com.mojang.authlib.GameProfile; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import io.izzel.arclight.common.bridge.core.entity.InternalEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.network.NetworkManagerBridge; import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; @@ -12,6 +11,8 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import io.izzel.arclight.mixin.Eject; import net.minecraft.core.BlockPos; import net.minecraft.core.LayeredRegistryAccess; @@ -27,7 +28,6 @@ import net.minecraft.network.protocol.game.ClientboundSetExperiencePacket; import net.minecraft.network.protocol.game.ClientboundSetSimulationDistancePacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; -import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.RegistryLayer; @@ -35,6 +35,7 @@ import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.server.network.ServerLoginPacketListenerImpl; import net.minecraft.server.players.IpBanList; import net.minecraft.server.players.IpBanListEntry; @@ -44,15 +45,12 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.stats.ServerStatsCounter; -import net.minecraft.tags.BlockTags; -import net.minecraft.util.Mth; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.Mob; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.portal.DimensionTransition; import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.level.storage.LevelResource; import net.minecraft.world.level.storage.PlayerDataStorage; @@ -63,6 +61,7 @@ import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.util.CraftChatMessage; +import org.bukkit.craftbukkit.v.util.CraftLocation; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; @@ -76,7 +75,6 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; @@ -84,6 +82,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import javax.annotation.Nullable; import java.io.File; @@ -93,7 +92,6 @@ import java.text.SimpleDateFormat; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.UUID; @Mixin(PlayerList.class) @@ -120,6 +118,8 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Shadow public abstract void sendAllPlayerInfo(ServerPlayer playerIn); @Shadow @Nullable public abstract ServerPlayer getPlayer(UUID playerUUID); @Shadow public abstract void broadcastSystemMessage(Component p_240618_, boolean p_240644_); + @Shadow public abstract void sendActivePlayerEffects(ServerPlayer serverPlayer); + @Shadow public abstract ServerPlayer respawn(ServerPlayer serverPlayer, boolean bl, Entity.RemovalReason removalReason); // @formatter:on private CraftServer cserver; @@ -222,6 +222,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { entityplayer.connection.disconnect(Component.translatable("multiplayer.disconnect.duplicate_login")); } ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, ClientInformation.createDefault()); + ((ServerPlayerEntityBridge) entity).bridge$setTransferCookieConnection((CraftPlayer.TransferCookieConnection) handler); Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(); String hostname = handler == null ? "" : ((NetworkManagerBridge) handler.connection).bridge$getHostname(); @@ -257,23 +258,26 @@ public abstract class PlayerListMixin implements PlayerListBridge { return entity; } - public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, PlayerRespawnEvent.RespawnReason reason) { - return this.respawn(entityplayer, this.server.getLevel(entityplayer.getRespawnDimension()), flag, null, true, reason); + public ServerPlayer respawn(ServerPlayer entityplayer, boolean flag, Entity.RemovalReason entity_removalreason, PlayerRespawnEvent.RespawnReason reason) { + return this.respawn(entityplayer, flag, entity_removalreason, reason, null); } - public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean flag, Location location, boolean avoidSuffocation, PlayerRespawnEvent.RespawnReason respawnReason) { + public ServerPlayer respawn(ServerPlayer playerIn, boolean flag, Entity.RemovalReason removalReason, PlayerRespawnEvent.RespawnReason respawnReason, Location location) { + if (true) { // TODO remove on next update + arclight$respawnReason = respawnReason; + arclight$loc = location; + return this.respawn(playerIn, flag, removalReason); + } if (respawnReason == null && location != null) { - if (bridge$platform$onTravelToDimension(playerIn, worldIn.dimension())) { + // TODO + if (bridge$platform$onTravelToDimension(playerIn, ((CraftWorld) location.getWorld()).getHandle().dimension)) { return null; } } playerIn.stopRiding(); this.players.remove(playerIn); - playerIn.serverLevel().removePlayerImmediately(playerIn, Entity.RemovalReason.DISCARDED); + playerIn.serverLevel().removePlayerImmediately(playerIn, removalReason); ((EntityBridge) playerIn).bridge$revive(); - BlockPos pos = playerIn.getRespawnPosition(); - float f = playerIn.getRespawnAngle(); - boolean flag2 = playerIn.isRespawnForced(); org.bukkit.World fromWorld = ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().getWorld(); playerIn.wonGame = false; /* @@ -284,56 +288,19 @@ public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean playerIn.addTag(s); } */ - boolean flag3 = false; + DimensionTransition dimensiontransition; if (location == null) { - boolean isBedSpawn = false; - ServerLevel spawnWorld = this.server.getLevel(playerIn.getRespawnDimension()); - if (spawnWorld != null) { - Optional optional; - if (pos != null) { - optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(spawnWorld, pos, f, flag2, flag); - } else { - optional = Optional.empty(); - } - if (optional.isPresent()) { - BlockState iblockdata = spawnWorld.getBlockState(pos); - boolean flag4 = iblockdata.is(Blocks.RESPAWN_ANCHOR); - Vec3 vec3d = optional.get(); - float f2; - if (!iblockdata.is(BlockTags.BEDS) && !flag4) { - f2 = f; - } else { - Vec3 vec3d2 = Vec3.atBottomCenterOf(pos).subtract(vec3d).normalize(); - f2 = (float) Mth.wrapDegrees(Mth.atan2(vec3d2.z, vec3d2.x) * 57.2957763671875 - 90.0); - } - // playerIn.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, f2, 0.0f); - // playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); - flag3 = (!flag && flag4); - isBedSpawn = true; - location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), vec3d.x, vec3d.y, vec3d.z); - } else if (pos != null) { - playerIn.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0f)); - ((ServerPlayerEntityBridge) playerIn).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESET); - playerIn.setRespawnPosition(Level.OVERWORLD, null, 0f, false, false); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed - } - } - if (location == null) { - spawnWorld = this.server.getLevel(Level.OVERWORLD); - pos = ((ServerPlayerEntityBridge) playerIn).bridge$getSpawnPoint(spawnWorld); - location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), pos.getX() + 0.5f, pos.getY() + 0.1f, pos.getZ() + 0.5f); - } - Player respawnPlayer = ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity(); - PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag3, flag3, respawnReason); - this.cserver.getPluginManager().callEvent(respawnEvent); - if (((ServerPlayNetHandlerBridge) playerIn.connection).bridge$isDisconnected()) { - return playerIn; - } - location = respawnEvent.getRespawnLocation(); + ((ServerPlayerEntityBridge) playerIn).bridge$pushRespawnReason(respawnReason); + dimensiontransition = playerIn.findRespawnPositionAndUseSpawnBlock(flag, DimensionTransition.DO_NOTHING); if (!flag) { - ((ServerPlayerEntityBridge) playerIn).bridge$reset(); + ((ServerPlayerEntityBridge) playerIn).bridge$reset(); // SPIGOT-4785 } } else { - location.setWorld(((WorldBridge) worldIn).bridge$getWorld()); + dimensiontransition = new DimensionTransition(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toVec3D(location), Vec3.ZERO, location.getYaw(), location.getPitch(), DimensionTransition.DO_NOTHING); + } + // Spigot Start + if (dimensiontransition == null) { + return playerIn; } ServerLevel serverWorld = ((CraftWorld) location.getWorld()).getHandle(); playerIn.setServerLevel(serverWorld); @@ -341,8 +308,10 @@ public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean playerIn.setShiftKeyDown(false); playerIn.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); playerIn.connection.resetPosition(); - while (avoidSuffocation && !serverWorld.noCollision(playerIn) && playerIn.getY() < serverWorld.getMaxBuildHeight()) { - playerIn.setPos(playerIn.getX(), playerIn.getY() + 1.0, playerIn.getZ()); + if (dimensiontransition.missingRespawnBlock()) { + playerIn.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0F)); + ((ServerPlayerEntityBridge) playerIn).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESET); + playerIn.setRespawnPosition(null, null, 0f, false, false); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed } LevelData worlddata = serverWorld.getLevelData(); playerIn.connection.send(new ClientboundRespawnPacket(playerIn.createCommonSpawnInfo(serverWorld), (byte) (flag ? 1 : 0))); @@ -352,6 +321,7 @@ public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean playerIn.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverWorld.getSharedSpawnPos(), serverWorld.getSharedSpawnAngle())); playerIn.connection.send(new ClientboundChangeDifficultyPacket(worlddata.getDifficulty(), worlddata.isDifficultyLocked())); playerIn.connection.send(new ClientboundSetExperiencePacket(playerIn.experienceProgress, playerIn.totalExperience, playerIn.experienceLevel)); + this.sendActivePlayerEffects(playerIn); this.sendLevelInfo(playerIn, serverWorld); this.sendPlayerPermissionLevel(playerIn); if (!((ServerPlayNetHandlerBridge) playerIn.connection).bridge$isDisconnected()) { @@ -361,15 +331,16 @@ public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean } playerIn.setHealth(playerIn.getHealth()); bridge$platform$onPlayerChangedDimension(playerIn, ((CraftWorld) fromWorld).getHandle().dimension, serverWorld.dimension); - if (flag3) { - playerIn.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, pos.getX(), pos.getY(), pos.getZ(), 1.0f, 1.0f, serverWorld.random.nextLong())); + if (!flag) { + BlockPos blockposition = BlockPos.containing(dimensiontransition.pos()); + BlockState iblockdata = serverWorld.getBlockState(blockposition); + + if (iblockdata.is(Blocks.RESPAWN_ANCHOR)) { + playerIn.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), 1.0F, 1.0F, serverWorld.getRandom().nextLong())); + } } this.sendAllPlayerInfo(playerIn); playerIn.onUpdateAbilities(); - for (Object o1 : playerIn.getActiveEffects()) { - MobEffectInstance mobEffect = (MobEffectInstance) o1; - playerIn.connection.send(new ClientboundUpdateMobEffectPacket(playerIn.getId(), mobEffect)); - } playerIn.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); if (fromWorld != location.getWorld()) { PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity(), fromWorld); @@ -381,158 +352,75 @@ public ServerPlayer respawn(ServerPlayer playerIn, ServerLevel worldIn, boolean return playerIn; } + @Override + public void bridge$pushRespawnCause(PlayerRespawnEvent.RespawnReason respawnReason) { + if (respawnReason != null) { + arclight$respawnReason = respawnReason; + } + } + private transient Location arclight$loc; - private transient Boolean arclight$suffo; private transient PlayerRespawnEvent.RespawnReason arclight$respawnReason; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public ServerPlayer respawn(ServerPlayer playerIn, boolean conqueredEnd) { - Location location = arclight$loc; - arclight$loc = null; - boolean avoidSuffocation = arclight$suffo == null || arclight$suffo; - arclight$suffo = null; - var respawnReason = arclight$respawnReason == null ? PlayerRespawnEvent.RespawnReason.DEATH : arclight$respawnReason; - arclight$respawnReason = null; - playerIn.stopRiding(); - this.players.remove(playerIn); - playerIn.serverLevel().removePlayerImmediately(playerIn, Entity.RemovalReason.DISCARDED); - BlockPos pos = playerIn.getRespawnPosition(); - float f = playerIn.getRespawnAngle(); - boolean flag2 = playerIn.isRespawnForced(); - - org.bukkit.World fromWorld = ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().getWorld(); - playerIn.wonGame = false; + @Inject(method = "respawn", at = @At("HEAD")) + private void arclight$stopRiding(ServerPlayer serverPlayer, boolean bl, Entity.RemovalReason removalReason, CallbackInfoReturnable cir) { + serverPlayer.stopRiding(); + } - boolean flag3 = false; - ServerLevel spawnWorld = this.server.getLevel(playerIn.getRespawnDimension()); + @Decorate(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;findRespawnPositionAndUseSpawnBlock(ZLnet/minecraft/world/level/portal/DimensionTransition$PostDimensionTransition;)Lnet/minecraft/world/level/portal/DimensionTransition;")) + private DimensionTransition arclight$respawnPoint(ServerPlayer instance, boolean bl, DimensionTransition.PostDimensionTransition postDimensionTransition) throws Throwable { + var location = arclight$loc; + var respawnReason = arclight$respawnReason == null ? PlayerRespawnEvent.RespawnReason.DEATH : arclight$respawnReason; + DimensionTransition dimensiontransition; if (location == null) { - boolean isBedSpawn = false; - if (spawnWorld != null) { - Optional optional; - if (pos != null) { - optional = net.minecraft.world.entity.player.Player.findRespawnPositionAndUseSpawnBlock(spawnWorld, pos, f, flag2, conqueredEnd); - } else { - optional = Optional.empty(); - } - if (optional.isPresent()) { - BlockState iblockdata = spawnWorld.getBlockState(pos); - boolean flag4 = iblockdata.is(Blocks.RESPAWN_ANCHOR); - Vec3 vec3d = optional.get(); - float f2; - if (!iblockdata.is(BlockTags.BEDS) && !flag4) { - f2 = f; - } else { - Vec3 vec3d2 = Vec3.atBottomCenterOf(pos).subtract(vec3d).normalize(); - f2 = (float) Mth.wrapDegrees(Mth.atan2(vec3d2.z, vec3d2.x) * 57.2957763671875 - 90.0); - } - // playerIn.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, f2, 0.0f); - // playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); - flag3 = (!flag2 && flag4); - isBedSpawn = true; - location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), vec3d.x, vec3d.y, vec3d.z); - } else if (pos != null) { - playerIn.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0f)); - ((ServerPlayerEntityBridge) playerIn).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESET); - playerIn.setRespawnPosition(Level.OVERWORLD, null, 0f, false, false); - } - } - if (location == null) { - spawnWorld = this.server.getLevel(Level.OVERWORLD); - pos = ((ServerPlayerEntityBridge) playerIn).bridge$getSpawnPoint(spawnWorld); - location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), pos.getX() + 0.5f, pos.getY() + 0.1f, pos.getZ() + 0.5f); - } - Player respawnPlayer = ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity(); - PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn && !flag3, flag3, respawnReason); - this.cserver.getPluginManager().callEvent(respawnEvent); - if (((ServerPlayNetHandlerBridge) playerIn.connection).bridge$isDisconnected()) { - return playerIn; - } - location = respawnEvent.getRespawnLocation(); - if (!conqueredEnd) { - ((ServerPlayerEntityBridge) playerIn).bridge$reset(); - } + ((ServerPlayerEntityBridge) instance).bridge$pushRespawnReason(respawnReason); + dimensiontransition = (DimensionTransition) DecorationOps.callsite().invoke(instance, bl, postDimensionTransition); } else { - location.setWorld(((WorldBridge) spawnWorld).bridge$getWorld()); + dimensiontransition = new DimensionTransition(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toVec3D(location), Vec3.ZERO, location.getYaw(), location.getPitch(), DimensionTransition.DO_NOTHING); } - - ServerLevel serverWorld = ((CraftWorld) location.getWorld()).getHandle(); - - ServerPlayer serverplayerentity = new ServerPlayer(this.server, serverWorld, playerIn.getGameProfile(), playerIn.clientInformation()); - - // Forward to new player instance - ((InternalEntityBridge) playerIn).internal$getBukkitEntity().setHandle(serverplayerentity); - ((EntityBridge) serverplayerentity).bridge$setBukkitEntity(((InternalEntityBridge) playerIn).internal$getBukkitEntity()); - if ((Object) playerIn instanceof Mob) { - ((Mob) (Object) playerIn).dropLeash(true, false); + if (dimensiontransition == null) { + return (DimensionTransition) DecorationOps.cancel().invoke(instance); } - playerIn.connection.player = serverplayerentity; + return dimensiontransition; + } - serverplayerentity.connection = playerIn.connection; - serverplayerentity.restoreFrom(playerIn, conqueredEnd); - serverplayerentity.setRespawnPosition(playerIn.getRespawnDimension(), playerIn.getRespawnPosition(), playerIn.getRespawnAngle(), playerIn.isRespawnForced(), false); + @Decorate(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;restoreFrom(Lnet/minecraft/server/level/ServerPlayer;Z)V")) + private void arclight$restoreInv(ServerPlayer newPlayer, ServerPlayer oldPlayer, boolean bl, ServerPlayer serverPlayer, boolean conqueredEnd) throws Throwable { + DecorationOps.callsite().invoke(newPlayer, oldPlayer, bl); if (!conqueredEnd) { // keep inventory here since inventory dropped at ServerPlayerEntity#onDeath - serverplayerentity.getInventory().replaceWith(playerIn.getInventory()); - serverplayerentity.experienceLevel = playerIn.experienceLevel; - serverplayerentity.totalExperience = playerIn.totalExperience; - serverplayerentity.experienceProgress = playerIn.experienceProgress; - serverplayerentity.setScore(playerIn.getScore()); + newPlayer.getInventory().replaceWith(oldPlayer.getInventory()); + newPlayer.experienceLevel = oldPlayer.experienceLevel; + newPlayer.totalExperience = oldPlayer.totalExperience; + newPlayer.experienceProgress = oldPlayer.experienceProgress; + newPlayer.setScore(oldPlayer.getScore()); } - serverplayerentity.setId(playerIn.getId()); - serverplayerentity.setMainArm(playerIn.getMainArm()); - - for (String s : playerIn.getTags()) { - serverplayerentity.addTag(s); - } - - serverplayerentity.setServerLevel(serverWorld); - serverplayerentity.setShiftKeyDown(false); - serverplayerentity.moveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); - serverplayerentity.connection.resetPosition(); + } - while (avoidSuffocation && !serverWorld.noCollision(serverplayerentity) && serverplayerentity.getY() < serverWorld.getMaxBuildHeight()) { - serverplayerentity.setPos(serverplayerentity.getX(), serverplayerentity.getY() + 1.0D, serverplayerentity.getZ()); - } + @Redirect(method = "respawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;teleport(DDDFF)V")) + private void arclight$respawnPackets(ServerGamePacketListenerImpl instance, double d, double e, double f, float g, float h) { + var player = instance.player; + player.connection.send(new ClientboundSetChunkCacheRadiusPacket(((WorldBridge) player.serverLevel()).bridge$spigotConfig().viewDistance)); + player.connection.send(new ClientboundSetSimulationDistancePacket(((WorldBridge) player.serverLevel()).bridge$spigotConfig().simulationDistance)); + ((ServerPlayNetHandlerBridge) player.connection).bridge$teleport(new Location(player.serverLevel().bridge$getWorld(), player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot())); + } - LevelData iworldinfo = serverplayerentity.level().getLevelData(); - serverplayerentity.connection.send(new ClientboundRespawnPacket(serverplayerentity.createCommonSpawnInfo(serverplayerentity.serverLevel()), (byte) (conqueredEnd ? 1 : 0))); - serverplayerentity.connection.send(new ClientboundSetChunkCacheRadiusPacket(((WorldBridge) serverWorld).bridge$spigotConfig().viewDistance)); - serverplayerentity.connection.send(new ClientboundSetSimulationDistancePacket(((WorldBridge) serverWorld).bridge$spigotConfig().simulationDistance)); - ((ServerPlayNetHandlerBridge) serverplayerentity.connection).bridge$teleport(new Location(((WorldBridge) serverWorld).bridge$getWorld(), serverplayerentity.getX(), serverplayerentity.getY(), serverplayerentity.getZ(), serverplayerentity.getYRot(), serverplayerentity.getXRot())); - serverplayerentity.connection.send(new ClientboundSetDefaultSpawnPositionPacket(serverWorld.getSharedSpawnPos(), serverWorld.getSharedSpawnAngle())); - serverplayerentity.connection.send(new ClientboundChangeDifficultyPacket(iworldinfo.getDifficulty(), iworldinfo.isDifficultyLocked())); - serverplayerentity.connection.send(new ClientboundSetExperiencePacket(serverplayerentity.experienceProgress, serverplayerentity.totalExperience, serverplayerentity.experienceLevel)); - this.sendLevelInfo(serverplayerentity, serverWorld); - this.sendPlayerPermissionLevel(serverplayerentity); - if (!((ServerPlayNetHandlerBridge) serverplayerentity.connection).bridge$isDisconnected()) { - serverWorld.addRespawnedPlayer(serverplayerentity); - this.players.add(serverplayerentity); - this.playersByUUID.put(serverplayerentity.getUUID(), serverplayerentity); - } - serverplayerentity.initInventoryMenu(); - serverplayerentity.setHealth(serverplayerentity.getHealth()); - bridge$platform$onPlayerRespawn(serverplayerentity, conqueredEnd); - if (flag2) { - serverplayerentity.connection.send(new ClientboundSoundPacket(SoundEvents.RESPAWN_ANCHOR_DEPLETE, SoundSource.BLOCKS, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), 1.0F, 1.0F, serverWorld.random.nextLong())); - } - this.sendAllPlayerInfo(serverplayerentity); - serverplayerentity.onUpdateAbilities(); - for (Object o1 : serverplayerentity.getActiveEffects()) { - MobEffectInstance mobEffect = (MobEffectInstance) o1; - serverplayerentity.connection.send(new ClientboundUpdateMobEffectPacket(serverplayerentity.getId(), mobEffect)); - } - serverplayerentity.triggerDimensionChangeTriggers(((CraftWorld) fromWorld).getHandle()); + @Inject(method = "respawn", at = @At("RETURN")) + private void arclight$postRespawn(ServerPlayer serverPlayer, boolean bl, Entity.RemovalReason removalReason, CallbackInfoReturnable cir) { + var location = arclight$loc; + arclight$loc = null; + arclight$respawnReason = null; + var fromWorld = serverPlayer.serverLevel(); + var newPlayer = cir.getReturnValue(); + this.sendAllPlayerInfo(newPlayer); + newPlayer.onUpdateAbilities(); + newPlayer.triggerDimensionChangeTriggers(fromWorld); if (fromWorld != location.getWorld()) { - PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(((ServerPlayerEntityBridge) serverplayerentity).bridge$getBukkitEntity(), fromWorld); + PlayerChangedWorldEvent event = new PlayerChangedWorldEvent(((ServerPlayerEntityBridge) newPlayer).bridge$getBukkitEntity(), fromWorld.bridge$getWorld()); Bukkit.getPluginManager().callEvent(event); } - if (((ServerPlayNetHandlerBridge) serverplayerentity.connection).bridge$isDisconnected()) { - this.save(serverplayerentity); + if (((ServerPlayNetHandlerBridge) newPlayer.connection).bridge$isDisconnected()) { + this.save(newPlayer); } - return serverplayerentity; } public void broadcastAll(Packet packet, net.minecraft.world.entity.player.Player entityhuman) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/ServerPlayerGameModeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/ServerPlayerGameModeMixin.java index 205a4f02e..d0855c5ec 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/ServerPlayerGameModeMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/ServerPlayerGameModeMixin.java @@ -1,26 +1,28 @@ package io.izzel.arclight.common.mixin.core.server.management; -import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.server.management.PlayerInteractionManagerBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; -import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.advancements.CriteriaTriggers; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; +import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.DoubleHighBlockItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemCooldowns; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.CakeBlock; @@ -30,7 +32,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.craftbukkit.v.block.CraftBlock; @@ -41,17 +42,18 @@ import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; -import java.util.Objects; @Mixin(ServerPlayerGameMode.class) public abstract class ServerPlayerGameModeMixin implements PlayerInteractionManagerBridge { @@ -61,20 +63,13 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana @Shadow @Final protected ServerPlayer player; @Shadow public abstract boolean isCreative(); @Shadow private GameType gameModeForPlayer; - @Shadow private int destroyProgressStart; - @Shadow private int gameTicks; - @Shadow private boolean isDestroyingBlock; - @Shadow private BlockPos destroyPos; - @Shadow private int lastSentState; - @Shadow private boolean hasDelayedDestroy; - @Shadow private BlockPos delayedDestroyPos; - @Shadow private int delayedTickStart; - @Shadow public abstract void destroyAndAck(BlockPos p_215117_, int p_215118_, String p_215119_); - @Shadow protected abstract void debugLogging(BlockPos p_215126_, boolean p_215127_, int p_215128_, String p_215129_); // @formatter:on public boolean interactResult = false; public boolean firedInteract = false; + public BlockPos interactPosition; + public InteractionHand interactHand; + public ItemStack interactItemStack; @Inject(method = "changeGameModeForPlayer", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;setGameModeForPlayer(Lnet/minecraft/world/level/GameType;Lnet/minecraft/world/level/GameType;)V")) private void arclight$gameModeEvent(GameType gameType, CallbackInfoReturnable cir) { @@ -85,141 +80,77 @@ public abstract class ServerPlayerGameModeMixin implements PlayerInteractionMana } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void handleBlockBreakAction(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, int i, int j) { - if (!this.level.hasChunkAt(blockPos)) { - return; + @Redirect(method = "handleBlockBreakAction", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;send(Lnet/minecraft/network/protocol/Packet;)V"), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;mayInteract(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;)Z"))) + private void arclight$mayNotInteractEvent(ServerGamePacketListenerImpl instance, Packet packet, BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction) throws Throwable { + CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockPos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); + DecorationOps.callsite().invoke(instance, packet); + BlockEntity blockEntity = this.level.getBlockEntity(blockPos); + if (blockEntity != null) { + this.player.connection.send(blockEntity.getUpdatePacket()); } + } - var forgeEvent = ((PlayerEntityBridge) player).bridge$platform$onLeftClickBlock(blockPos, direction, action); - if (forgeEvent._1 || (!this.isCreative() && forgeEvent._2)) { // Restore block and te data - level.sendBlockUpdated(blockPos, level.getBlockState(blockPos), level.getBlockState(blockPos), 3); + @Decorate(method = "handleBlockBreakAction", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayerGameMode;isCreative()Z")) + private void arclight$interactEvent(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, + @Local(allocate = "playerInteractEvent") PlayerInteractEvent event) throws Throwable { + event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockPos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); + if (event.isCancelled()) { + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); + BlockEntity blockEntity = this.level.getBlockEntity(blockPos); + if (blockEntity != null) { + this.player.connection.send(blockEntity.getUpdatePacket()); + } + DecorationOps.cancel().invoke(); return; } - if (this.player.getEyePosition().distanceToSqr(Vec3.atCenterOf(blockPos)) != 0 // mixin compat with immptl: https://github.com/iPortalTeam/ImmersivePortalsMod/blob/f419883d285995f2269da11bc1c761e76dafd0e9/src/main/java/qouteall/imm_ptl/core/mixin/common/interaction/MixinServerPlayerGameMode.java - && !((PlayerEntityBridge) this.player).bridge$platform$canReach(blockPos, 1.5)) { // Vanilla check is eye-to-center distance < 6, so padding is 6 - 4.5 = 1.5 - this.debugLogging(blockPos, false, j, "too far"); - } else if (blockPos.getY() >= i) { - this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos))); - this.debugLogging(blockPos, false, j, "too high"); - } else if (action == ServerboundPlayerActionPacket.Action.START_DESTROY_BLOCK) { - if (!this.level.mayInteract(this.player, blockPos)) { - CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockPos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); - this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos))); - this.debugLogging(blockPos, false, j, "may not interact"); - BlockEntity tileentity = this.level.getBlockEntity(blockPos); - if (tileentity != null) { - this.player.connection.send(tileentity.getUpdatePacket()); - } - return; - } - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK, blockPos, direction, this.player.getInventory().getSelected(), InteractionHand.MAIN_HAND); - if (event.isCancelled()) { + DecorationOps.blackhole().invoke(); + } + + @Decorate(method = "handleBlockBreakAction", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/block/state/BlockState;isAir()Z")) + private boolean arclight$playerInteractCancelled(BlockState instance, BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, + @Local(allocate = "playerInteractEvent") PlayerInteractEvent event) throws Throwable { + boolean result = false; + if (event.useInteractedBlock() == org.bukkit.event.Event.Result.DENY) { + BlockState data = this.level.getBlockState(blockPos); + if (data.getBlock() instanceof DoorBlock) { + boolean bottom = data.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - BlockEntity tileentity2 = this.level.getBlockEntity(blockPos); - if (tileentity2 != null) { - this.player.connection.send(tileentity2.getUpdatePacket()); - } - return; - } - if (this.isCreative()) { - this.destroyAndAck(blockPos, j, "creative destroy"); - return; - } - // Spigot start - handle debug stick left click for non-creative - if (this.player.getMainHandItem().is(net.minecraft.world.item.Items.DEBUG_STICK) - && ((net.minecraft.world.item.DebugStickItem) net.minecraft.world.item.Items.DEBUG_STICK).handleInteraction(this.player, this.level.getBlockState(blockPos), this.level, blockPos, false, this.player.getMainHandItem())) { + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? blockPos.above() : blockPos.below())); + } else if (data.getBlock() instanceof TrapDoorBlock) { this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - return; - } - // Spigot end - if (this.player.blockActionRestricted(this.level, blockPos, this.gameModeForPlayer)) { - this.player.connection.send(new ClientboundBlockUpdatePacket(blockPos, this.level.getBlockState(blockPos))); - this.debugLogging(blockPos, false, j, "block action restricted"); - return; } - this.destroyProgressStart = this.gameTicks; - float f = 1.0f; - BlockState iblockdata = this.level.getBlockState(blockPos); - if (event.useInteractedBlock() == org.bukkit.event.Event.Result.DENY) { - BlockState data = this.level.getBlockState(blockPos); - if (data.getBlock() instanceof DoorBlock) { - boolean bottom = data.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; - this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? blockPos.above() : blockPos.below())); - } else if (data.getBlock() instanceof TrapDoorBlock) { - this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - } - } else if (!iblockdata.isAir()) { - if (!forgeEvent._3) { - iblockdata.attack(this.level, blockPos, this.player); - } - f = iblockdata.getDestroyProgress(this.player, this.player.level(), blockPos); - } - if (event.useItemInHand() == Event.Result.DENY) { - if (f > 1.0f) { - this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - } - return; - } - BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, blockPos, this.player.getInventory().getSelected(), f >= 1.0f); - if (blockEvent.isCancelled()) { + result = true; + } else { + result = (boolean) DecorationOps.callsite().invoke(instance); + } + return result; + } + + @Decorate(method = "handleBlockBreakAction", inject = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/block/state/BlockState;isAir()Z")) + private void arclight$blockDamageEvent(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, + @Local(ordinal = -1) float f, + @Local(allocate = "playerInteractEvent") PlayerInteractEvent event) throws Throwable { + if (event.useItemInHand() == Event.Result.DENY) { + if (f > 1.0f) { this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); - return; - } - if (blockEvent.getInstaBreak()) { - f = 2.0f; - } - if (!iblockdata.isAir() && f >= 1.0f) { - this.destroyAndAck(blockPos, j, "insta mine"); - } else { - if (this.isDestroyingBlock) { - this.player.connection.send(new ClientboundBlockUpdatePacket(this.destroyPos, this.level.getBlockState(this.destroyPos))); - this.debugLogging(blockPos, false, j, "abort destroying since another started (client insta mine, server disagreed)"); - } - this.isDestroyingBlock = true; - this.destroyPos = blockPos; - int state = (int) (f * 10.0f); - this.level.destroyBlockProgress(this.player.getId(), blockPos, state); - this.debugLogging(blockPos, true, j, "actual start of destroying"); - CraftEventFactory.callBlockDamageAbortEvent(this.player, blockPos, this.player.getInventory().getSelected()); - this.lastSentState = state; - } - } else if (action == ServerboundPlayerActionPacket.Action.STOP_DESTROY_BLOCK) { - if (blockPos.equals(this.destroyPos)) { - int k = this.gameTicks - this.destroyProgressStart; - BlockState iblockdata = this.level.getBlockState(blockPos); - if (!iblockdata.isAir()) { - float f2 = iblockdata.getDestroyProgress(this.player, this.player.level(), blockPos) * (k + 1); - if (f2 >= 0.7f) { - this.isDestroyingBlock = false; - this.level.destroyBlockProgress(this.player.getId(), blockPos, -1); - this.destroyAndAck(blockPos, j, "destroyed"); - return; - } - if (!this.hasDelayedDestroy) { - this.isDestroyingBlock = false; - this.hasDelayedDestroy = true; - this.delayedDestroyPos = blockPos; - this.delayedTickStart = this.destroyProgressStart; - } - } - } - this.debugLogging(blockPos, true, j, "stopped destroying"); - } else if (action == ServerboundPlayerActionPacket.Action.ABORT_DESTROY_BLOCK) { - this.isDestroyingBlock = false; - if (!Objects.equals(this.destroyPos, blockPos)) { - ArclightServer.LOGGER.debug("Mismatch in destroy block pos: " + this.destroyPos + " " + blockPos); - this.level.destroyBlockProgress(this.player.getId(), this.destroyPos, -1); - this.debugLogging(blockPos, true, j, "aborted mismatched destroying"); } - this.level.destroyBlockProgress(this.player.getId(), blockPos, -1); - this.debugLogging(blockPos, true, j, "aborted destroying"); + return; + } + BlockDamageEvent blockEvent = CraftEventFactory.callBlockDamageEvent(this.player, blockPos, this.player.getInventory().getSelected(), f >= 1.0f); + if (blockEvent.isCancelled()) { + this.player.connection.send(new ClientboundBlockUpdatePacket(this.level, blockPos)); + return; } + if (blockEvent.getInstaBreak()) { + f = 2.0f; + } + DecorationOps.blackhole().invoke(f); + } + + @Inject(method = "handleBlockBreakAction", at = @At(value = "CONSTANT", args = "stringValue=aborted destroying")) + private void arclight$abortBlockBreak(BlockPos blockPos, ServerboundPlayerActionPacket.Action action, Direction direction, int i, int j, CallbackInfo ci) { + CraftEventFactory.callBlockDamageAbortEvent(this.player, blockPos, this.player.getInventory().getSelected()); } @Inject(method = "destroyBlock", at = @At("RETURN")) @@ -270,99 +201,60 @@ public void handleBlockBreakAction(BlockPos blockPos, ServerboundPlayerActionPac this.interactResult = b; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public InteractionResult useItemOn(ServerPlayer playerIn, Level worldIn, ItemStack stackIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn) { + @Override + public BlockPos bridge$getInteractPosition() { + return interactPosition; + } + + @Override + public InteractionHand bridge$getInteractHand() { + return interactHand; + } + + @Override + public ItemStack bridge$getInteractItemStack() { + return interactItemStack; + } + + @Inject(method = "useItemOn", cancellable = true, at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, ordinal = 0, target = "Lnet/minecraft/server/level/ServerPlayerGameMode;gameModeForPlayer:Lnet/minecraft/world/level/GameType;")) + private void arclight$rightClickBlock(ServerPlayer playerIn, Level worldIn, ItemStack stackIn, InteractionHand handIn, BlockHitResult blockRaytraceResultIn, CallbackInfoReturnable cir) { BlockPos blockpos = blockRaytraceResultIn.getBlockPos(); BlockState blockstate = worldIn.getBlockState(blockpos); - // InteractionResult resultType = InteractionResult.PASS; - { // compatible with questadditions - // these variables are not available inside next if block - boolean cancelledBlock = false; - if (!blockstate.getBlock().isEnabled(worldIn.enabledFeatures())) { - return InteractionResult.FAIL; - } else if (this.gameModeForPlayer == GameType.SPECTATOR) { - MenuProvider provider = blockstate.getMenuProvider(worldIn, blockpos); - cancelledBlock = !(provider instanceof MenuProvider); - } - if (playerIn.getCooldowns().isOnCooldown(stackIn.getItem())) { - cancelledBlock = true; - } - - PlayerInteractEvent bukkitEvent = CraftEventFactory.callPlayerInteractEvent(playerIn, Action.RIGHT_CLICK_BLOCK, blockpos, blockRaytraceResultIn.getDirection(), stackIn, cancelledBlock, handIn, blockRaytraceResultIn.getLocation()); - bridge$setFiredInteract(true); - bridge$setInteractResult(bukkitEvent.useItemInHand() == Event.Result.DENY); - if (bukkitEvent.useInteractedBlock() == Event.Result.DENY) { - if (blockstate.getBlock() instanceof DoorBlock) { - boolean bottom = blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; - playerIn.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? blockpos.above() : blockpos.below())); - } else if (blockstate.getBlock() instanceof CakeBlock) { - ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().sendHealthUpdate(); - } else if (stackIn.getItem() instanceof DoubleHighBlockItem) { - // send a correcting update to the client, as it already placed the upper half of the bisected item - playerIn.connection.send(new ClientboundBlockUpdatePacket(level, blockpos.relative(blockRaytraceResultIn.getDirection()).above())); - // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) - playerIn.connection.send(new ClientboundBlockUpdatePacket(level, blockpos.above())); - } - ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().updateInventory(); - return ((bukkitEvent.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS); - } - } + boolean cancelledBlock = false; if (this.gameModeForPlayer == GameType.SPECTATOR) { - MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos); - if (inamedcontainerprovider != null) { - playerIn.openMenu(inamedcontainerprovider); - return InteractionResult.SUCCESS; - } else { - return InteractionResult.PASS; - } - } else { - var event = ((PlayerEntityBridge) player).bridge$platform$onRightClickBlock(handIn, blockpos, blockRaytraceResultIn); - if (event._1) { - return event._6; - } - UseOnContext itemusecontext = new UseOnContext(playerIn, handIn, blockRaytraceResultIn); - if (!event._3) { - InteractionResult result = ((ItemStackBridge) (Object) stackIn).bridge$forge$onItemUseFirst(itemusecontext); - if (result != InteractionResult.PASS) { - return result; - } - } - boolean flag = !playerIn.getMainHandItem().isEmpty() || !playerIn.getOffhandItem().isEmpty(); - boolean flag1 = (playerIn.isSecondaryUseActive() && flag) - && !(((ItemStackBridge) (Object) playerIn.getMainHandItem()).bridge$forge$doesSneakBypassUse(worldIn, blockpos, playerIn) - && (((ItemStackBridge) (Object) playerIn.getOffhandItem()).bridge$forge$doesSneakBypassUse(worldIn, blockpos, playerIn))); - ItemStack itemstack = stackIn.copy(); - InteractionResult resultType = InteractionResult.PASS; - if (event._4 || (!event._5 && !flag1)) { - resultType = blockstate.use(worldIn, playerIn, handIn, blockRaytraceResultIn); - if (resultType.consumesAction()) { - CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, itemstack); - return resultType; - } - } - if (event._2 || (!stackIn.isEmpty() && resultType != InteractionResult.SUCCESS && !bridge$getInteractResult())) { - if (event._3) { - return InteractionResult.PASS; - } - if (this.isCreative()) { - int i = stackIn.getCount(); - resultType = stackIn.useOn(itemusecontext); - stackIn.setCount(i); - } else { - resultType = stackIn.useOn(itemusecontext); - } - - if (resultType.consumesAction()) { - CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, itemstack); - } - return resultType; - } else { - return resultType; + MenuProvider provider = blockstate.getMenuProvider(worldIn, blockpos); + cancelledBlock = !(provider instanceof MenuProvider); + } + if (playerIn.getCooldowns().isOnCooldown(stackIn.getItem())) { + cancelledBlock = true; + } + PlayerInteractEvent bukkitEvent = CraftEventFactory.callPlayerInteractEvent(playerIn, Action.RIGHT_CLICK_BLOCK, blockpos, blockRaytraceResultIn.getDirection(), stackIn, cancelledBlock, handIn, blockRaytraceResultIn.getLocation()); + bridge$setFiredInteract(true); + bridge$setInteractResult(bukkitEvent.useItemInHand() == Event.Result.DENY); + interactPosition = blockpos.immutable(); + interactHand = handIn; + interactItemStack = stackIn.copy(); + if (bukkitEvent.useInteractedBlock() == Event.Result.DENY) { + if (blockstate.getBlock() instanceof DoorBlock) { + boolean bottom = blockstate.getValue(DoorBlock.HALF) == DoubleBlockHalf.LOWER; + playerIn.connection.send(new ClientboundBlockUpdatePacket(this.level, bottom ? blockpos.above() : blockpos.below())); + } else if (blockstate.getBlock() instanceof CakeBlock) { + ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().sendHealthUpdate(); + } else if (stackIn.getItem() instanceof DoubleHighBlockItem) { + // send a correcting update to the client, as it already placed the upper half of the bisected item + playerIn.connection.send(new ClientboundBlockUpdatePacket(level, blockpos.relative(blockRaytraceResultIn.getDirection()).above())); + // send a correcting update to the client for the block above as well, this because of replaceable blocks (such as grass, sea grass etc) + playerIn.connection.send(new ClientboundBlockUpdatePacket(level, blockpos.above())); } + ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().updateInventory(); + cir.setReturnValue((bukkitEvent.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS); } } + + @Decorate(method = "useItemOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemCooldowns;isOnCooldown(Lnet/minecraft/world/item/Item;)Z")) + private boolean arclight$useInteractResult(ItemCooldowns instance, Item item) throws Throwable { + var result = (boolean) DecorationOps.callsite().invoke(instance, item); + DecorationOps.blackhole().invoke(result); + return interactResult; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/StringUtilMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/StringUtilMixin.java new file mode 100644 index 000000000..da1cd191b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/StringUtilMixin.java @@ -0,0 +1,26 @@ +package io.izzel.arclight.common.mixin.core.util; + +import io.izzel.arclight.i18n.ArclightConfig; +import net.minecraft.util.StringUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(StringUtil.class) +public class StringUtilMixin { + + @Unique + private static boolean arclight$validUsernameCheck(String name) { + var regex = ArclightConfig.spec().getCompat().getValidUsernameRegex(); + return !regex.isBlank() && name.matches(regex); + } + + @Inject(method = "isValidPlayerName", cancellable = true, at = @At("HEAD")) + private static void arclight$checkUsername(String name, CallbackInfoReturnable cir) { + if (arclight$validUsernameCheck(name)) { + cir.setReturnValue(true); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/thread/BlockableEventLoopMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/thread/BlockableEventLoopMixin.java new file mode 100644 index 000000000..f59b1869a --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/util/thread/BlockableEventLoopMixin.java @@ -0,0 +1,20 @@ +package io.izzel.arclight.common.mixin.core.util.thread; + +import io.izzel.arclight.common.mod.server.RunnableInPlace; +import net.minecraft.util.thread.BlockableEventLoop; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BlockableEventLoop.class) +public class BlockableEventLoopMixin { + + @Inject(method = "execute", cancellable = true, at = @At("HEAD")) + private void arclight$runInPlace(Runnable runnable, CallbackInfo ci) { + if (runnable instanceof RunnableInPlace) { + runnable.run(); + ci.cancel(); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatEntryMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatEntryMixin.java new file mode 100644 index 000000000..795b0da04 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatEntryMixin.java @@ -0,0 +1,22 @@ +package io.izzel.arclight.common.mixin.core.world.damagesource; + +import io.izzel.arclight.common.bridge.core.world.damagesource.CombatEntryBridge; +import net.minecraft.network.chat.Component; +import net.minecraft.world.damagesource.CombatEntry; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CombatEntry.class) +public class CombatEntryMixin implements CombatEntryBridge { + + private Component arclight$deathMessage; + + @Override + public void bridge$setDeathMessage(Component component) { + this.arclight$deathMessage = component; + } + + @Override + public Component bridge$getDeathMessage() { + return this.arclight$deathMessage; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatTrackerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatTrackerMixin.java new file mode 100644 index 000000000..1f8677e63 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/CombatTrackerMixin.java @@ -0,0 +1,46 @@ +package io.izzel.arclight.common.mixin.core.world.damagesource; + +import io.izzel.arclight.common.bridge.core.world.damagesource.CombatEntryBridge; +import io.izzel.arclight.common.bridge.core.world.damagesource.CombatTrackerBridge; +import net.minecraft.network.chat.Component; +import net.minecraft.world.damagesource.CombatEntry; +import net.minecraft.world.damagesource.CombatTracker; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(CombatTracker.class) +public class CombatTrackerMixin implements CombatTrackerBridge { + + @Shadow @Final private List entries; + + private Component arclight$emptyComnent; + + @Inject(method = "getDeathMessage", cancellable = true, at = @At("HEAD")) + private void arclight$useOverride(CallbackInfoReturnable cir) { + if (!this.entries.isEmpty()) { + var entry = this.entries.get(this.entries.size() - 1); + var deathMessage = ((CombatEntryBridge) (Object) entry).bridge$getDeathMessage(); + cir.setReturnValue(deathMessage); + } else { + if (this.arclight$emptyComnent != null) { + cir.setReturnValue(this.arclight$emptyComnent); + } + } + this.arclight$emptyComnent = null; + } + + @Override + public void bridge$setDeathMessage(Component component) { + this.arclight$emptyComnent = component; + if (!this.entries.isEmpty()) { + var entry = this.entries.get(this.entries.size() - 1); + ((CombatEntryBridge) (Object) entry).bridge$setDeathMessage(component); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourceMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourceMixin.java index 9dcaa320f..4f9a513d7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourceMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourceMixin.java @@ -7,6 +7,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -25,10 +26,12 @@ public abstract class DamageSourceMixin implements DamageSourceBridge { // @formatter:on private org.bukkit.block.Block directBlock; + private org.bukkit.block.BlockState directBlockState; private boolean withSweep; private boolean melting; private boolean poison; - private Entity customCausingEntity = null; + private Entity customEntityDamager = null; + private Entity customCausingEntityDamager = null; public boolean isSweep() { return withSweep; @@ -77,29 +80,63 @@ public DamageSource poison() { return poison(); } - public Entity getCausingEntity() { - return this.customCausingEntity == null ? this.causingEntity : this.customCausingEntity; + public Entity getDamager() { + return this.customEntityDamager == null ? this.causingEntity : this.customEntityDamager; } @Override public Entity bridge$getCausingEntity() { - return this.getCausingEntity(); + return this.getDamager(); } - @Override - public DamageSource bridge$customCausingEntity(Entity entity) { + public DamageSource customEntityDamager(Entity entity) { // This method is not intended for change the causing entity if is already set // also is only necessary if the entity passed is not the direct entity or different from the current causingEntity - if (this.customCausingEntity != null || this.directEntity == entity || this.causingEntity == entity) { + if (this.customEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) { return (DamageSource) (Object) this; } var src = cloneInstance(); return ((DamageSourceBridge) src).bridge$setCustomCausingEntity(entity); } + public Entity getCausingDamager() { + return (this.customCausingEntityDamager != null) ? this.customCausingEntityDamager : this.causingEntity; + } + + @Override + public Entity bridge$getCausingEntityDamager() { + return this.getCausingDamager(); + } + + @Override + public DamageSource bridge$customCausingEntity(Entity entity) { + return customEntityDamager(entity); + } + @Override public DamageSource bridge$setCustomCausingEntity(Entity entity) { - this.customCausingEntity = entity; + this.customEntityDamager = entity; + return (DamageSource) (Object) this; + } + + public DamageSource customCausingEntityDamager(Entity entity) { + // This method is not intended for change the causing entity if is already set + // also is only necessary if the entity passed is not the direct entity or different from the current causingEntity + if (this.customCausingEntityDamager != null || this.directEntity == entity || this.causingEntity == entity) { + return (DamageSource) (Object) this; + } + var src = cloneInstance(); + return ((DamageSourceBridge) src).bridge$setCustomCausingEntityDamager(entity); + } + + @Override + public DamageSource bridge$customCausingEntityDamager(Entity entity) { + return customCausingEntityDamager(entity); + } + + @Override + public DamageSource bridge$setCustomCausingEntityDamager(Entity entity) { + this.customCausingEntityDamager = entity; return (DamageSource) (Object) this; } @@ -123,11 +160,42 @@ public Block getDirectBlock() { return (DamageSource) (Object) this; } + public org.bukkit.block.BlockState getDirectBlockState() { + return this.directBlockState; + } + + public DamageSource directBlockState(org.bukkit.block.BlockState blockState) { + if (blockState == null) { + return (DamageSource) (Object) this; + } + // Cloning the instance lets us return unique instances of DamageSource without affecting constants defined in DamageSources + DamageSource damageSource = this.cloneInstance(); + ((DamageSourceBridge) damageSource).bridge$setDirectBlockState(blockState); + return damageSource; + } + + @Override + public BlockState bridge$directBlockState() { + return this.directBlockState; + } + + @Override + public DamageSource bridge$directBlockState(BlockState block) { + return directBlockState(block); + } + + @Override + public DamageSource bridge$setDirectBlockState(BlockState block) { + this.directBlockState = block; + return (DamageSource) (Object) this; + } + private DamageSource cloneInstance() { var damageSource = new DamageSource(this.type, this.directEntity, this.causingEntity, this.damageSourcePosition); var br = (DamageSourceBridge) damageSource; br.bridge$setDirectBlock(this.bridge$directBlock()); - br.bridge$setCustomCausingEntity(this.customCausingEntity); + br.bridge$setDirectBlockState(this.bridge$directBlockState()); + br.bridge$setCustomCausingEntity(this.customEntityDamager); if (this.withSweep) { br.bridge$sweep(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourcesMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourcesMixin.java index 1e6e4cf59..ae2a1dade 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourcesMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/damagesource/DamageSourcesMixin.java @@ -8,12 +8,16 @@ import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.damagesource.DamageType; import net.minecraft.world.damagesource.DamageTypes; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import javax.annotation.Nullable; + @Mixin(DamageSources.class) public abstract class DamageSourcesMixin implements DamageSourcesBridge { @@ -21,6 +25,12 @@ public abstract class DamageSourcesMixin implements DamageSourcesBridge { @Shadow protected abstract DamageSource source(ResourceKey p_270957_); // @formatter:on + @Shadow + public abstract DamageSource badRespawnPointExplosion(Vec3 vec3); + + @Shadow + public abstract DamageSource source(ResourceKey resourceKey, @org.jetbrains.annotations.Nullable Entity entity, @org.jetbrains.annotations.Nullable Entity entity2); + public DamageSource melting; public DamageSource poison; @@ -47,4 +57,12 @@ public DamageSource melting() { public DamageSource bridge$melting() { return melting(); } + + public DamageSource explosion(@Nullable Entity entity, @Nullable Entity entity1, ResourceKey resourceKey) { + return this.source(resourceKey, entity, entity1); + } + + public DamageSource badRespawnPointExplosion(Vec3 vec3d, org.bukkit.block.BlockState blockState) { + return ((DamageSourceBridge) this.badRespawnPointExplosion(vec3d)).bridge$directBlockState(blockState); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HealOrHarmMobEffectMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HealOrHarmMobEffectMixin.java index 5856fc2c8..3d21083f4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HealOrHarmMobEffectMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HealOrHarmMobEffectMixin.java @@ -8,12 +8,13 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(targets = "net.minecraft.world.effect.HealOrHarmMobEffect") public class HealOrHarmMobEffectMixin { @Inject(method = "applyEffectTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;heal(F)V")) - private void arclight$healReason1(LivingEntity livingEntity, int amplifier, CallbackInfo ci) { + private void arclight$healReason1(LivingEntity livingEntity, int amplifier, CallbackInfoReturnable cir) { ((LivingEntityBridge) livingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.MAGIC); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HungerMobEffectMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HungerMobEffectMixin.java index b8588f31b..d636f16ea 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HungerMobEffectMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/HungerMobEffectMixin.java @@ -7,12 +7,13 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(targets = "net.minecraft.world.effect.HungerMobEffect") public class HungerMobEffectMixin { @Inject(method = "applyEffectTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")) - private void arclight$reason(LivingEntity livingEntity, int amplifier, CallbackInfo ci) { + private void arclight$reason(LivingEntity livingEntity, int amplifier, CallbackInfoReturnable cir) { ((PlayerEntityBridge) livingEntity).bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.HUNGER_EFFECT); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/MobEffectUtilMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/MobEffectUtilMixin.java index b9e0bb819..79bde6e2e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/MobEffectUtilMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/MobEffectUtilMixin.java @@ -2,27 +2,20 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.server.level.ServerLevel; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.Local; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffectUtil; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.List; @Mixin(MobEffectUtil.class) public class MobEffectUtilMixin { - @Inject(method = "addEffectToPlayersAround", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V")) - private static void arclight$pushCause(ServerLevel p_216947_, Entity p_216948_, Vec3 p_216949_, double p_216950_, MobEffectInstance p_216951_, int p_216952_, CallbackInfoReturnable> cir, - MobEffect effect, List players) { + @Decorate(method = "addEffectToPlayersAround", inject = true, at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V")) + private static void arclight$pushCause(@Local(ordinal = -1) List players) { var cause = ArclightCaptures.getEffectCause(); if (cause != null) { for (ServerPlayer player : players) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/RegenerationMobEffectMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/RegenerationMobEffectMixin.java index 8acdb4c20..9c1f8bf81 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/RegenerationMobEffectMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/RegenerationMobEffectMixin.java @@ -7,12 +7,13 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(targets = "net.minecraft.world.effect.RegenerationMobEffect") public class RegenerationMobEffectMixin { @Inject(method = "applyEffectTick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;heal(F)V")) - private void arclight$reason(LivingEntity livingEntity, int amplifier, CallbackInfo ci) { + private void arclight$reason(LivingEntity livingEntity, int amplifier, CallbackInfoReturnable cir) { ((LivingEntityBridge) livingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.MAGIC_REGEN); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/SaturationMobEffectMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/SaturationMobEffectMixin.java index 3071692e3..22bb779d8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/SaturationMobEffectMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/effect/SaturationMobEffectMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.effect; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; @@ -10,21 +12,19 @@ import org.bukkit.event.entity.FoodLevelChangeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(targets = "net.minecraft.world.effect.SaturationMobEffect") public class SaturationMobEffectMixin { - @Redirect(method = "applyEffectTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) - private void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, LivingEntity livingEntity, int amplifier) { + @Decorate(method = "applyEffectTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) + private void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, LivingEntity livingEntity, int amplifier) throws Throwable { Player playerEntity = ((Player) livingEntity); int oldFoodLevel = playerEntity.getFoodData().getFoodLevel(); FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(playerEntity, foodLevelIn + oldFoodLevel); if (!event.isCancelled()) { - playerEntity.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, foodSaturationModifier); + DecorationOps.callsite().invoke(foodStats, event.getFoodLevel() - oldFoodLevel, foodSaturationModifier); } ((ServerPlayer) playerEntity).connection.send(new ClientboundSetHealthPacket(((ServerPlayerEntityBridge) playerEntity).bridge$getBukkitEntity().getScaledHealth(), playerEntity.getFoodData().getFoodLevel(), playerEntity.getFoodData().getSaturationLevel())); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/AreaEffectCloudEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/AreaEffectCloudEntityMixin.java index ef4ad43a2..c63f4b8e8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/AreaEffectCloudEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/AreaEffectCloudEntityMixin.java @@ -1,227 +1,72 @@ package io.izzel.arclight.common.mixin.core.world.entity; -import com.google.common.collect.Lists; import io.izzel.arclight.common.bridge.core.entity.AreaEffectCloudEntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.AreaEffectCloudApplyEvent; +import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Mixin(AreaEffectCloud.class) public abstract class AreaEffectCloudEntityMixin extends EntityMixin implements AreaEffectCloudEntityBridge { // @formatter:off - @Shadow private boolean fixedColor; - @Shadow @Final private static EntityDataAccessor DATA_COLOR; - @Shadow public List effects; - @Shadow private Potion potion; - @Shadow public abstract void setPotion(Potion potionIn); - @Shadow public abstract boolean isWaiting(); - @Shadow public abstract float getRadius(); - @Shadow public abstract ParticleOptions getParticle(); - @Shadow public abstract int getColor(); - @Shadow public int waitTime; - @Shadow private int duration; - @Shadow protected abstract void setWaiting(boolean ignoreRadius); - @Shadow public float radiusPerTick; - @Shadow public abstract void setRadius(float radiusIn); @Shadow @Final private Map victims; - @Shadow public int reapplicationDelay; @Shadow @Nullable public abstract LivingEntity getOwner(); - @Shadow public float radiusOnUse; - @Shadow public int durationOnUse; // @formatter:on - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void tick() { - super.tick(); - boolean flag = this.isWaiting(); - float f = this.getRadius(); - if (this.level().isClientSide) { - if (flag && this.random.nextBoolean()) { - return; - } - - ParticleOptions particleoptions = this.getParticle(); - int i; - float f1; - if (flag) { - i = 2; - f1 = 0.2F; - } else { - i = Mth.ceil((float) Math.PI * f * f); - f1 = f; - } - - for (int j = 0; j < i; ++j) { - float f2 = this.random.nextFloat() * ((float) Math.PI * 2F); - float f3 = Mth.sqrt(this.random.nextFloat()) * f1; - double d0 = this.getX() + (double) (Mth.cos(f2) * f3); - double d2 = this.getY(); - double d4 = this.getZ() + (double) (Mth.sin(f2) * f3); - double d5; - double d6; - double d7; - if (particleoptions.getType() != ParticleTypes.ENTITY_EFFECT) { - if (flag) { - d5 = 0.0D; - d6 = 0.0D; - d7 = 0.0D; - } else { - d5 = (0.5D - this.random.nextDouble()) * 0.15D; - d6 = 0.01F; - d7 = (0.5D - this.random.nextDouble()) * 0.15D; - } - } else { - int k = flag && this.random.nextBoolean() ? 16777215 : this.getColor(); - d5 = (float) (k >> 16 & 255) / 255.0F; - d6 = (float) (k >> 8 & 255) / 255.0F; - d7 = (float) (k & 255) / 255.0F; - } - - this.level().addAlwaysVisibleParticle(particleoptions, d0, d2, d4, d5, d6, d7); - } - } else { - if (this.tickCount >= this.waitTime + this.duration) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); - this.discard(); - return; - } - - boolean flag1 = this.tickCount < this.waitTime; - if (flag != flag1) { - this.setWaiting(flag1); - } - - if (flag1) { - return; - } - - if (this.radiusPerTick != 0.0F) { - f += this.radiusPerTick; - if (f < 0.5F) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); - this.discard(); - return; - } - - this.setRadius(f); - } - - if (this.tickCount % 5 == 0) { - this.victims.entrySet().removeIf((p_146784_) -> { - return this.tickCount >= p_146784_.getValue(); - }); - List list = Lists.newArrayList(); - - for (MobEffectInstance mobeffectinstance : this.potion.getEffects()) { - list.add(new MobEffectInstance(mobeffectinstance.getEffect(), mobeffectinstance.getDuration() / 4, mobeffectinstance.getAmplifier(), mobeffectinstance.isAmbient(), mobeffectinstance.isVisible())); - } - - list.addAll(this.effects); - if (list.isEmpty()) { - this.victims.clear(); - } else { - List list1 = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox()); - if (!list1.isEmpty()) { - List entities = new java.util.ArrayList(); // CraftBukkit - for (LivingEntity livingentity : list1) { - if (!this.victims.containsKey(livingentity) && livingentity.isAffectedByPotions()) { - double d8 = livingentity.getX() - this.getX(); - double d1 = livingentity.getZ() - this.getZ(); - double d3 = d8 * d8 + d1 * d1; - if (d3 <= (double) (f * f)) { - entities.add(((LivingEntityBridge) livingentity).bridge$getBukkitEntity()); - } - } - } - AreaEffectCloudApplyEvent event = CraftEventFactory.callAreaEffectCloudApplyEvent((AreaEffectCloud) (Object) this, entities); - if (!event.isCancelled()) { - for (org.bukkit.entity.LivingEntity entity : event.getAffectedEntities()) { - if (entity instanceof CraftLivingEntity) { - net.minecraft.world.entity.LivingEntity livingentity = ((CraftLivingEntity) entity).getHandle(); - - this.victims.put(livingentity, this.tickCount + this.reapplicationDelay); - - for (MobEffectInstance mobeffectinstance1 : list) { - if (mobeffectinstance1.getEffect().isInstantenous()) { - mobeffectinstance1.getEffect().applyInstantenousEffect((AreaEffectCloud) (Object) this, this.getOwner(), livingentity, mobeffectinstance1.getAmplifier(), 0.5D); - } else { - livingentity.addEffect(new MobEffectInstance(mobeffectinstance1), (AreaEffectCloud) (Object) this); - } - } - - if (this.radiusOnUse != 0.0F) { - f += this.radiusOnUse; - if (f < 0.5F) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); - this.discard(); - return; - } - - this.setRadius(f); - } - - if (this.durationOnUse != 0) { - this.duration += this.durationOnUse; - if (this.duration <= 0) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); - this.discard(); - return; - } - } - } - } - } - } - } - } + @SuppressWarnings("unchecked") + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;getEntitiesOfClass(Ljava/lang/Class;Lnet/minecraft/world/phys/AABB;)Ljava/util/List;")) + private List arclight$effectApply(Level instance, Class cl, AABB aabb, + @Local(ordinal = 0) float radius, + @Local(ordinal = -1) List effects) throws Throwable { + var entities = (List) DecorationOps.callsite().invoke(instance, cl, aabb); + var affected = entities.stream().filter(it -> !this.victims.containsKey(it) && it.isAffectedByPotions()) + .filter(it -> effects.stream().anyMatch(it::canBeAffected)) + .filter(it -> { + double d3 = it.getX() - this.getX(); + double d4 = it.getZ() - this.getZ(); + double d5 = d3 * d3 + d4 * d4; + return d5 <= (double) (radius * radius); + }) + .map(it -> (org.bukkit.entity.LivingEntity) it.bridge$getBukkitEntity()) + .toList(); + var event = CraftEventFactory.callAreaEffectCloudApplyEvent((AreaEffectCloud) (Object) this, affected); + if (!event.isCancelled()) { + return event.getAffectedEntities().stream().map(it -> ((CraftLivingEntity) it).getHandle()).collect(Collectors.toCollection(ArrayList::new)); } - - } - - - public void refreshEffects() { - if (!this.fixedColor) { - this.getEntityData().set(DATA_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); - } - } - - public String getPotionType() { - return BuiltInRegistries.POTION.getKey(this.potion).toString(); + return new ArrayList<>(); } - public void setPotionType(final String string) { - this.setPotion(BuiltInRegistries.POTION.get(new ResourceLocation(string))); + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$effectCause(LivingEntity instance, MobEffectInstance mobEffectInstance, Entity entity) throws Throwable { + ((LivingEntityBridge) instance).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.AREA_EFFECT_CLOUD); + return (boolean) DecorationOps.callsite().invoke(instance, mobEffectInstance, entity); } - @Override - public void bridge$refreshEffects() { - refreshEffects(); + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/AreaEffectCloud;discard()V")) + private void arclight$discard(CallbackInfo ci) { + this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java index d6a84b18f..c8e5783d5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.entity; import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; import io.izzel.arclight.common.bridge.core.command.ICommandSourceBridge; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.InternalEntityBridge; @@ -9,17 +8,20 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; import io.izzel.arclight.common.bridge.core.util.DamageSourceBridge; -import io.izzel.arclight.common.bridge.core.world.TeleporterBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; import io.izzel.arclight.common.mod.server.BukkitRegistry; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.BlockUtil; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.Holder; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; @@ -30,13 +32,15 @@ import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSources; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Leashable; 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.RelativeMovement; @@ -45,16 +49,9 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.border.WorldBorder; -import net.minecraft.world.level.dimension.DimensionType; -import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.levelgen.Heightmap; import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.portal.PortalInfo; -import net.minecraft.world.level.portal.PortalShape; +import net.minecraft.world.level.portal.DimensionTransition; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; @@ -70,16 +67,21 @@ import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.event.CraftPortalEvent; +import org.bukkit.craftbukkit.v.util.CraftLocation; import org.bukkit.entity.Hanging; import org.bukkit.entity.Vehicle; import org.bukkit.event.entity.EntityAirChangeEvent; import org.bukkit.event.entity.EntityCombustByBlockEvent; import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityCombustEvent; +import org.bukkit.event.entity.EntityDismountEvent; import org.bukkit.event.entity.EntityDropItemEvent; +import org.bukkit.event.entity.EntityMountEvent; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.entity.EntityPoseChangeEvent; import org.bukkit.event.entity.EntityRemoveEvent; +import org.bukkit.event.entity.EntityTeleportEvent; +import org.bukkit.event.entity.EntityUnleashEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; @@ -89,13 +91,11 @@ import org.bukkit.projectiles.ProjectileSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -103,7 +103,6 @@ import javax.annotation.Nullable; import java.util.List; -import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -123,10 +122,8 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public int remainingFireTicks; @Shadow public abstract Pose getPose(); @Shadow public abstract String getScoreboardName(); - @Shadow protected abstract void handleNetherPortal(); @Shadow public abstract boolean fireImmune(); - @Shadow public abstract boolean hurt(DamageSource source, float amount); - @Shadow public abstract void setSecondsOnFire(int seconds); + @Shadow public boolean hurt(DamageSource source, float amount) { return false; } @Shadow public boolean horizontalCollision; @Shadow protected abstract Vec3 collide(Vec3 vec); @Shadow public int tickCount; @@ -185,7 +182,6 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract void moveTo(double x, double y, double z, float yaw, float pitch); @Shadow public abstract int getId(); @Shadow @Nullable public abstract Component getCustomName(); - @Shadow public abstract void doEnchantDamageEffects(LivingEntity entityLivingBaseIn, Entity entityIn); @Shadow public abstract boolean isPassengerOfSameVehicle(Entity entityIn); @Shadow public abstract boolean isInvulnerable(); @Shadow public abstract double getX(); @@ -195,7 +191,6 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract Vec3 position(); @Shadow public abstract boolean isPushable(); @Shadow protected abstract void removeAfterChangingDimensions(); - @Shadow protected BlockPos portalEntrancePos; @Shadow protected abstract Vec3 getRelativePortalPosition(Direction.Axis axis, BlockUtil.FoundRectangle result); @Shadow public abstract EntityDimensions getDimensions(Pose poseIn); @Shadow protected abstract boolean updateInWaterStateAndDoFluidPushing(); @@ -210,12 +205,10 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract void discard(); @Shadow public abstract void unsetRemoved(); @Shadow public abstract double getY(double p_20228_); - @Shadow public abstract void gameEvent(GameEvent p_146853_, @org.jetbrains.annotations.Nullable Entity p_146854_); @Shadow public abstract void setTicksFrozen(int p_146918_); @Shadow public abstract void setSharedFlagOnFire(boolean p_146869_); @Shadow public abstract int getMaxAirSupply(); @Shadow public abstract int getAirSupply(); - @Shadow public abstract void gameEvent(GameEvent p_146851_); @Shadow protected abstract SoundEvent getSwimSound(); @Shadow protected abstract SoundEvent getSwimSplashSound(); @Shadow protected abstract SoundEvent getSwimHighSpeedSplashSound(); @@ -234,9 +227,17 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract CompoundTag saveWithoutId(CompoundTag p_20241_); @Shadow public abstract boolean saveAsPassenger(CompoundTag p_20087_); @Shadow public abstract Vec3 getEyePosition(); + @Shadow public abstract void gameEvent(Holder holder); + @Shadow public abstract void gameEvent(Holder holder, @org.jetbrains.annotations.Nullable Entity entity); + @Shadow protected abstract void handlePortal(); + @Shadow protected abstract void applyGravity(); + @Shadow public abstract void igniteForSeconds(float f); + @Shadow public abstract boolean onGround(); // @formatter:on + @Shadow private Level level; private static final int CURRENT_LEVEL = 2; + public boolean forceDrops; public boolean persist = true; public boolean generation; public boolean valid; @@ -278,6 +279,21 @@ public CraftEntity getBukkitEntity() { return bukkitEntity; } + @Override + public boolean bridge$pluginRemoved() { + return pluginRemoved; + } + + @Override + public boolean bridge$isForceDrops() { + return forceDrops; + } + + @Override + public void bridge$setForceDrops(boolean b) { + this.forceDrops = b; + } + public float getBukkitYaw() { return getYRot(); } @@ -458,7 +474,7 @@ public boolean isValid() { public void postTick() { // No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle if (!((Object) this instanceof ServerPlayer)) { - this.handleNetherPortal(); + this.handlePortal(); } } @@ -467,17 +483,19 @@ public void postTick() { postTick(); } - @Redirect(method = "baseTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleNetherPortal()V")) - public void arclight$baseTick$moveToPostTick(Entity entity) { - if ((Object) this instanceof ServerPlayer) this.handleNetherPortal();// CraftBukkit - // Moved up to postTick + @Decorate(method = "baseTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handlePortal()V")) + private void arclight$baseTick$moveToPostTick(Entity entity) throws Throwable { + if ((Object) this instanceof ServerPlayer) { + DecorationOps.callsite().invoke(entity);// CraftBukkit - // Moved up to postTick + } } - @Redirect(method = "updateFluidHeightAndDoFluidPushing", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FluidState;getFlow(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/Vec3;")) - private Vec3 arclight$setLava(FluidState instance, BlockGetter level, BlockPos pos) { + @Decorate(method = "updateFluidHeightAndDoFluidPushing", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/material/FluidState;getFlow(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 arclight$setLava(FluidState instance, BlockGetter level, BlockPos pos) throws Throwable { if (instance.getType().is(FluidTags.LAVA)) { lastLavaContact = pos.immutable(); } - return instance.getFlow(level, pos); + return (Vec3) DecorationOps.callsite().invoke(instance, level, pos); } @Override @@ -485,39 +503,39 @@ public void postTick() { this.lastLavaContact = pos; } - @Redirect(method = "baseTick", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/entity/Entity;isInLava()Z")) - private boolean arclight$resetLava(Entity instance) { - var ret = instance.isInLava(); + @Decorate(method = "baseTick", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/entity/Entity;isInLava()Z")) + private boolean arclight$resetLava(Entity instance) throws Throwable { + var ret = (boolean) DecorationOps.callsite().invoke(instance); if (!ret) { this.lastLavaContact = null; } return ret; } - @Redirect(method = "lavaHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - public void arclight$setOnFireFromLava$bukkitEvent(Entity entity, int seconds) { + @Decorate(method = "lavaHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + public void arclight$setOnFireFromLava$bukkitEvent(Entity instance, float f) throws Throwable { if ((Object) this instanceof LivingEntity && remainingFireTicks <= 0) { var damager = (lastLavaContact == null) ? null : CraftBlock.at(level(), lastLavaContact); var damagee = this.getBukkitEntity(); EntityCombustEvent combustEvent = new EntityCombustByBlockEvent(damager, damagee, 15); Bukkit.getPluginManager().callEvent(combustEvent); - if (!combustEvent.isCancelled()) { - this.setSecondsOnFire(combustEvent.getDuration()); + if (combustEvent.isCancelled()) { + return; } - } else { - // This will be called every single tick the entity is in lava, so don't throw an event - this.setSecondsOnFire(15); + f = combustEvent.getDuration(); } + DecorationOps.callsite().invoke(instance, f); } - @Redirect(method = "lavaHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;lava()Lnet/minecraft/world/damagesource/DamageSource;")) - private DamageSource arclight$resetBlockDamage(DamageSources instance) { + @Decorate(method = "lavaHurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;lava()Lnet/minecraft/world/damagesource/DamageSource;")) + private DamageSource arclight$resetBlockDamage(DamageSources instance) throws Throwable { var damager = (lastLavaContact == null) ? null : CraftBlock.at(level(), lastLavaContact); - return ((DamageSourceBridge) instance.lava()).bridge$directBlock(damager); + var damageSource = (DamageSource) DecorationOps.callsite().invoke(instance); + return ((DamageSourceBridge) damageSource).bridge$directBlock(damager); } - public void setSecondsOnFire(int seconds, boolean callEvent) { + public void setSecondsOnFire(float seconds, boolean callEvent) { if (callEvent) { EntityCombustEvent event = new EntityCombustEvent(this.getBukkitEntity(), seconds); Bukkit.getPluginManager().callEvent(event); @@ -526,11 +544,11 @@ public void setSecondsOnFire(int seconds, boolean callEvent) { } seconds = event.getDuration(); } - this.setSecondsOnFire(seconds); + this.igniteForSeconds(seconds); } @Override - public void bridge$setOnFire(int tick, boolean callEvent) { + public void bridge$setOnFire(float tick, boolean callEvent) { setSecondsOnFire(tick, callEvent); } @@ -549,7 +567,7 @@ public void setSecondsOnFire(int seconds, boolean callEvent) { slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;updateEntityAfterFallOn(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/world/entity/Entity;)V"))) private void arclight$move$blockCollide(MoverType typeIn, Vec3 pos, CallbackInfo ci) { if (horizontalCollision && this.bridge$getBukkitEntity() instanceof Vehicle vehicle) { - org.bukkit.block.Block block = ((WorldBridge) this.level()).bridge$getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); + org.bukkit.block.Block block = this.level().bridge$getWorld().getBlockAt(Mth.floor(this.getX()), Mth.floor(this.getY()), Mth.floor(this.getZ())); Vec3 vec3d = this.collide(pos); if (pos.x > vec3d.x) { block = block.getRelative(BlockFace.EAST); @@ -735,136 +753,97 @@ private static boolean isLevelAtLeast(CompoundTag tag, int level) { } } - @Redirect(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;addPassenger(Lnet/minecraft/world/entity/Entity;)V")) - private void arclight$startRiding(Entity entity, Entity pPassenger) { - if (!((EntityBridge) entity).bridge$addPassenger(pPassenger)) { - this.vehicle = null; + @Inject(method = "interact", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;dropLeash(ZZ)V")) + private void arclight$unleashEvent(Player player, InteractionHand interactionHand, CallbackInfoReturnable cir) { + if (CraftEventFactory.callPlayerUnleashEntityEvent((Entity) (Object) this, player, interactionHand).isCancelled()) { + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket((Entity) (Object) this, ((Leashable) this).getLeashHolder())); + cir.setReturnValue(InteractionResult.PASS); } } - @Redirect(method = "removeVehicle", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;removePassenger(Lnet/minecraft/world/entity/Entity;)V")) - private void arclight$stopRiding(Entity entity, Entity passenger) { - if (!((EntityBridge) entity).bridge$removePassenger(passenger)) { - this.vehicle = entity; + @Inject(method = "interact", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;setLeashedTo(Lnet/minecraft/world/entity/Entity;Z)V")) + private void arclight$leashEvent(Player player, InteractionHand interactionHand, CallbackInfoReturnable cir) { + if (CraftEventFactory.callPlayerLeashEntityEvent((Entity) (Object) this, player, player, interactionHand).isCancelled()) { + ((ServerPlayerEntityBridge) player).bridge$resendItemInHands(); // SPIGOT-7615: Resend to fix client desync with used item + ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket((Entity) (Object) this, ((Leashable) this).getLeashHolder())); + cir.setReturnValue(InteractionResult.PASS); } } - @Override - public List bridge$getPassengers() { - return passengers; - } - - @Override - public boolean bridge$addPassenger(Entity entity) { - return addPassenger(entity); - } - - public boolean addPassenger(Entity entity) { - if (entity.getVehicle() != (Object) this) { - throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)"); - } else { - // CraftBukkit start - com.google.common.base.Preconditions.checkState(!((EntityBridge) entity).bridge$getPassengers().contains(this), "Circular entity riding! %s %s", this, entity); - - CraftEntity craft = (CraftEntity) ((EntityBridge) entity).bridge$getBukkitEntity().getVehicle(); - Entity orig = craft == null ? null : craft.getHandle(); - if (getBukkitEntity() instanceof Vehicle && ((EntityBridge) entity).bridge$getBukkitEntity() instanceof org.bukkit.entity.LivingEntity) { - VehicleEnterEvent event = new VehicleEnterEvent( - (Vehicle) getBukkitEntity(), - ((EntityBridge) entity).bridge$getBukkitEntity() - ); - // Suppress during worldgen - if (this.valid) { - Bukkit.getPluginManager().callEvent(event); - } - CraftEntity craftn = (CraftEntity) ((EntityBridge) entity).bridge$getBukkitEntity().getVehicle(); - Entity n = craftn == null ? null : craftn.getHandle(); - if (event.isCancelled() || n != orig) { - return false; - } - } - var event = new org.bukkit.event.entity.EntityMountEvent(((EntityBridge) entity).bridge$getBukkitEntity(), this.getBukkitEntity()); - // Suppress during worldgen + @Inject(method = "startRiding(Lnet/minecraft/world/entity/Entity;Z)Z", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;isPassenger()Z")) + private void arclight$startRiding(Entity entity, boolean bl, CallbackInfoReturnable cir) { + if (entity.bridge$getBukkitEntity() instanceof Vehicle v && this.getBukkitEntity() instanceof org.bukkit.entity.LivingEntity) { + VehicleEnterEvent event = new VehicleEnterEvent(v, this.getBukkitEntity()); if (this.valid) { Bukkit.getPluginManager().callEvent(event); } if (event.isCancelled()) { - return false; - } - // CraftBukkit end - if (this.passengers.isEmpty()) { - this.passengers = ImmutableList.of(entity); - } else { - List list = Lists.newArrayList(this.passengers); - - if (!this.level().isClientSide && entity instanceof Player && !(this.getFirstPassenger() instanceof Player)) { - list.add(0, entity); - } else { - list.add(entity); - } - - this.passengers = ImmutableList.copyOf(list); + cir.setReturnValue(false); + return; } + } - this.gameEvent(GameEvent.ENTITY_MOUNT, entity); + EntityMountEvent event = new EntityMountEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity()); + if (this.valid) { + Bukkit.getPluginManager().callEvent(event); + } + if (event.isCancelled()) { + cir.setReturnValue(false); } - return true; // CraftBukkit } - @Override - public boolean bridge$removePassenger(Entity entity) { - return removePassenger(entity); + private transient boolean arclight$dismountCancelled = false; + + @Inject(method = "removeVehicle", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Entity;removePassenger(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$stopRiding(CallbackInfo ci, Entity entity) { + if (arclight$dismountCancelled) { + this.vehicle = entity; + } + arclight$dismountCancelled = false; } - public boolean removePassenger(Entity entity) { // CraftBukkit + @Inject(method = "removePassenger", cancellable = true, at = @At("HEAD")) + private void arclight$dismountEvent(Entity entity, CallbackInfo ci) { if (entity.getVehicle() == (Object) this) { - throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)"); - } else { - // CraftBukkit start - CraftEntity craft = (CraftEntity) ((EntityBridge) entity).bridge$getBukkitEntity().getVehicle(); - Entity orig = craft == null ? null : craft.getHandle(); - if (getBukkitEntity() instanceof Vehicle && ((EntityBridge) entity).bridge$getBukkitEntity() instanceof org.bukkit.entity.LivingEntity) { - VehicleExitEvent event = new VehicleExitEvent( - (Vehicle) getBukkitEntity(), - (org.bukkit.entity.LivingEntity) ((EntityBridge) entity).bridge$getBukkitEntity() - ); - // Suppress during worldgen - if (this.valid) { - Bukkit.getPluginManager().callEvent(event); - } - CraftEntity craftn = (CraftEntity) ((EntityBridge) entity).bridge$getBukkitEntity().getVehicle(); - Entity n = craftn == null ? null : craftn.getHandle(); - if (event.isCancelled() || n != orig) { - return false; - } - } - var event = new org.bukkit.event.entity.EntityDismountEvent(((EntityBridge) entity).bridge$getBukkitEntity(), this.getBukkitEntity()); - // Suppress during worldgen + return; + } + CraftEntity craft = (CraftEntity) entity.bridge$getBukkitEntity().getVehicle(); + Entity orig = craft == null ? null : craft.getHandle(); + if (getBukkitEntity() instanceof Vehicle && entity.bridge$getBukkitEntity() instanceof org.bukkit.entity.LivingEntity) { + VehicleExitEvent event = new VehicleExitEvent( + (Vehicle) getBukkitEntity(), + (org.bukkit.entity.LivingEntity) entity.bridge$getBukkitEntity() + ); if (this.valid) { Bukkit.getPluginManager().callEvent(event); } - if (event.isCancelled()) { - return false; - } - // CraftBukkit end - if (this.passengers.size() == 1 && this.passengers.get(0) == entity) { - this.passengers = ImmutableList.of(); - } else { - this.passengers = this.passengers.stream().filter((entity1) -> entity1 != entity) - .collect(ImmutableList.toImmutableList()); + CraftEntity craftn = (CraftEntity) entity.bridge$getBukkitEntity().getVehicle(); + Entity n = craftn == null ? null : craftn.getHandle(); + if (event.isCancelled() || n != orig) { + ci.cancel(); + arclight$dismountCancelled = true; + return; } + } - entity.boardingCooldown = 60; - this.gameEvent(GameEvent.ENTITY_DISMOUNT, entity); + EntityDismountEvent event = new EntityDismountEvent(entity.bridge$getBukkitEntity(), this.getBukkitEntity()); + if (this.valid) { + Bukkit.getPluginManager().callEvent(event); + } + if (event.isCancelled()) { + ci.cancel(); + arclight$dismountCancelled = true; } - return true; // CraftBukkit } - @Inject(method = "handleNetherPortal", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;changeDimension(Lnet/minecraft/server/level/ServerLevel;)Lnet/minecraft/world/entity/Entity;")) - public void arclight$changeDimension(CallbackInfo ci) { - if (this instanceof ServerPlayerEntityBridge) { - ((ServerPlayerEntityBridge) this).bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); - } + @Override + public List bridge$getPassengers() { + return passengers; + } + + @Decorate(method = "handlePortal", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;canChangeDimensions(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/Level;)Z")) + private boolean arclight$changeDimension(Entity instance, Level level, Level level2) throws Throwable { + return (boolean) DecorationOps.callsite().invoke(instance, level, level2) || this instanceof ServerPlayerEntityBridge; } @Inject(method = "setSwimming", cancellable = true, at = @At(value = "HEAD")) @@ -895,22 +874,23 @@ public boolean removePassenger(Entity entity) { // CraftBukkit // CraftBukkit end } - @Redirect(method = "thunderHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - public void arclight$onStruckByLightning$EntityCombustByEntityEvent0(Entity entity, int seconds) { + @Decorate(method = "thunderHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$onStruckByLightning$EntityCombustByEntityEvent0(Entity entity, float f) throws Throwable { final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); - final org.bukkit.entity.Entity stormBukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); + final org.bukkit.entity.Entity stormBukkitEntity = entity.bridge$getBukkitEntity(); final PluginManager pluginManager = Bukkit.getPluginManager(); // CraftBukkit start - Call a combust event when lightning strikes EntityCombustByEntityEvent entityCombustEvent = new EntityCombustByEntityEvent(stormBukkitEntity, thisBukkitEntity, 8); pluginManager.callEvent(entityCombustEvent); - if (!entityCombustEvent.isCancelled()) { - this.setSecondsOnFire(entityCombustEvent.getDuration()); + if (entityCombustEvent.isCancelled()) { + return; } + DecorationOps.callsite().invoke(entity, entityCombustEvent.getDuration()); // CraftBukkit end } - @Redirect(method = "thunderHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) - public boolean arclight$onStruckByLightning$EntityCombustByEntityEvent1(Entity entity, DamageSource source, float amount) { + @Decorate(method = "thunderHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private boolean arclight$onStruckByLightning$EntityCombustByEntityEvent1(Entity entity, DamageSource source, float amount) throws Throwable { final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); final org.bukkit.entity.Entity stormBukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); final PluginManager pluginManager = Bukkit.getPluginManager(); @@ -926,10 +906,7 @@ public boolean removePassenger(Entity entity) { // CraftBukkit if (this.fireImmune()) { return false; } - if (!this.hurt(((DamageSourceBridge) this.damageSources().lightningBolt()).bridge$customCausingEntity(entity), amount)) { - return false; - } - return true; + return (boolean) DecorationOps.callsite().invoke(entity, ((DamageSourceBridge) source).bridge$customCausingEntity(entity), amount); } @Override @@ -942,172 +919,54 @@ public boolean removePassenger(Entity entity) { // CraftBukkit return this.boardingCooldown; } - private transient Vec3 arclight$tpPos; - - public Entity teleportTo(ServerLevel world, Vec3 blockPos) { - arclight$tpPos = blockPos; - return changeDimension(world); - } - - @Override - public Vec3 bridge$getLastTpPos() { - try { - return arclight$tpPos; - } finally { - arclight$tpPos = null; - } - } - public boolean teleportTo(ServerLevel worldserver, double d0, double d1, double d2, Set set, float f, float f1, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { return this.teleportTo(worldserver, d0, d1, d2, set, f, f1); } - @Override - public Entity bridge$teleportTo(ServerLevel world, Vec3 blockPos) { - return teleportTo(world, blockPos); - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @org.jetbrains.annotations.Nullable - public Entity changeDimension(ServerLevel serverLevel) { + @Decorate(method = "changeDimension", inject = true, at = @At("HEAD")) + private void arclight$changeDim(DimensionTransition dimensionTransition) throws Throwable { if (this.level() instanceof ServerLevel && !this.isRemoved()) { - this.level().getProfiler().push("changeDimension"); - //this.unRide(); - if (serverLevel == null) { - return null; - } - this.level().getProfiler().push("reposition"); - var bukkitPos = bridge$getLastTpPos(); - PortalInfo portalInfo = bukkitPos == null ? this.findDimensionEntryPoint(serverLevel) : - new PortalInfo(new Vec3(bukkitPos.x(), bukkitPos.y(), bukkitPos.z()), Vec3.ZERO, this.yRot, this.xRot); - if (portalInfo == null) { - return null; - } else { - ServerLevel world = ((PortalInfoBridge) portalInfo).bridge$getWorld() == null ? serverLevel : ((PortalInfoBridge) portalInfo).bridge$getWorld(); - if (world == this.level()) { - this.moveTo(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, this.getXRot()); - this.setDeltaMovement(portalInfo.speed); - return (Entity) (Object) this; - } - this.unRide(); - this.level().getProfiler().popPush("reloading"); - Entity entity = this.getType().create(serverLevel); - if (entity != null) { - entity.restoreFrom((Entity) (Object) this); - entity.moveTo(portalInfo.pos.x, portalInfo.pos.y, portalInfo.pos.z, portalInfo.yRot, entity.getXRot()); - entity.setDeltaMovement(portalInfo.speed); - if (this.bridge$isInWorld()) { - world.addDuringTeleport(entity); - if (((WorldBridge) world).bridge$getTypeKey() == LevelStem.END && Level.END != null /* fabric dimensions v1 */) { - ArclightCaptures.captureEndPortalEntity((Entity) (Object) this, true); - ServerLevel.makeObsidianPlatform(world); - } - } - } - - this.removeAfterChangingDimensions(); - this.level().getProfiler().pop(); - ((ServerLevel) this.level()).resetEmptyTime(); - serverLevel.resetEmptyTime(); - this.level().getProfiler().pop(); - return entity; + Location to = new Location(dimensionTransition.newLevel().bridge$getWorld(), dimensionTransition.pos().x, dimensionTransition.pos().y, dimensionTransition.pos().z, dimensionTransition.yRot(), dimensionTransition.xRot()); + EntityTeleportEvent teleEvent = CraftEventFactory.callEntityTeleportEvent((Entity) (Object) this, to); + if (teleEvent.isCancelled()) { + DecorationOps.cancel().invoke((Entity) null); + return; } - } else { - return null; + to = teleEvent.getTo(); + var cause = ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$getTeleportCause(); + dimensionTransition = new DimensionTransition(((CraftWorld) to.getWorld()).getHandle(), CraftLocation.toVec3D(to), dimensionTransition.speed(), to.getYaw(), to.getPitch(), dimensionTransition.missingRespawnBlock(), dimensionTransition.postDimensionTransition()); + ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$setTeleportCause(cause); } } - @Redirect(method = "teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FF)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addDuringTeleport(Lnet/minecraft/world/entity/Entity;)V")) - private void arclight$skipIfNotInWorld(ServerLevel instance, Entity entity) { + @Decorate(method = "changeDimension", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addDuringTeleport(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$skipTeleportIfNotInWorld(ServerLevel instance, Entity entity) throws Throwable { if (this.inWorld) { - instance.addDuringTeleport(entity); + DecorationOps.callsite().invoke(instance, entity); } } - @Inject(method = "restoreFrom", at = @At("HEAD")) - private void arclight$forwardHandle(Entity entityIn, CallbackInfo ci) { - ((InternalEntityBridge) entityIn).internal$getBukkitEntity().setHandle((Entity) (Object) this); - ((EntityBridge) this).bridge$setBukkitEntity(((InternalEntityBridge) entityIn).internal$getBukkitEntity()); - if (entityIn instanceof Mob) { - ((Mob) entityIn).dropLeash(true, false); - } + @Inject(method = "removeAfterChangingDimensions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;dropLeash(ZZ)V")) + private void arclight$dropLeashChangeDim(CallbackInfo ci) { + Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); } - /** - * @author IzzelAliz - * @reason - */ - @Nullable - @Overwrite - protected PortalInfo findDimensionEntryPoint(ServerLevel world) { - if (world == null) { - return null; + @Decorate(method = "teleportTo(Lnet/minecraft/server/level/ServerLevel;DDDLjava/util/Set;FF)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addDuringTeleport(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$skipIfNotInWorld(ServerLevel instance, Entity entity) throws Throwable { + if (this.inWorld) { + DecorationOps.callsite().invoke(instance, entity); } - boolean flag = ((WorldBridge) this.level()).bridge$getTypeKey() == LevelStem.END && ((WorldBridge) world).bridge$getTypeKey() == LevelStem.OVERWORLD; - boolean flag1 = ((WorldBridge) world).bridge$getTypeKey() == LevelStem.END; - if (!flag && !flag1) { - boolean flag2 = ((WorldBridge) world).bridge$getTypeKey() == LevelStem.NETHER; - if (this.level().dimension() != Level.NETHER && !flag2) { - return null; - } else { - WorldBorder worldborder = world.getWorldBorder(); - double d0 = DimensionType.getTeleportationScale(this.level().dimensionType(), world.dimensionType()); - BlockPos blockpos1 = worldborder.clampToBounds(this.getX() * d0, this.getY(), this.getZ() * d0); - - CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, new Vec3(blockpos1.getX(), blockpos1.getY(), blockpos1.getZ()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); - if (event == null) { - return null; - } - ServerLevel worldFinal = world = ((CraftWorld) event.getTo().getWorld()).getHandle(); - blockpos1 = worldFinal.getWorldBorder().clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); - - return this.getExitPortal(world, blockpos1, flag2, worldborder, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((result) -> { - BlockState blockstate = this.level().getBlockState(this.portalEntrancePos); - Direction.Axis direction$axis; - Vec3 vector3d; - if (blockstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { - direction$axis = blockstate.getValue(BlockStateProperties.HORIZONTAL_AXIS); - BlockUtil.FoundRectangle teleportationrepositioner$result = BlockUtil.getLargestRectangleAround(this.portalEntrancePos, direction$axis, 21, Direction.Axis.Y, 21, (pos) -> { - return this.level().getBlockState(pos) == blockstate; - }); - vector3d = this.getRelativePortalPosition(direction$axis, teleportationrepositioner$result); - } else { - direction$axis = Direction.Axis.X; - vector3d = new Vec3(0.5D, 0.0D, 0.0D); - } - - ArclightCaptures.captureCraftPortalEvent(event); - return PortalShape.createPortalInfo(worldFinal, result, direction$axis, vector3d, (Entity) (Object) this, this.getDeltaMovement(), this.getYRot(), this.getXRot()); - }).orElse(null); - } - } else { - BlockPos blockpos; - if (flag1) { - blockpos = ServerLevel.END_SPAWN_POINT; - } else { - blockpos = world.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, world.getSharedSpawnPos()); - } - - CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, new Vec3(blockpos.getX() + 0.5D, blockpos.getY(), blockpos.getZ() + 0.5D), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); - if (event == null) { - return null; - } + } - PortalInfo portalInfo = new PortalInfo(new Vec3(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()), this.getDeltaMovement(), this.getYRot(), this.getXRot()); - ((PortalInfoBridge) portalInfo).bridge$setWorld(((CraftWorld) event.getTo().getWorld()).getHandle()); - ((PortalInfoBridge) portalInfo).bridge$setPortalEventInfo(event); - return portalInfo; - } + @Inject(method = "restoreFrom", at = @At("HEAD")) + private void arclight$forwardHandle(Entity entityIn, CallbackInfo ci) { + ((InternalEntityBridge) entityIn).internal$getBukkitEntity().setHandle((Entity) (Object) this); + ((EntityBridge) this).bridge$setBukkitEntity(((InternalEntityBridge) entityIn).internal$getBukkitEntity()); } - protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldServer, Vec3 exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { - CraftEntity bukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); + public CraftPortalEvent callPortalEvent(Entity entity, Location exit, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { + CraftEntity bukkitEntity = entity.bridge$getBukkitEntity(); Location enter = bukkitEntity.getLocation(); - Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.x(), exitPosition.y(), exitPosition.z()); EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { @@ -1116,7 +975,12 @@ protected CraftPortalEvent callPortalEvent(Entity entity, ServerLevel exitWorldS return new CraftPortalEvent(event); } - protected Optional getExitPortal(ServerLevel serverWorld, BlockPos pos, boolean flag, WorldBorder worldborder, int searchRadius, boolean canCreatePortal, int createRadius) { - return ((TeleporterBridge) serverWorld.getPortalForcer()).bridge$findPortal(pos, worldborder, searchRadius); + @Override + public CraftPortalEvent bridge$callPortalEvent(Entity entity, Location exit, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { + return this.callPortalEvent(entity, exit, cause, searchRadius, creationRadius); + } + + public void refreshEntityData(ServerPlayer to) { + ((SynchedEntityDataBridge) this.entityData).bridge$refresh(to); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityTypeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityTypeMixin.java index e20e8cc52..c2982e3b3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityTypeMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityTypeMixin.java @@ -3,7 +3,6 @@ import io.izzel.arclight.common.bridge.core.entity.EntityTypeBridge; import io.izzel.arclight.common.bridge.core.world.IWorldWriterBridge; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -26,7 +25,7 @@ public abstract class EntityTypeMixin implements EntityTypeBridge { // @formatter:off - @Shadow @Nullable public abstract T create(ServerLevel p_262637_, @org.jetbrains.annotations.Nullable CompoundTag p_262687_, @org.jetbrains.annotations.Nullable Consumer p_262629_, BlockPos p_262595_, MobSpawnType p_262666_, boolean p_262685_, boolean p_262588_); + @Shadow @Nullable public abstract T create(ServerLevel p_262637_, @org.jetbrains.annotations.Nullable Consumer p_262629_, BlockPos p_262595_, MobSpawnType p_262666_, boolean p_262685_, boolean p_262588_); // @formatter:on @Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;", @@ -38,21 +37,21 @@ public abstract class EntityTypeMixin implements EntityTypeBri } } - @Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/nbt/CompoundTag;Ljava/util/function/Consumer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;", + @Inject(method = "spawn(Lnet/minecraft/server/level/ServerLevel;Ljava/util/function/Consumer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/MobSpawnType;ZZ)Lnet/minecraft/world/entity/Entity;", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V"))) - private void arclight$returnIfSuccess(ServerLevel p_262704_, CompoundTag p_262603_, Consumer p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_, CallbackInfoReturnable cir, T t) { + private void arclight$returnIfSuccess(ServerLevel serverLevel, Consumer consumer, BlockPos blockPos, MobSpawnType mobSpawnType, boolean bl, boolean bl2, CallbackInfoReturnable cir, T t) { if (t != null) { cir.setReturnValue(t.isRemoved() ? null : t); } } public T spawn(ServerLevel p_262634_, BlockPos p_262707_, MobSpawnType p_262597_, CreatureSpawnEvent.SpawnReason spawnReason) { - return this.spawn(p_262634_, null, null, p_262707_, p_262597_, false, false, spawnReason); + return this.spawn(p_262634_, null, p_262707_, p_262597_, false, false, spawnReason); } - public T spawn(ServerLevel p_262704_, @Nullable CompoundTag p_262603_, @Nullable Consumer p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_, CreatureSpawnEvent.SpawnReason spawnReason) { - T t = this.create(p_262704_, p_262603_, p_262621_, p_262672_, p_262644_, p_262690_, p_262590_); + public T spawn(ServerLevel p_262704_, @Nullable Consumer p_262621_, BlockPos p_262672_, MobSpawnType p_262644_, boolean p_262690_, boolean p_262590_, CreatureSpawnEvent.SpawnReason spawnReason) { + T t = this.create(p_262704_, p_262621_, p_262672_, p_262644_, p_262690_, p_262590_); if (t != null) { ((IWorldWriterBridge) p_262704_).bridge$pushAddEntityReason(spawnReason); p_262704_.addFreshEntityWithPassengers(t); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java index 1d51baade..2aacf7daf 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java @@ -1,13 +1,15 @@ package io.izzel.arclight.common.mixin.core.world.entity; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.item.enchantment.EnchantedItemInUse; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityRemoveEvent; @@ -16,7 +18,6 @@ import org.bukkit.event.player.PlayerExpCooldownChangeEvent; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -24,7 +25,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Map; +import java.util.Optional; @Mixin(ExperienceOrb.class) public abstract class ExperienceOrbMixin extends EntityMixin { @@ -33,8 +34,6 @@ public abstract class ExperienceOrbMixin extends EntityMixin { @Shadow private Player followingPlayer; @Shadow public abstract boolean hurt(DamageSource source, float amount); @Shadow public int value; - @Shadow protected abstract int durabilityToXp(int durability); - @Shadow protected abstract int xpToDurability(int p_20799_); // @formatter:on private transient Player arclight$lastPlayer; @@ -80,45 +79,33 @@ public abstract class ExperienceOrbMixin extends EntityMixin { return this.followingPlayer; } - @Redirect(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;giveExperiencePoints(I)V")) - private void arclight$expChange(Player player, int amount) { - player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, amount).getAmount()); + @Decorate(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;giveExperiencePoints(I)V")) + private void arclight$expChange(Player player, int amount) throws Throwable { + DecorationOps.callsite().invoke(player, CraftEventFactory.callPlayerExpChangeEvent(player, amount).getAmount()); } - @Redirect(method = "playerTouch", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/player/Player;takeXpDelay:I")) - private void arclight$cooldown(Player instance, int value) { - instance.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(instance, value, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); + @Decorate(method = "playerTouch", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/player/Player;takeXpDelay:I")) + private void arclight$cooldown(Player instance, int value) throws Throwable { + DecorationOps.callsite().invoke(instance, CraftEventFactory.callPlayerXpCooldownEvent(instance, value, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown()); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private int repairPlayerItems(Player player, int i) { - Map.Entry entry = EnchantmentHelper.getRandomItemWith(Enchantments.MENDING, player, ItemStack::isDamaged); - - if (entry != null) { - ItemStack itemstack = entry.getValue(); - int j = Math.min(this.xpToDurability(i), itemstack.getDamageValue()); - // CraftBukkit start - org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(player, (ExperienceOrb) (Object) this, itemstack, entry.getKey(), j); - j = event.getRepairAmount(); - if (event.isCancelled()) { - return i; - } - // CraftBukkit end - - itemstack.setDamageValue(itemstack.getDamageValue() - j); - int k = i - this.durabilityToXp(j); - this.value = k; - - return k > 0 ? this.repairPlayerItems(player, k) : 0; - } else { - return i; + @Decorate(method = "repairPlayerItems", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;setDamageValue(I)V")) + private void arclight$itemMend(ServerPlayer serverPlayer, int i, @Local(ordinal = -1) ItemStack itemstack, + @Local(ordinal = -1) Optional optional, @Local(ordinal = -1) int k) throws Throwable { + org.bukkit.event.player.PlayerItemMendEvent event = CraftEventFactory.callPlayerItemMendEvent(serverPlayer, (ExperienceOrb) (Object) this, itemstack, optional.get().inSlot(), k); + k = event.getRepairAmount(); + if (event.isCancelled()) { + DecorationOps.cancel().invoke(i); + return; } + DecorationOps.blackhole().invoke(k); } + @Decorate(method = "repairPlayerItems", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ExperienceOrb;repairPlayerItems(Lnet/minecraft/server/level/ServerPlayer;I)I")) + private int arclight$updateXp(ExperienceOrb instance, ServerPlayer serverPlayer, int i) throws Throwable { + this.value = i; + return (int) DecorationOps.callsite().invoke(instance, serverPlayer, i); + } @Inject(method = "getExperienceValue", cancellable = true, at = @At("HEAD")) private static void arclight$higherLevelSplit(int expValue, CallbackInfoReturnable cir) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LeashableMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LeashableMixin.java new file mode 100644 index 000000000..8bbc30b1b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LeashableMixin.java @@ -0,0 +1,57 @@ +package io.izzel.arclight.common.mixin.core.world.entity; + +import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Leashable; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.level.ItemLike; +import org.bukkit.Bukkit; +import org.bukkit.event.entity.EntityUnleashEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Leashable.class) +public interface LeashableMixin { + + @Decorate(method = "writeLeashData", inject = true, at = @At("HEAD")) + private void arclight$skipRemoved(CompoundTag compoundTag, Leashable.LeashData leashData) throws Throwable { + if (leashData != null && leashData.leashHolder != null && ((EntityBridge) leashData.leashHolder).bridge$pluginRemoved()) { + DecorationOps.cancel().invoke(); + return; + } + DecorationOps.blackhole().invoke(); + } + + @Decorate(method = "restoreLeashFromSave", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private static ItemEntity arclight$forceDrop(Entity instance, ItemLike itemLike) throws Throwable { + instance.bridge().bridge$setForceDrops(true); + var itemEntity = (ItemEntity) DecorationOps.callsite().invoke(instance, itemLike); + instance.bridge().bridge$setForceDrops(false); + return itemEntity; + } + + @Decorate(method = "dropLeash(Lnet/minecraft/world/entity/Entity;ZZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private static ItemEntity arclight$forceDrop2(Entity instance, ItemLike itemLike) throws Throwable { + instance.bridge().bridge$setForceDrops(true); + var itemEntity = (ItemEntity) DecorationOps.callsite().invoke(instance, itemLike); + instance.bridge().bridge$setForceDrops(false); + return itemEntity; + } + + @Decorate(method = "tickLeash", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;dropLeash(Lnet/minecraft/world/entity/Entity;ZZ)V")) + private static void arclight$unleashEvent(E entity, boolean bl, boolean bl2) throws Throwable { + Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(entity.bridge$getBukkitEntity(), (!entity.isAlive()) + ? EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : EntityUnleashEvent.UnleashReason.HOLDER_GONE)); + DecorationOps.callsite().invoke(entity, bl, !entity.bridge().bridge$pluginRemoved()); + } + + @Decorate(method = "leashTooFarBehaviour", inject = true, at = @At("HEAD")) + private void arclight$distanceLeash() { + if (this instanceof Entity entity) { + Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(entity.bridge$getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LivingEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LivingEntityMixin.java index a0f35594b..1f11333d5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LivingEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/LivingEntityMixin.java @@ -5,16 +5,18 @@ import com.google.common.collect.Maps; import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; +import io.izzel.arclight.common.mod.util.EntityDamageResult; import io.izzel.arclight.common.util.IteratorUtil; +import io.izzel.arclight.i18n.ArclightConfig; import io.izzel.arclight.mixin.Decorate; import io.izzel.arclight.mixin.DecorationOps; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Local; import io.izzel.tools.collection.XmapList; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.core.Holder; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.IntTag; @@ -27,8 +29,8 @@ import net.minecraft.tags.DamageTypeTags; import net.minecraft.tags.EntityTypeTags; import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.damagesource.CombatRules; import net.minecraft.world.damagesource.CombatTracker; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffect; @@ -39,18 +41,18 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.WalkAnimationState; 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.Attributes; -import net.minecraft.world.entity.animal.Animal; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.food.FoodProperties; import net.minecraft.world.item.Equipable; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -66,7 +68,6 @@ import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityExhaustionEvent; import org.bukkit.event.entity.EntityKnockbackEvent; import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityRegainHealthEvent; @@ -74,6 +75,7 @@ import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.event.entity.EntityTeleportEvent; import org.bukkit.event.player.PlayerItemConsumeEvent; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -82,6 +84,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -89,7 +92,6 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; -import java.util.ConcurrentModificationException; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -114,12 +116,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public net.minecraft.world.entity.player.Player lastHurtByPlayer; @Shadow public int deathTime; @Shadow protected boolean dead; - @Shadow public abstract AttributeInstance getAttribute(Attribute attribute); @Shadow public boolean effectsDirty; - @Shadow public abstract boolean removeEffect(MobEffect effectIn); @Shadow public abstract boolean removeAllEffects(); @Shadow @Final public static EntityDataAccessor DATA_HEALTH_ID; - @Shadow public abstract boolean hasEffect(MobEffect potionIn); @Shadow public abstract boolean isSleeping(); @Shadow public abstract void stopSleeping(); @Shadow protected int noActionTime; @@ -140,7 +139,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow private long lastDamageStamp; @Shadow protected abstract float getDamageAfterArmorAbsorb(DamageSource source, float damage); @Shadow public abstract net.minecraft.world.item.ItemStack getItemInHand(InteractionHand hand); - @Shadow @Nullable public abstract MobEffectInstance getEffect(MobEffect potionIn); @Shadow protected abstract float getDamageAfterMagicAbsorb(DamageSource source, float damage); @Shadow public abstract float getAbsorptionAmount(); @Shadow public abstract void setAbsorptionAmount(float amount); @@ -149,7 +147,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public abstract boolean onClimbable(); @Shadow protected ItemStack useItem; @Shadow public abstract void take(Entity entityIn, int quantity); - @Shadow protected abstract void dropAllDeathLoot(DamageSource damageSourceIn); @Shadow public abstract ItemStack getMainHandItem(); @Shadow public abstract void setSprinting(boolean sprinting); @Shadow public abstract void setLastHurtMob(Entity entityIn); @@ -161,17 +158,13 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow @Nullable public LivingEntity lastHurtByMob; @Shadow public CombatTracker combatTracker; @Shadow public abstract ItemStack getOffhandItem(); - @Shadow public abstract RandomSource getRandom(); @Shadow public abstract Optional getSleepingPos(); - @Shadow @Final private static EntityDataAccessor DATA_EFFECT_COLOR_ID; @Shadow @Final private static EntityDataAccessor DATA_EFFECT_AMBIENCE_ID; @Shadow @Final public Map activeEffects; @Shadow protected abstract void onEffectRemoved(MobEffectInstance effect); @Shadow protected abstract void updateInvisibilityStatus(); @Shadow public abstract boolean canBeAffected(MobEffectInstance potioneffectIn); - @Shadow @Nullable public abstract MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect potioneffectin); @Shadow protected abstract void createWitherRose(@Nullable LivingEntity entitySource); - @Shadow public abstract double getAttributeValue(Attribute attribute); @Shadow protected abstract void hurtArmor(DamageSource damageSource, float damage); @Shadow public abstract boolean isDeadOrDying(); @Shadow public abstract int getArrowCount(); @@ -187,7 +180,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow protected abstract boolean doesEmitEquipEvent(EquipmentSlot p_217035_); @Shadow protected abstract void verifyEquippedItem(ItemStack p_181123_); @Shadow public abstract boolean wasExperienceConsumed(); - @Shadow public abstract int getExperienceReward(); @Shadow @Nullable protected abstract SoundEvent getHurtSound(DamageSource p_21239_); @Shadow protected abstract SoundEvent getFallDamageSound(int p_21313_); @Shadow protected abstract SoundEvent getDrinkingSound(ItemStack p_21174_); @@ -196,15 +188,25 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow @Final public WalkAnimationState walkAnimation; @Shadow public int invulnerableDuration; @Shadow public abstract void indicateDamage(double p_270514_, double p_270826_); - @Shadow public static EquipmentSlot getEquipmentSlotForItem(ItemStack p_147234_) { return null; } - @Shadow protected abstract void actuallyHurt(DamageSource p_21240_, float p_21241_); + @Shadow protected void actuallyHurt(DamageSource p_21240_, float p_21241_) {} @Shadow public abstract void skipDropExperience(); @Shadow public abstract AttributeMap getAttributes(); @Shadow protected abstract void updateGlowingStatus(); + @Shadow public abstract int getExperienceReward(ServerLevel serverLevel, @org.jetbrains.annotations.Nullable Entity entity); + @Shadow protected abstract void triggerOnDeathMobEffects(Entity.RemovalReason removalReason); + @Shadow @org.jetbrains.annotations.Nullable public abstract AttributeInstance getAttribute(Holder holder); + @Shadow public abstract boolean hasEffect(Holder holder); + @Shadow @org.jetbrains.annotations.Nullable public abstract MobEffectInstance getEffect(Holder holder); + @Shadow public abstract double getAttributeValue(Holder holder); + @Shadow public abstract boolean removeEffect(Holder holder); + @Shadow public abstract boolean addEffect(MobEffectInstance mobEffectInstance, @org.jetbrains.annotations.Nullable Entity entity); + @Shadow @org.jetbrains.annotations.Nullable public abstract MobEffectInstance removeEffectNoUpdate(Holder holder); + @Shadow public abstract int getArmorValue(); + @Shadow public abstract EquipmentSlot getEquipmentSlotForItem(ItemStack itemStack); + @Shadow protected abstract void dropAllDeathLoot(ServerLevel serverLevel, DamageSource damageSource); // @formatter:on public int expToDrop; - public boolean forceDrops; public CraftAttributeMap craftAttributes; public boolean collides; public boolean bukkitPickUpLoot; @@ -247,7 +249,7 @@ public SoundEvent getEatingSound0(ItemStack itemstack) { * @reason */ @Overwrite - protected void dropExperience() { + protected void dropExperience(Entity entity) { // if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) { if (!((Object) this instanceof EnderDragon)) { int reward = this.bridge$forge$getExperienceDrop((LivingEntity) (Object) this, this.lastHurtByPlayer, this.expToDrop); @@ -257,45 +259,27 @@ protected void dropExperience() { } private boolean isTickingEffects = false; - private List, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList(); + private final List>, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList(); - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected void tickEffects() { + @Inject(method = "tickEffects", at = @At("HEAD")) + private void arclight$startTicking(CallbackInfo ci) { this.isTickingEffects = true; - Iterator iterator = this.activeEffects.keySet().iterator(); + } - try { - while (iterator.hasNext()) { - MobEffect effect = iterator.next(); - MobEffectInstance effectinstance = this.activeEffects.get(effect); - if (!effectinstance.tick((LivingEntity) (Object) this, () -> { - onEffectUpdated(effectinstance, true, null); - })) { - if (!this.level().isClientSide && !this.bridge$forge$mobEffectExpired(effectinstance)) { - EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, EntityPotionEffectEvent.Cause.EXPIRATION); - if (event.isCancelled()) { - continue; - } - - iterator.remove(); - this.onEffectRemoved(effectinstance); - } - } else if (effectinstance.getDuration() % 600 == 0) { - this.onEffectUpdated(effectinstance, false, null); - } - } - } catch (ConcurrentModificationException ignored) { + @Decorate(method = "tickEffects", inject = true, at = @At(value = "INVOKE", target = "Ljava/util/Iterator;remove()V")) + private void arclight$effectExpire(@Local(ordinal = -1) MobEffectInstance mobeffect) throws Throwable { + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, mobeffect, null, EntityPotionEffectEvent.Cause.EXPIRATION); + if (event.isCancelled()) { + throw DecorationOps.jumpToLoopStart(); } + } + @Inject(method = "tickEffects", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/world/entity/LivingEntity;effectsDirty:Z")) + private void arclight$pendingEffects(CallbackInfo ci) { isTickingEffects = false; - for (Map.Entry, EntityPotionEffectEvent.Cause> e : effectsToProcess) { - Either either = e.getKey(); - EntityPotionEffectEvent.Cause cause = e.getValue(); - bridge$pushEffectCause(cause); + for (var e : effectsToProcess) { + var either = e.getKey(); + var cause = e.getValue(); if (either.left().isPresent()) { addEffect(either.left().get(), cause); } else { @@ -303,99 +287,93 @@ protected void tickEffects() { } } effectsToProcess.clear(); + } - if (this.effectsDirty) { - if (!this.level().isClientSide) { - this.updateInvisibilityStatus(); - this.updateGlowingStatus(); - } + private transient EntityPotionEffectEvent.Cause arclight$cause; - this.effectsDirty = false; - } + public boolean addEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { + return this.addEffect(effect, null, cause); + } - int i = this.entityData.get(DATA_EFFECT_COLOR_ID); - boolean flag1 = this.entityData.get(DATA_EFFECT_AMBIENCE_ID); - if (i > 0) { - boolean flag; - if (this.isInvisible()) { - flag = this.random.nextInt(15) == 0; - } else { - flag = this.random.nextBoolean(); - } + public boolean addEffect(MobEffectInstance effect, Entity entity, EntityPotionEffectEvent.Cause cause) { + bridge$pushEffectCause(cause); + return this.addEffect(effect, entity); + } - if (flag1) { - flag &= this.random.nextInt(5) == 0; - } + public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { + bridge$pushEffectCause(cause); + return this.removeAllEffects(); + } - if (flag && i > 0) { - double d0 = (double) (i >> 16 & 255) / 255.0D; - double d1 = (double) (i >> 8 & 255) / 255.0D; - double d2 = (double) (i >> 0 & 255) / 255.0D; - this.level().addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.getX() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), this.getY() + this.random.nextDouble() * (double) this.getBbHeight(), this.getZ() + (this.random.nextDouble() - 0.5D) * (double) this.getBbWidth(), d0, d1, d2); - } - } + @Override + public boolean bridge$removeAllEffects(EntityPotionEffectEvent.Cause cause) { + return removeAllEffects(cause); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean addEffect(MobEffectInstance effectInstanceIn, Entity entity) { - EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); + @Decorate(method = "addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z", inject = true, at = @At(value = "JUMP", opcode = Opcodes.IFNE, ordinal = 0)) + private void arclight$addPendingEffects(MobEffectInstance mobEffectInstance, Entity entity, + @Local(allocate = "cause") EntityPotionEffectEvent.Cause cause) throws Throwable { + cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); if (isTickingEffects) { - effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause)); - return true; + effectsToProcess.add(Maps.immutableEntry(Either.left(mobEffectInstance), cause)); + DecorationOps.cancel().invoke(true); + return; } + DecorationOps.blackhole().invoke(); + } - if (!this.canBeAffected(effectInstanceIn)) { - return false; - } else { - MobEffectInstance effectinstance = this.activeEffects.get(effectInstanceIn.getEffect()); - boolean flag = false; - - boolean override = false; - if (effectinstance != null) { - override = new MobEffectInstance(effectinstance).update(effectInstanceIn); - } + @Decorate(method = "addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z", inject = true, + at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")) + private void arclight$effectAdd(MobEffectInstance mobEffectInstance, Entity entity, @Local(allocate = "cause") EntityPotionEffectEvent.Cause cause) throws Throwable { + var event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, null, mobEffectInstance, cause, false); + if (event.isCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } + DecorationOps.blackhole().invoke(); + } - EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override); - if (event.isCancelled()) { - return false; - } + @Decorate(method = "addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/effect/MobEffectInstance;update(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) + private boolean arclight$effectReplace(MobEffectInstance oldEffect, MobEffectInstance newEffect, + MobEffectInstance mobEffectInstance, Entity entity, @Local(allocate = "cause") EntityPotionEffectEvent.Cause cause) throws Throwable { + var override = new MobEffectInstance(oldEffect).update(newEffect); + var event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, oldEffect, newEffect, cause, override); + if (event.isCancelled()) { + return (boolean) DecorationOps.cancel().invoke(false); + } + if (event.isOverride()) { + var b = (boolean) DecorationOps.callsite().invoke(oldEffect, newEffect); + DecorationOps.blackhole().invoke(b); + } + return event.isOverride(); + } - this.bridge$forge$mobEffectAdded(effectinstance, effectInstanceIn, entity); - if (effectinstance == null) { - this.activeEffects.put(effectInstanceIn.getEffect(), effectInstanceIn); - this.onEffectAdded(effectInstanceIn, entity); - flag = true; - } else if (event.isOverride()) { - effectinstance.update(effectInstanceIn); - this.onEffectUpdated(effectinstance, true, entity); - flag = true; - } + public boolean removeEffect(Holder effect, EntityPotionEffectEvent.Cause cause) { + bridge$pushEffectCause(cause); + return removeEffect(effect); + } - effectInstanceIn.onEffectStarted((LivingEntity) (Object) this); - return flag; - } + @Override + public boolean bridge$removeEffect(Holder effect, EntityPotionEffectEvent.Cause cause) { + return removeEffect(effect, cause); } - @SuppressWarnings("unused") // mock - public MobEffectInstance c(@Nullable MobEffect potioneffectin, EntityPotionEffectEvent.Cause cause) { + public MobEffectInstance removeEffectNoUpdate(@Nullable Holder holder, EntityPotionEffectEvent.Cause cause) { bridge$pushEffectCause(cause); - return removeEffectNoUpdate(potioneffectin); + return removeEffectNoUpdate(holder); } @Inject(method = "removeEffectNoUpdate", cancellable = true, at = @At("HEAD")) - public void arclight$clearActive(MobEffect effect, CallbackInfoReturnable cir) { + public void arclight$clearActive(Holder holder, CallbackInfoReturnable cir) { EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); if (isTickingEffects) { - effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause)); + effectsToProcess.add(Maps.immutableEntry(Either.right(holder), cause)); cir.setReturnValue(null); return; } - MobEffectInstance effectInstance = this.activeEffects.get(effect); + MobEffectInstance effectInstance = this.activeEffects.get(holder); if (effectInstance == null) { cir.setReturnValue(null); return; @@ -407,6 +385,11 @@ public MobEffectInstance c(@Nullable MobEffect potioneffectin, EntityPotionEffec } } + @Inject(method = "triggerOnDeathMobEffects", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Map;clear()V")) + private void arclight$fireRemoveEvents(Entity.RemovalReason removalReason, CallbackInfo ci) { + this.removeAllEffects(EntityPotionEffectEvent.Cause.DEATH); + } + @Override public boolean bridge$canPickUpLoot() { return bukkitPickUpLoot; @@ -417,9 +400,9 @@ public float getBukkitYaw() { return getYHeadRot(); } - public int getExpReward() { - if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { - int exp = this.getExperienceReward(); + public int getExpReward(Entity entity) { + if (this.level() instanceof ServerLevel serverLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { + int exp = this.getExperienceReward(serverLevel, entity); return this.bridge$forge$getExperienceDrop((LivingEntity) (Object) this, this.lastHurtByPlayer, exp); } else { return 0; @@ -427,8 +410,8 @@ public int getExpReward() { } @Override - public int bridge$getExpReward() { - return getExpReward(); + public int bridge$getExpReward(Entity entity) { + return getExpReward(entity); } @Override @@ -441,11 +424,6 @@ public int getExpReward() { return this.expToDrop; } - @Override - public boolean bridge$isForceDrops() { - return forceDrops; - } - @Inject(method = "readAdditionalSaveData", at = @At("HEAD")) public void arclight$readMaxHealth(CompoundTag compound, CallbackInfo ci) { if (compound.contains("Bukkit.MaxHealth")) { @@ -517,8 +495,8 @@ public void knockback(double d, double e, double f, Entity attacker, EntityKnock this.knockback(d, e, f); } - @Redirect(method = "knockback", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setDeltaMovement(DDD)V")) - private void arclight$knockbackEvent(LivingEntity instance, double x, double y, double z, double d, double e, double f) { + @Decorate(method = "knockback", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setDeltaMovement(DDD)V")) + private void arclight$knockbackEvent(LivingEntity instance, double x, double y, double z, double d, double e, double f) throws Throwable { var attacker = arclight$knockbackAttacker; var cause = arclight$knockbackCause == null ? EntityKnockbackEvent.KnockbackCause.UNKNOWN : arclight$knockbackCause; arclight$knockbackAttacker = null; @@ -526,335 +504,204 @@ public void knockback(double d, double e, double f, Entity attacker, EntityKnock var raw = (new Vec3(e, 0.0, f)).normalize().scale(d); var event = CraftEventFactory.callEntityKnockbackEvent(this.getBukkitEntity(), attacker, cause, d, raw, x, y, z); if (!event.isCancelled()) { - instance.setDeltaMovement(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()); + DecorationOps.callsite().invoke(instance, event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()); } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean hurt(DamageSource source, float amount) { - if (this.isInvulnerableTo(source)) { - return false; - } else if (this.level().isClientSide) { - return false; - } else if (this.dead || this.isRemoved() || this.isDeadOrDying()) { - return false; - } else if (source.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { - return false; - } else { - if (this.isSleeping() && !this.level().isClientSide) { - this.stopSleeping(); - } - - this.noActionTime = 0; - float f = amount; - boolean flag = f > 0.0F && this.isDamageSourceBlocked(source); // Copied from below - float f1 = 0.0F; - // ShieldBlockEvent implemented in damageEntity0 - - if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { - this.hurtCurrentlyUsedShield(amount); - f1 = amount; - amount = 0.0F; - if (!source.is(DamageTypeTags.IS_PROJECTILE)) { - Entity entity = source.getDirectEntity(); - if (entity instanceof LivingEntity) { - this.blockUsingShield((LivingEntity) entity); - } - } + @Unique protected transient EntityDamageResult entityDamageResult; - flag = true; - } + @Decorate(method = "hurt", inject = true, at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;noActionTime:I")) + private void arclight$entityDamageEvent(DamageSource damagesource, float originalDamage) throws Throwable { + arclight$damageResult = false; + entityDamageResult = null; + final boolean human = (Object) this instanceof net.minecraft.world.entity.player.Player; - if (source.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) { - f *= 5.0F; - } + float damage = originalDamage; - this.walkAnimation.setSpeed(1.5F); - boolean flag1 = true; - if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { - if (amount <= this.lastHurt) { - return false; - } + Function blocking = f -> -((this.isDamageSourceBlocked(damagesource)) ? f : 0.0); + float blockingModifier = blocking.apply((double) damage).floatValue(); + damage += blockingModifier; - this.actuallyHurt(source, amount - this.lastHurt); - if (!arclight$damageResult) { - return false; - } - this.lastHurt = amount; - flag1 = false; - } else { - this.actuallyHurt(source, amount); - if (!arclight$damageResult) { - return false; - } - this.lastHurt = amount; - this.invulnerableTime = 20; - this.hurtDuration = 10; - this.hurtTime = this.hurtDuration; + Function freezing = f -> { + if (damagesource.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) { + return -(f - (f * 5.0F)); } + return -0.0; + }; + float freezingModifier = freezing.apply((double) damage).floatValue(); + damage += freezingModifier; - if ((Object) this instanceof Animal) { - ((Animal) (Object) this).resetLove(); - if ((Object) this instanceof TamableAnimal) { - ((TamableAnimal) (Object) this).setOrderedToSit(false); - } + Function hardHat = f -> { + if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { + return -(f - (f * 0.75F)); } - - Entity entity1 = source.getEntity(); - if (entity1 != null) { - if (entity1 instanceof LivingEntity && !source.is(DamageTypeTags.NO_ANGER)) { - this.setLastHurtByMob((LivingEntity) entity1); - } - - if (entity1 instanceof net.minecraft.world.entity.player.Player) { - this.lastHurtByPlayerTime = 100; - this.lastHurtByPlayer = (net.minecraft.world.entity.player.Player) entity1; - } else if (entity1 instanceof TamableAnimal wolfentity) { - if (wolfentity.isTame()) { - this.lastHurtByPlayerTime = 100; - LivingEntity livingentity = wolfentity.getOwner(); - if (livingentity instanceof net.minecraft.world.entity.player.Player) { - this.lastHurtByPlayer = (net.minecraft.world.entity.player.Player) livingentity; - } else { - this.lastHurtByPlayer = null; - } - } + return -0.0; + }; + float hardHatModifier = hardHat.apply((double) damage).floatValue(); + damage += hardHatModifier; + + if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { + if (damage <= this.lastHurt) { + if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { + ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); } + return; } + } - if (flag1) { - if (flag) { - this.level().broadcastEntityEvent((LivingEntity) (Object) this, (byte) 29); - } else { - this.level().broadcastDamageEvent((LivingEntity) (Object) this, source); - } - - if (!source.is(DamageTypeTags.NO_IMPACT) && (!flag || amount > 0.0F)) { - this.markHurt(); - } - - if (entity1 != null && !source.is(DamageTypeTags.NO_KNOCKBACK)) { - double d1 = entity1.getX() - this.getX(); - - double d0; - for (d0 = entity1.getZ() - this.getZ(); d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D) { - d1 = (Math.random() - Math.random()) * 0.01D; - } - - this.bridge$pushKnockbackCause(entity1, entity1 == null ? EntityKnockbackEvent.KnockbackCause.DAMAGE : EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); - this.knockback(0.4F, d1, d0); - if (!flag) { - this.indicateDamage(d1, d0); - } - } + Function armor = f -> { + if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { + return -(f - CombatRules.getDamageAfterAbsorb((LivingEntity) (Object) this, f.floatValue(), damagesource, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS))); } - if (this.isDeadOrDying()) { - if (!this.checkTotemDeathProtection(source)) { - SoundEvent soundevent = this.getDeathSound(); - if (flag1 && soundevent != null) { - this.playSound(soundevent, this.getSoundVolume(), this.getVoicePitch()); - } - - this.die(source); - } - } else if (flag1) { - this.playHurtSound(source); + return -0.0; + }; + float originalArmorDamage = damage; + float armorModifier = armor.apply((double) damage).floatValue(); + damage += armorModifier; + + Function resistance = f -> { + if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { + int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; + int j = 25 - i; + float f1 = f.floatValue() * (float) j; + return -(f - (f1 / 25.0F)); } - - boolean flag2 = !flag || amount > 0.0F; - if (flag2) { - this.lastDamageSource = source; - this.lastDamageStamp = this.level().getGameTime(); + return -0.0; + }; + float resistanceModifier = resistance.apply((double) damage).floatValue(); + damage += resistanceModifier; + + Function magic = f -> { + float l; + if (this.level() instanceof ServerLevel serverLevel) { + l = EnchantmentHelper.getDamageProtection(serverLevel, (LivingEntity) (Object) this, damagesource); + } else { + l = 0.0F; } - if ((Object) this instanceof ServerPlayer) { - CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) (Object) this, source, f, amount, flag); - if (f1 > 0.0F && f1 < 3.4028235E37F) { - ((ServerPlayer) (Object) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f1 * 10.0F)); - } + if (l > 0.0F) { + return -(f - CombatRules.getDamageAfterMagicAbsorb(f.floatValue(), l)); } + return -0.0; + }; + float magicModifier = magic.apply((double) damage).floatValue(); + damage += magicModifier; - if (entity1 instanceof ServerPlayer) { - CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) entity1, (LivingEntity) (Object) this, source, f, amount, flag); - } + Function absorption = f -> -(Math.max(f - Math.max(f - this.getAbsorptionAmount(), 0.0F), 0.0F)); + float absorptionModifier = absorption.apply((double) damage).floatValue(); - return flag2; + EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent((LivingEntity) (Object) this, damagesource, originalDamage, freezingModifier, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, freezing, hardHat, blocking, armor, resistance, magic, absorption); + if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { + ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); } - } - - @Inject(method = "actuallyHurt", cancellable = true, at = @At("HEAD")) - public void arclight$redirectDamageEntity(DamageSource damageSrc, float damageAmount, CallbackInfo ci) { - damageEntity0(damageSrc, damageAmount); - ci.cancel(); - } - private transient boolean arclight$damageResult; - - protected boolean damageEntity0(DamageSource damagesource, float f) { - if (!this.isInvulnerableTo(damagesource)) { - final boolean human = (Object) this instanceof net.minecraft.world.entity.player.Player; - - f = this.bridge$forge$onLivingHurt((LivingEntity) (Object) this, damagesource, f); - if (f <= 0) return arclight$damageResult = true; + if (event.isCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } - float originalDamage = f; - Function hardHat = f12 -> { - if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { - return -(f12 - (f12 * 0.75F)); - } - return -0.0; - }; - float hardHatModifier = hardHat.apply((double) f).floatValue(); - f += hardHatModifier; - - Function blocking; - var shieldTakesDamage = false; - if (this.isDamageSourceBlocked(damagesource)) { - var shieldEvent = this.bridge$forge$onShieldBlock((LivingEntity) (Object) this, damagesource, f); - if (!shieldEvent._1) { - var blocked = shieldEvent._2; - shieldTakesDamage = shieldEvent._3; - blocking = f13 -> -(double) blocked; - } else { - blocking = f13 -> 0d; - } + damage = (float) event.getFinalDamage(); + float damageOffset = damage - originalDamage; + float armorDamage = (float) (event.getDamage() + event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) + event.getDamage(EntityDamageEvent.DamageModifier.HARD_HAT)); + entityDamageResult = new + + EntityDamageResult( + Math.abs(damageOffset) > 1E-6, + originalDamage, + damage, + damageOffset, + originalArmorDamage, + armorDamage - originalArmorDamage, + hardHatModifier > 0 && damage <= 0, + armorModifier > 0 && (event.getDamage() + event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) + event.getDamage(EntityDamageEvent.DamageModifier.HARD_HAT)) <= 0, + blockingModifier < 0 && event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) >= 0 + ); + + if (damage > 0 || !human) { + arclight$damageResult = true; + } else { + if (event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0) { + arclight$damageResult = true; } else { - blocking = f13 -> 0d; + arclight$damageResult = originalDamage > 0; } - float blockingModifier = blocking.apply((double) f).floatValue(); - f += blockingModifier; - - Function armor = f14 -> -(f14 - this.getDamageAfterArmorAbsorb(damagesource, f14.floatValue())); - float armorModifier = armor.apply((double) f).floatValue(); - f += armorModifier; - - Function resistance = f15 -> { - if (!damagesource.is(DamageTypeTags.BYPASSES_EFFECTS) && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { - int i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; - int j = 25 - i; - float f1 = f15.floatValue() * (float) j; - return -(f15 - (f1 / 25.0F)); - } - return -0.0; - }; - float resistanceModifier = resistance.apply((double) f).floatValue(); - f += resistanceModifier; - - Function magic = f16 -> -(f16 - this.getDamageAfterMagicAbsorb(damagesource, f16.floatValue())); - float magicModifier = magic.apply((double) f).floatValue(); - f += magicModifier; - - Function absorption = f17 -> -(Math.max(f17 - Math.max(f17 - this.getAbsorptionAmount(), 0.0F), 0.0F)); - float absorptionModifier = absorption.apply((double) f).floatValue(); + } + if (damage == 0) { + originalDamage = 0; + DecorationOps.blackhole().invoke(originalDamage); + } + } - EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent((LivingEntity) (Object) this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); - if (damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { - ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).resetAttackStrengthTicker(); - } + @Decorate(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isDamageSourceBlocked(Lnet/minecraft/world/damagesource/DamageSource;)Z")) + private boolean arclight$cancelShieldBlock(LivingEntity instance, DamageSource damageSource, + @Local(ordinal = -1) boolean blocked) throws Throwable { + return (entityDamageResult == null || !entityDamageResult.blockingCancelled()) && (boolean) DecorationOps.callsite().invoke(instance, damageSource); + } - if (event.isCancelled()) { - return arclight$damageResult = false; + @Decorate(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtHelmet(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void arclight$cancelHurtHelmet(LivingEntity instance, DamageSource damageSource, float f) throws + Throwable { + if (entityDamageResult == null || !entityDamageResult.helmetHurtCancelled()) { + var result = f + entityDamageResult.armorDamageOffset(); + if (entityDamageResult.armorDamageOffset() < 0 && result < 0) { + result = f + f * (entityDamageResult.armorDamageOffset() / entityDamageResult.originalArmorDamage()); } - - f = (float) event.getFinalDamage(); - - // Resistance - if (event.getDamage(EntityDamageEvent.DamageModifier.RESISTANCE) < 0) { - float f3 = (float) -event.getDamage(EntityDamageEvent.DamageModifier.RESISTANCE); - if (f3 > 0.0F && f3 < 3.4028235E37F) { - if ((Object) this instanceof ServerPlayer) { - ((ServerPlayer) (Object) this).awardStat(Stats.DAMAGE_RESISTED, Math.round(f3 * 10.0F)); - } else if (damagesource.getEntity() instanceof ServerPlayer) { - ((ServerPlayer) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_RESISTED, Math.round(f3 * 10.0F)); - } - } + if (result > 0) { + DecorationOps.callsite().invoke(instance, damageSource, result); } + } + } - // Apply damage to helmet - if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { - this.hurtHelmet(damagesource, f); - } + @Decorate(method = "hurt", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/LivingEntity;invulnerableTime:I"), + slice = @Slice(to = @At(value = "FIELD", target = "Lnet/minecraft/tags/DamageTypeTags;BYPASSES_COOLDOWN:Lnet/minecraft/tags/TagKey;"))) + private int arclight$useInvulnerableDuration(LivingEntity instance) throws Throwable { + int result = (int) DecorationOps.callsite().invoke(instance); + return result + 10 - (int) (this.invulnerableDuration / 2.0F); + } - // Apply damage to armor - if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { - float armorDamage = (float) (event.getDamage() + event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) + event.getDamage(EntityDamageEvent.DamageModifier.HARD_HAT)); - this.hurtArmor(damagesource, armorDamage); - } + @Decorate(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void arclight$returnIfBlocked(LivingEntity instance, DamageSource damageSource, float f) throws + Throwable { + DecorationOps.callsite().invoke(instance, damageSource, f); + if (!arclight$damageResult) { + DecorationOps.cancel().invoke(false); + return; + } + DecorationOps.blackhole().invoke(); + } - // Apply blocking code // PAIL: steal from above - if (event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0) { - this.level().broadcastEntityEvent((Entity) (Object) this, (byte) 29); // SPIGOT-4635 - shield damage sound - if (shieldTakesDamage) { - this.hurtCurrentlyUsedShield((float) -event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING)); - } - Entity entity = damagesource.getDirectEntity(); + @Inject(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) + private void arclight$knockbackCause(DamageSource damageSource, float f, CallbackInfoReturnable cir) { + this.bridge$pushKnockbackCause(damageSource.getEntity(), damageSource.getEntity() == null ? EntityKnockbackEvent.KnockbackCause.DAMAGE : EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); + } - if (entity instanceof LivingEntity) { - this.blockUsingShield(((LivingEntity) entity)); + @Decorate(method = "actuallyHurt", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;getCombatTracker()Lnet/minecraft/world/damagesource/CombatTracker;")) + private void arclight$setDamageResult(DamageSource damageSource, float f) throws Throwable { + arclight$damageResult = true; + if (entityDamageResult != null && entityDamageResult.damageOverride()) { + float newDamage; + if (ArclightConfig.spec().getCompat().isExactPluginEntityDamageControl()) { + newDamage = entityDamageResult.finalDamage(); + } else { + newDamage = f + entityDamageResult.damageOffset(); + if (newDamage < 0 && entityDamageResult.damageOffset() < 0) { + newDamage = f + f * (entityDamageResult.damageOffset() / entityDamageResult.originalDamage()); } } + f = newDamage; + DecorationOps.blackhole().invoke(f); + } + } - absorptionModifier = (float) -event.getDamage(EntityDamageEvent.DamageModifier.ABSORPTION); - this.setAbsorptionAmount(Math.max(this.getAbsorptionAmount() - absorptionModifier, 0.0F)); - float f2 = absorptionModifier; - - if (f2 > 0.0F && f2 < 3.4028235E37F && (Object) this instanceof net.minecraft.world.entity.player.Player) { - ((net.minecraft.world.entity.player.Player) (Object) this).awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F)); - } - if (f2 > 0.0F && f2 < 3.4028235E37F && damagesource.getEntity() instanceof net.minecraft.world.entity.player.Player) { - ((net.minecraft.world.entity.player.Player) damagesource.getEntity()).awardStat(Stats.DAMAGE_DEALT_ABSORBED, Math.round(f2 * 10.0F)); - } - - f = this.bridge$forge$onLivingDamage((LivingEntity) (Object) this, damagesource, f); - - if (f > 0 || !human) { - if (human) { - // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. - ((PlayerEntityBridge) this).bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.DAMAGED); - ((net.minecraft.world.entity.player.Player) (Object) this).causeFoodExhaustion(damagesource.getFoodExhaustion()); - if (f < 3.4028235E37F) { - ((net.minecraft.world.entity.player.Player) (Object) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); - } - } - // CraftBukkit end - float f3 = this.getHealth(); - - this.getCombatTracker().recordDamage(damagesource, f); - this.setHealth(f3 - f); // Forge: moved to fix MC-121048 - // CraftBukkit start - if (!human) { - this.setAbsorptionAmount(this.getAbsorptionAmount() - f); - } - this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); + protected transient boolean arclight$damageResult; - return arclight$damageResult = true; - } else { - // Duplicate triggers if blocking - if (event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) < 0) { - if ((Object) this instanceof ServerPlayer) { - CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) (Object) this, damagesource, f, originalDamage, true); - f2 = (float) (-event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING)); - if (f2 > 0.0f && f2 < 3.4028235E37f) { - ((ServerPlayer) (Object) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0f)); - } - } - if (damagesource.getEntity() instanceof ServerPlayer) { - CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), (Entity) (Object) this, damagesource, f, originalDamage, true); - } - - return arclight$damageResult = false; - } else { - return arclight$damageResult = originalDamage > 0; - } - // CraftBukkit end - } + @Decorate(method = "getDamageAfterArmorAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtArmor(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void arclight$muteDamageArmor(LivingEntity entity, DamageSource damageSource, float damage) throws + Throwable { + if (entityDamageResult == null || !entityDamageResult.armorHurtCancelled()) { + DecorationOps.callsite().invoke(entity, damageSource, damage); } - return arclight$damageResult = false; // CraftBukkit } private transient EntityRegainHealthEvent.RegainReason arclight$regainReason; @@ -885,33 +732,6 @@ public void heal(float healAmount, EntityRegainHealthEvent.RegainReason regainRe arclight$regainReason = null; } - private transient EntityPotionEffectEvent.Cause arclight$cause; - - public boolean removeEffect(MobEffect effect, EntityPotionEffectEvent.Cause cause) { - bridge$pushEffectCause(cause); - return removeEffect(effect); - } - - @Override - public boolean bridge$removeEffect(MobEffect effect, EntityPotionEffectEvent.Cause cause) { - return removeEffect(effect, cause); - } - - public boolean addEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { - bridge$pushEffectCause(cause); - return this.addEffect(effect, (Entity) null); - } - - public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { - bridge$pushEffectCause(cause); - return this.removeAllEffects(); - } - - @Override - public boolean bridge$removeAllEffects(EntityPotionEffectEvent.Cause cause) { - return removeAllEffects(cause); - } - public CraftLivingEntity getBukkitEntity() { return (CraftLivingEntity) internal$getBukkitEntity(); } @@ -982,39 +802,20 @@ private boolean checkTotemDeathProtection(DamageSource damageSourceIn) { @Redirect(method = "createWitherRose", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) private boolean arclight$fireWitherRoseForm(Level instance, BlockPos pPos, BlockState pNewState, int pFlags) { - return CraftEventFactory.handleBlockFormEvent(instance, pPos, pNewState, 3, (Entity) (Object) this); - } - - // https://github.com/IzzelAliz/Arclight/issues/831 - @Mixin(value = LivingEntity.class, priority = 1500) - public static class ObscureApiCompat { - - @Redirect(method = "getDamageAfterArmorAbsorb", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurtArmor(Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void arclight$muteDamageArmor(LivingEntity entity, DamageSource damageSource, float damage) { - } - } - - // https://github.com/IzzelAliz/Arclight/issues/811 - @Mixin(value = LivingEntity.class, priority = 1500) - public static class ApotheosisCompatMixin { - - @Redirect(method = "getDamageAfterMagicAbsorb", require = 0, at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;hasEffect(Lnet/minecraft/world/effect/MobEffect;)Z")) - public boolean arclight$mutePotion(LivingEntity livingEntity, MobEffect potionIn) { - return false; - } + return CraftEventFactory.handleBlockFormEvent(instance, pPos, pNewState, pFlags, (Entity) (Object) this); } - @Redirect(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setSharedFlag(IZ)V")) - public void arclight$stopGlide(LivingEntity livingEntity, int flag, boolean set) { + @Decorate(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setSharedFlag(IZ)V")) + private void arclight$stopGlide(LivingEntity livingEntity, int flag, boolean set) throws Throwable { if (set != livingEntity.getSharedFlag(flag) && !CraftEventFactory.callToggleGlideEvent(livingEntity, set).isCancelled()) { - livingEntity.setSharedFlag(flag, set); + DecorationOps.callsite().invoke(livingEntity, flag, set); } } - @Redirect(method = "updateFallFlying", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setSharedFlag(IZ)V")) - public void arclight$toggleGlide(LivingEntity livingEntity, int flag, boolean set) { + @Decorate(method = "updateFallFlying", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setSharedFlag(IZ)V")) + private void arclight$toggleGlide(LivingEntity livingEntity, int flag, boolean set) throws Throwable { if (set != livingEntity.getSharedFlag(flag) && !CraftEventFactory.callToggleGlideEvent(livingEntity, set).isCancelled()) { - livingEntity.setSharedFlag(flag, set); + DecorationOps.callsite().invoke(livingEntity, flag, set); } } @@ -1041,9 +842,9 @@ public boolean canCollideWith(Entity entity) { return this.isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); } - @Eject(method = "completeUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;finishUsingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/item/ItemStack;")) - private ItemStack arclight$itemConsume(ItemStack itemStack, Level worldIn, LivingEntity - entityLiving, CallbackInfo ci) { + @Decorate(method = "completeUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;finishUsingItem(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/item/ItemStack;")) + private ItemStack arclight$itemConsume(ItemStack itemStack, Level worldIn, LivingEntity entityLiving) throws + Throwable { if (this instanceof ServerPlayerEntityBridge) { final org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(itemStack); final PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, CraftEquipmentSlot.getHand(this.getUsedItemHand())); @@ -1051,27 +852,42 @@ public boolean canCollideWith(Entity entity) { if (event.isCancelled()) { ((ServerPlayerEntityBridge) this).bridge$getBukkitEntity().updateInventory(); ((ServerPlayerEntityBridge) this).bridge$getBukkitEntity().updateScaledHealth(); - ci.cancel(); - return null; + return (ItemStack) DecorationOps.cancel().invoke(); } else if (!craftItem.equals(event.getItem())) { - return CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(worldIn, entityLiving); + itemStack = CraftItemStack.asNMSCopy(event.getItem()); } } - return itemStack.finishUsingItem(worldIn, entityLiving); + return (ItemStack) DecorationOps.callsite().invoke(itemStack, worldIn, entityLiving); } - @Eject(method = "randomTeleport", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;teleportTo(DDD)V")) - private void arclight$entityTeleport(LivingEntity entity, double x, double y, double z, CallbackInfoReturnable< - Boolean> cir) { - EntityTeleportEvent event = new EntityTeleportEvent(getBukkitEntity(), new Location(this.level().bridge$getWorld(), this.getX(), this.getY(), this.getZ()), - new Location(this.level().bridge$getWorld(), x, y, z)); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) { - this.teleportTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + @Decorate(method = "randomTeleport", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;teleportTo(DDD)V")) + private void arclight$entityTeleport(LivingEntity entity, double x, double y, double z) throws Throwable { + if ((Object) this instanceof ServerPlayer) { + (((ServerPlayer) (Object) this).connection).teleport(x, y, z, this.getYRot(), this.getXRot(), java.util.Collections.emptySet()); + if (!((ServerPlayNetHandlerBridge) ((ServerPlayer) (Object) this).connection).bridge$teleportCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } } else { - this.teleportTo(this.getX(), this.getY(), this.getZ()); - cir.setReturnValue(false); + EntityTeleportEvent event = new EntityTeleportEvent(getBukkitEntity(), new Location(this.level().bridge$getWorld(), this.getX(), this.getY(), this.getZ()), + new Location(this.level().bridge$getWorld(), x, y, z)); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + x = event.getTo().getX(); + y = event.getTo().getY(); + z = event.getTo().getZ(); + } else { + x = this.getX(); + y = this.getY(); + z = this.getZ(); + } + if (event.isCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } + DecorationOps.callsite().invoke(entity, x, y, z); } + DecorationOps.blackhole().invoke(); } @Unique private List arclight$capturedDrops; @@ -1103,7 +919,7 @@ public boolean canCollideWith(Entity entity) { } @Override - public void bridge$common$finishCaptureAndFireEvent() { + public void bridge$common$finishCaptureAndFireEvent(DamageSource damageSource) { // in vanilla all items are dropped here // in forge we do not capture items ourselves but use forge system var drops = arclight$capturedDrops; @@ -1117,24 +933,23 @@ public boolean canCollideWith(Entity entity) { itemEntity.setDefaultPickUpDelay(); return itemEntity; }); - CraftEventFactory.callEntityDeathEvent((LivingEntity) (Object) this, itemStackList); + CraftEventFactory.callEntityDeathEvent((LivingEntity) (Object) this, damageSource, itemStackList); arclight$capturedDrops = null; } @Inject(method = "dropAllDeathLoot", at = @At("HEAD")) - private void arclight$startCapture(DamageSource damageSource, CallbackInfo ci) { + private void arclight$startCapture(ServerLevel serverLevel, DamageSource damageSource, CallbackInfo ci) { this.bridge$common$startCaptureDrops(); } - @Inject(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience()V")) - private void arclight$stopCapture(DamageSource damageSource, CallbackInfo ci) { - this.bridge$common$finishCaptureAndFireEvent(); + @Inject(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$stopCapture(ServerLevel serverLevel, DamageSource damageSource, CallbackInfo ci) { + this.bridge$common$finishCaptureAndFireEvent(damageSource); } @Inject(method = "addEatEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - public void arclight$foodEffectCause(ItemStack p_213349_1_, Level p_213349_2_, LivingEntity - livingEntity, CallbackInfo ci) { - ((LivingEntityBridge) livingEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.FOOD); + public void arclight$foodEffectCause(FoodProperties foodProperties, CallbackInfo ci) { + this.bridge$pushEffectCause(EntityPotionEffectEvent.Cause.FOOD); } @Override @@ -1184,22 +999,22 @@ public final void setArrowCount(int count, boolean reset) { return CraftEventFactory.callArrowBodyCountChangeEvent((LivingEntity) (Object) this, this.getArrowCount(), newCount, reset).isCancelled(); } - public void setItemSlot(EquipmentSlot slotIn, ItemStack stack, boolean silent) { + public void onEquipItem(EquipmentSlot slotIn, ItemStack stack, boolean silent) { this.setItemSlot(slotIn, stack); } @Override public void bridge$setSlot(EquipmentSlot slotIn, ItemStack stack, boolean silent) { - this.setItemSlot(slotIn, stack, silent); + this.onEquipItem(slotIn, stack, silent); } protected void equipEventAndSound(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem, boolean silent) { boolean flag = newItem.isEmpty() && oldItem.isEmpty(); - if (!flag && !ItemStack.isSameItemSameTags(oldItem, newItem) && !this.firstTick) { + if (!flag && !ItemStack.isSameItemSameComponents(oldItem, newItem) && !this.firstTick) { Equipable equipable = Equipable.get(newItem); if (!this.level().isClientSide() && !this.isSpectator()) { if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == slot && !silent) { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + this.level().playSeededSound(null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F, this.random.nextLong()); } if (this.doesEmitEquipEvent(slot)) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/MobMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/MobMixin.java index 8939c1798..c0ff69cd5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/MobMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/MobMixin.java @@ -1,17 +1,13 @@ package io.izzel.arclight.common.mixin.core.world.entity; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mod.server.ArclightServer; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; -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.EquipmentSlot; @@ -24,7 +20,6 @@ import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityKnockbackEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.entity.EntityTargetEvent; @@ -38,7 +33,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -53,14 +47,12 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri @Shadow public abstract boolean removeWhenFarAway(double distanceToClosestPlayer); @Shadow @Nullable public abstract LivingEntity getTarget(); @Shadow private LivingEntity target; - @Shadow protected abstract ResourceLocation getDefaultLootTable(); @Shadow public abstract ItemStack getItemBySlot(EquipmentSlot slotIn); @Shadow public abstract boolean canHoldItem(ItemStack stack); @Shadow protected abstract float getEquipmentDropChance(EquipmentSlot slotIn); @Shadow public abstract void setItemSlot(EquipmentSlot slotIn, ItemStack stack); @Shadow @Final public float[] handDropChances; @Shadow @Final public float[] armorDropChances; - @Shadow @Nullable public abstract Entity getLeashHolder(); @Shadow public abstract boolean isPersistenceRequired(); @Shadow protected void customServerAiStep() { } @Shadow public abstract boolean isNoAi(); @@ -68,6 +60,7 @@ public abstract class MobMixin extends LivingEntityMixin implements MobEntityBri @Shadow protected abstract void setItemSlotAndDropWhenKilled(EquipmentSlot p_233657_1_, ItemStack p_233657_2_); @Shadow @Nullable public abstract T convertTo(EntityType p_233656_1_, boolean p_233656_2_); @Shadow @Nullable protected abstract SoundEvent getAmbientSound(); + @Shadow public abstract void setTarget(@org.jetbrains.annotations.Nullable LivingEntity livingEntity); // @formatter:on public boolean aware; @@ -104,12 +97,8 @@ public SoundEvent getAmbientSound0() { private transient EntityTargetEvent.TargetReason arclight$reason; private transient boolean arclight$fireEvent; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void setTarget(@Nullable LivingEntity livingEntity) { + @Decorate(method = "setTarget", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/Mob;target:Lnet/minecraft/world/entity/LivingEntity;")) + private void arclight$setTargetEvent(Mob instance, LivingEntity livingEntity) throws Throwable { boolean fireEvent = arclight$fireEvent; arclight$fireEvent = false; EntityTargetEvent.TargetReason reason = arclight$reason == null ? EntityTargetEvent.TargetReason.UNKNOWN : arclight$reason; @@ -123,7 +112,7 @@ public void setTarget(@Nullable LivingEntity livingEntity) { reason = (this.getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED); } if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { - ArclightServer.LOGGER.warn("Unknown target reason setting {} target to {}", this, livingEntity); + ArclightServer.LOGGER.debug("Unknown target reason setting {} target to {}", this, livingEntity); } CraftLivingEntity ctarget = null; if (livingEntity != null) { @@ -133,6 +122,7 @@ public void setTarget(@Nullable LivingEntity livingEntity) { Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { arclight$targetSuccess = false; + DecorationOps.cancel().invoke(); return; } if (event.getTarget() != null) { @@ -140,14 +130,8 @@ public void setTarget(@Nullable LivingEntity livingEntity) { } else { livingEntity = null; } - var newTarget = this.bridge$forge$onLivingChangeTarget((LivingEntity) (Object) this, livingEntity, LivingTargetType.MOB_TARGET); - if (newTarget == null) { - arclight$targetSuccess = false; - return; - } - livingEntity = newTarget; } - this.target = livingEntity; + DecorationOps.callsite().invoke(instance, livingEntity); arclight$targetSuccess = true; } @@ -177,11 +161,6 @@ public boolean setTarget(LivingEntity livingEntity, EntityTargetEvent.TargetReas arclight$fireEvent = fireEvent; } - @Redirect(method = "addAdditionalSaveData", at = @At(value = "FIELD", ordinal = 0, opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/world/entity/Mob;leashHolder:Lnet/minecraft/world/entity/Entity;")) - private Entity arclight$skipLeaseSave(Mob instance) { - return this.pluginRemoved ? null : instance.getLeashHolder(); - } - @Inject(method = "addAdditionalSaveData", at = @At("HEAD")) private void arclight$setAware(CompoundTag compound, CallbackInfo ci) { compound.putBoolean("Bukkit.Aware", this.aware); @@ -254,98 +233,30 @@ public ItemStack equipItemIfPossible(ItemStack stack) { forceDrops = false; } - if (equipmentslottype.isArmor() && stack.getCount() > 1) { - ItemStack itemstack1 = stack.copyWithCount(1); - this.setItemSlotAndDropWhenKilled(equipmentslottype, itemstack1); - return itemstack1; - } else { - this.setItemSlotAndDropWhenKilled(equipmentslottype, stack); - return stack; - } + var itemstack2 = equipmentslottype.limit(stack); + this.setItemSlotAndDropWhenKilled(equipmentslottype, itemstack2); + return itemstack2; } else { return ItemStack.EMPTY; } } - @Inject(method = "interact", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;dropLeash(ZZ)V")) - private void arclight$unleash(Player player, InteractionHand hand, CallbackInfoReturnable cir) { - if (CraftEventFactory.callPlayerUnleashEntityEvent((Mob) (Object) this, player, hand).isCancelled()) { - ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket((Mob) (Object) this, this.getLeashHolder())); - cir.setReturnValue(InteractionResult.PASS); - } - } - - @Inject(method = "checkAndHandleImportantInteractions", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;setLeashedTo(Lnet/minecraft/world/entity/Entity;Z)V")) - private void arclight$leash(Player player, InteractionHand hand, CallbackInfoReturnable cir) { - if (CraftEventFactory.callPlayerLeashEntityEvent((Mob) (Object) this, player, player, hand).isCancelled()) { - ((ServerPlayer) player).connection.send(new ClientboundSetEntityLinkPacket((Mob) (Object) this, this.getLeashHolder())); - cir.setReturnValue(InteractionResult.PASS); - } - } - - @Inject(method = "tickLeash", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;dropLeash(ZZ)V")) - public void arclight$unleash2(CallbackInfo ci) { - Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), this.isAlive() ? - EntityUnleashEvent.UnleashReason.HOLDER_GONE : EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH)); - } - - @ModifyArg(method = "tickLeash", index = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;dropLeash(ZZ)V")) - private boolean arclight$skipOnPluginRemove(boolean b) { - return !this.pluginRemoved; - } - - @Inject(method = "dropLeash", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Mob;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) - public void arclight$leashDropPost(boolean sendPacket, boolean dropLead, CallbackInfo ci) { - this.forceDrops = false; - } - - @Inject(method = "dropLeash", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) - public void arclight$leashDropPre(boolean sendPacket, boolean dropLead, CallbackInfo ci) { - this.forceDrops = true; - } - - @Inject(method = "restoreLeashFromSave", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/Mob;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) - private void arclight$leashRestorePost(CallbackInfo ci) { - this.forceDrops = false; - } - - @Inject(method = "restoreLeashFromSave", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) - private void arclight$leashRestorePre(CallbackInfo ci) { - this.forceDrops = true; - } - @Inject(method = "startRiding", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;dropLeash(ZZ)V")) private void arclight$unleashRide(Entity entityIn, boolean force, CallbackInfoReturnable cir) { Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); } - @Inject(method = "removeAfterChangingDimensions", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Mob;dropLeash(ZZ)V")) - private void arclight$unleashDead(CallbackInfo ci) { - Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); - } - - private transient boolean arclight$cancelSpawn; - - @Redirect(method = "convertTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$copySpawn(net.minecraft.world.level.Level world, Entity entityIn) { + @Decorate(method = "convertTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$copySpawn(net.minecraft.world.level.Level world, Entity entityIn) throws Throwable { EntityTransformEvent.TransformReason transformReason = arclight$transform == null ? EntityTransformEvent.TransformReason.UNKNOWN : arclight$transform; arclight$transform = null; if (CraftEventFactory.callEntityTransformEvent((Mob) (Object) this, (LivingEntity) entityIn, transformReason).isCancelled()) { - arclight$cancelSpawn = true; - return false; + return (boolean) DecorationOps.cancel().invoke((Mob) null); } else { - return world.addFreshEntity(entityIn); + return (boolean) DecorationOps.callsite().invoke(world, entityIn); } } - @Inject(method = "convertTo", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private void arclight$cancelSpawn(EntityType entityType, boolean bl, CallbackInfoReturnable cir) { - if (arclight$cancelSpawn) { - cir.setReturnValue(null); - } - arclight$cancelSpawn = false; - } - @Inject(method = "convertTo", at = @At("RETURN")) private void arclight$cleanReason(EntityType p_233656_1_, boolean p_233656_2_, CallbackInfoReturnable cir) { ((WorldBridge) this.level()).bridge$pushAddEntityReason(null); @@ -370,15 +281,6 @@ public T convertTo(EntityType entityType, boolean flag, Entit this.arclight$transform = transformReason; } - @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - public void arclight$attackCombust(Entity entity, int seconds) { - EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), seconds); - org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); - if (!combustEvent.isCancelled()) { - ((EntityBridge) entity).bridge$setOnFire(combustEvent.getDuration(), false); - } - } - @Inject(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V")) private void arclight$attackKnockback(Entity entity, CallbackInfoReturnable cir) { ((LivingEntityBridge) entity).bridge$pushKnockbackCause((Entity) (Object) this, EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); @@ -389,11 +291,6 @@ public T convertTo(EntityType entityType, boolean flag, Entit this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - @Override - public ResourceLocation bridge$getLootTable() { - return this.getDefaultLootTable(); - } - @Override public boolean bridge$isPersistenceRequired() { return this.persistenceRequired; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/NeutralMobMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/NeutralMobMixin.java new file mode 100644 index 000000000..3537e5a78 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/NeutralMobMixin.java @@ -0,0 +1,38 @@ +package io.izzel.arclight.common.mixin.core.world.entity; + +import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.NeutralMob; +import org.bukkit.event.entity.EntityTargetEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import javax.annotation.Nullable; + +@Mixin(NeutralMob.class) +public interface NeutralMobMixin { + + @Shadow + void setTarget(@org.jetbrains.annotations.Nullable LivingEntity livingEntity); + + @Decorate(method = "readPersistentAngerSaveData", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/NeutralMob;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$targetReason() { + if (this instanceof MobEntityBridge b) { + b.bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.UNKNOWN, false); + } + } + + default boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { + if (this instanceof MobEntityBridge b) { + b.bridge$pushGoalTargetReason(reason, fireEvent); + } + this.setTarget(entityliving); + if (this instanceof MobEntityBridge b) { + return b.bridge$lastGoalTargetResult(); + } else { + return true; + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/PathfinderMobMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/PathfinderMobMixin.java index f22c61d33..1a1fde05e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/PathfinderMobMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/PathfinderMobMixin.java @@ -11,8 +11,4 @@ @Mixin(PathfinderMob.class) public abstract class PathfinderMobMixin extends MobMixin { - @Inject(method = "tickLeash", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/PathfinderMob;dropLeash(ZZ)V")) - private void arclight$unleashDistance(CallbackInfo ci) { - Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StartAttackingMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StartAttackingMixin.java index b0faf0a0c..f39400979 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StartAttackingMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StartAttackingMixin.java @@ -1,68 +1,38 @@ package io.izzel.arclight.common.mixin.core.world.entity.ai.behavior; -import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; +import com.mojang.datafixers.kinds.K1; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.ai.behavior.BehaviorControl; import net.minecraft.world.entity.ai.behavior.StartAttacking; -import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; -import net.minecraft.world.entity.ai.memory.MemoryModuleType; +import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityTargetEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; +import org.spongepowered.asm.mixin.injection.At; @Mixin(StartAttacking.class) public class StartAttackingMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public static BehaviorControl create(Predicate p_259618_, Function> p_259435_) { - return BehaviorBuilder.create((p_258782_) -> { - return p_258782_.group(p_258782_.absent(MemoryModuleType.ATTACK_TARGET), p_258782_.registered(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE)).apply(p_258782_, (p_258778_, p_258779_) -> { - return (p_258773_, p_258774_, p_258775_) -> { - if (!p_259618_.test(p_258774_)) { - return false; - } else { - Optional optional = p_259435_.apply(p_258774_); - if (optional.isEmpty()) { - return false; - } else { - LivingEntity livingentity = optional.get(); - if (!p_258774_.canAttack(livingentity)) { - return false; - } else { - var newTarget = ((LivingEntityBridge) p_258774_).bridge$forge$onLivingChangeTarget(p_258774_, livingentity, LivingEntityBridge.LivingTargetType.BEHAVIOR_TARGET); - if (newTarget == null) - return false; - // CraftBukkit start - EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(p_258774_, newTarget, (newTarget instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); - if (event.isCancelled()) { - return false; - } - if (event.getTarget() == null) { - p_258778_.erase(); - return true; - } - livingentity = ((CraftLivingEntity) event.getTarget()).getHandle(); - // CraftBukkit end - p_258778_.set(livingentity); - p_258779_.erase(); - return true; - } - } - } - }; - }); - }); + @SuppressWarnings({"unchecked", "MixinAnnotationTarget"}) + @Decorate(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/behavior/declarative/MemoryAccessor;set(Ljava/lang/Object;)V")) + private static void arclight$targetEvent(MemoryAccessor instance, Value object, @Local(ordinal = -1) Mob mob) throws Throwable { + var newTarget = (LivingEntity) object; + EntityTargetEvent event = CraftEventFactory.callEntityTargetLivingEvent(mob, newTarget, (newTarget instanceof ServerPlayer) ? EntityTargetEvent.TargetReason.CLOSEST_PLAYER : EntityTargetEvent.TargetReason.CLOSEST_ENTITY); + if (event.isCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } + if (event.getTarget() == null) { + instance.erase(); + DecorationOps.cancel().invoke(false); + return; + } + object = (Value) ((CraftLivingEntity) event.getTarget()).getHandle(); + DecorationOps.callsite().invoke(instance, object); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StopAttackingIfTargetInvalidMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StopAttackingIfTargetInvalidMixin.java index 7cbee8b19..7c2c9ba20 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StopAttackingIfTargetInvalidMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/behavior/StopAttackingIfTargetInvalidMixin.java @@ -43,11 +43,10 @@ public static BehaviorControl create(Predicate if (event.isCancelled()) { return false; } - if (event.getTarget() == null) { - p_258787_.erase(); + if (event.getTarget() != null) { + p_258796_.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, ((CraftLivingEntity) event.getTarget()).getHandle()); return true; } - livingentity = ((CraftLivingEntity) event.getTarget()).getHandle(); // CraftBukkit end p_259568_.accept(p_258796_, livingentity); p_258787_.erase(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/goal/FollowOwnerGoalMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/goal/FollowOwnerGoalMixin.java deleted file mode 100644 index 98d2d2408..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ai/goal/FollowOwnerGoalMixin.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.entity.ai.goal; - -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import net.minecraft.world.entity.TamableAnimal; -import net.minecraft.world.entity.ai.goal.FollowOwnerGoal; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v.entity.CraftEntity; -import org.bukkit.event.entity.EntityTeleportEvent; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(FollowOwnerGoal.class) -public class FollowOwnerGoalMixin { - - // @formatter:off - @Shadow @Final private TamableAnimal tamable; - // @formatter:on - - private transient boolean arclight$cancelled; - - @Redirect(method = "maybeTeleportTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/TamableAnimal;moveTo(DDDFF)V")) - public void arclight$teleport(TamableAnimal tameableEntity, double x, double y, double z, float yaw, float pitch) { - CraftEntity craftEntity = this.tamable.bridge$getBukkitEntity(); - Location location = new Location(craftEntity.getWorld(), x, y, z, yaw, pitch); - EntityTeleportEvent event = new EntityTeleportEvent(craftEntity, craftEntity.getLocation(), location); - Bukkit.getPluginManager().callEvent(event); - if (!(arclight$cancelled = event.isCancelled())) { - tameableEntity.moveTo(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ(), event.getTo().getYaw(), event.getTo().getPitch()); - } - } - - @Inject(method = "maybeTeleportTo", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/navigation/PathNavigation;stop()V")) - public void arclight$returnIfFail(int x, int y, int z, CallbackInfoReturnable cir) { - if (arclight$cancelled) { - cir.setReturnValue(false); - } - arclight$cancelled = false; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/AnimalMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/AnimalMixin.java index 52af9f5ff..fb28ef4c7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/AnimalMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/AnimalMixin.java @@ -46,8 +46,12 @@ public abstract class AnimalMixin extends AgeableMobMixin implements AnimalEntit * @reason */ @Overwrite - public boolean hurt(DamageSource source, float amount) { - return super.hurt(source, amount); + protected void actuallyHurt(DamageSource arg, float f) { + super.actuallyHurt(arg, f); + if (!arclight$damageResult) { + return; + } + this.resetLove(); } @Inject(method = "setInLove(Lnet/minecraft/world/entity/player/Player;)V", cancellable = true, at = @At("HEAD")) @@ -90,7 +94,7 @@ public void finalizeSpawnChildFromBreeding(ServerLevel worldserver, Animal entit Optional cause = Optional.ofNullable(this.getLoveCause()).or(() -> { return Optional.ofNullable(entityanimal.getLoveCause()); }); - int experience = this.getRandom().nextInt(7) + 1; + int experience = this.random.nextInt(7) + 1; if (entityageable != null) { org.bukkit.event.entity.EntityBreedEvent entityBreedEvent = CraftEventFactory.callEntityBreedEvent(entityageable, (Animal) (Object) this, entityanimal, cause.orElse(null), this.breedItem, experience); if (entityBreedEvent.isCancelled()) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BeeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BeeMixin.java index 91299ae39..0e9b0ce32 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BeeMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BeeMixin.java @@ -24,8 +24,8 @@ public abstract class BeeMixin extends AnimalMixin { @Inject(method = "addAdditionalSaveData", at = @At("RETURN")) private void arclight$removePos(CompoundTag tag, CallbackInfo ci) { if (this.arclight$saveNotIncludeAll) { - tag.remove("HivePos"); - tag.remove("FlowerPos"); + tag.remove("hive_pos"); + tag.remove("flower_pos"); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BucketableMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BucketableMixin.java index c5a020cd0..85d2d592d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BucketableMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/BucketableMixin.java @@ -2,7 +2,6 @@ import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -42,7 +41,7 @@ static Optional bucketM itemstack1 = CraftItemStack.asNMSCopy(event.getEntityBucket()); if (event.isCancelled()) { player.containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket - ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone + entity.bridge$getBukkitEntity().update((ServerPlayer) player); // We need to play out these packets as the client assumes the fish is gone ((SynchedEntityDataBridge) livingEntity.getEntityData()).bridge$refresh((ServerPlayer) player); // Need to send data such as the display name to client return Optional.of(InteractionResult.FAIL); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/CatMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/CatMixin.java index c868b11b5..cdc5fdce6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/CatMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/CatMixin.java @@ -1,19 +1,19 @@ package io.izzel.arclight.common.mixin.core.world.entity.animal; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.animal.Cat; import net.minecraft.world.entity.player.Player; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; -// how can we not having cats before @Mixin(Cat.class) public abstract class CatMixin extends AnimalMixin { - @Redirect(method = "mobInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I")) - private int arclight$tame(RandomSource instance, int i, Player player) { - var ret = instance.nextInt(i); + @Decorate(method = "tryToTame", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I")) + private int arclight$tame(RandomSource instance, int i, Player player) throws Throwable { + var ret = (int) DecorationOps.callsite().invoke(instance, i); return ret == 0 && this.bridge$common$animalTameEvent(player) ? ret : 1; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/SheepMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/SheepMixin.java index d0932e32f..eebe46808 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/SheepMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/SheepMixin.java @@ -1,13 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.entity.animal; -import io.izzel.arclight.common.bridge.core.inventory.CraftingInventoryBridge; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.CraftingContainer; -import net.minecraft.world.inventory.ResultContainer; -import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.event.CraftEventFactory; @@ -42,11 +38,6 @@ public abstract class SheepMixin extends AnimalMixin { } } - @Inject(method = "makeContainer", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) - private static void arclight$resultInv(DyeColor color, DyeColor color1, CallbackInfoReturnable cir, CraftingContainer craftingInventory) { - ((CraftingInventoryBridge) craftingInventory).bridge$setResultInventory(new ResultContainer()); - } - // Forge: ShearsItem#interactLivingEntity @Inject(method = "mobInteract", require = 0, cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Sheep;shear(Lnet/minecraft/sounds/SoundSource;)V")) private void arclight$onShear(Player player, InteractionHand hand, CallbackInfoReturnable cir, ItemStack stack) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/TameableAnimalMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/TameableAnimalMixin.java index 9934fdd2f..021018fa2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/TameableAnimalMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/TameableAnimalMixin.java @@ -1,9 +1,14 @@ package io.izzel.arclight.common.mixin.core.world.entity.animal; -import io.izzel.arclight.common.mixin.core.world.entity.animal.AnimalMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.entity.TamableAnimal; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.EntityTeleportEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; @Mixin(TamableAnimal.class) public abstract class TameableAnimalMixin extends AnimalMixin { @@ -11,4 +16,15 @@ public abstract class TameableAnimalMixin extends AnimalMixin { // @formatter:off @Shadow public abstract boolean isTame(); // @formatter:on + + @Decorate(method = "maybeTeleportTo", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/TamableAnimal;moveTo(DDDFF)V")) + private void arclight$teleportEvent(TamableAnimal instance, double x, double y, double z, float yaw, float pitch) throws Throwable { + EntityTeleportEvent event = CraftEventFactory.callEntityTeleportEvent(instance, x, y, z); + if (event.isCancelled()) { + DecorationOps.cancel().invoke(false); + return; + } + Location to = event.getTo(); + DecorationOps.callsite().invoke(instance, to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/WolfMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/WolfMixin.java index dba36ba2e..6ab9aad93 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/WolfMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/WolfMixin.java @@ -21,9 +21,9 @@ public abstract class WolfMixin extends TameableAnimalMixin { private void arclight$handledBy(Wolf wolfEntity, boolean p_233687_1_) { } - @Inject(method = "setTame", at = @At("RETURN")) - private void arclight$healToMax(boolean tamed, CallbackInfo ci) { - if (tamed) { + @Inject(method = "applyTamingSideEffects", at = @At("RETURN")) + private void arclight$healToMax(CallbackInfo ci) { + if (this.isTame()) { this.setHealth(this.getMaxHealth()); } } @@ -38,7 +38,7 @@ public abstract class WolfMixin extends TameableAnimalMixin { bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.FORGOT_TARGET, true); } - @Redirect(method = "mobInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I")) + @Redirect(method = "tryToTame", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/RandomSource;nextInt(I)I")) private int arclight$tame(RandomSource instance, int i, Player player) { var ret = instance.nextInt(i); return ret == 0 && this.bridge$common$animalTameEvent(player) ? ret : 1; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/armadillo/ArmadilloMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/armadillo/ArmadilloMixin.java new file mode 100644 index 000000000..4b7f59df7 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/armadillo/ArmadilloMixin.java @@ -0,0 +1,41 @@ +package io.izzel.arclight.common.mixin.core.world.entity.animal.armadillo; + +import io.izzel.arclight.common.mixin.core.world.entity.animal.AnimalMixin; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.animal.armadillo.Armadillo; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Armadillo.class) +public abstract class ArmadilloMixin extends AnimalMixin { + + @Inject(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/armadillo/Armadillo;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private void arclight$forceDrop1(CallbackInfo ci) { + this.forceDrops = true; + } + + @Inject(method = "customServerAiStep", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/animal/armadillo/Armadillo;spawnAtLocation(Lnet/minecraft/world/level/ItemLike;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private void arclight$forceDrop2(CallbackInfo ci) { + this.forceDrops = false; + } + + @Inject(method = "brushOffScute", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/armadillo/Armadillo;spawnAtLocation(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private void arclight$forceDrop3(CallbackInfoReturnable cir) { + this.forceDrops = true; + } + + @Inject(method = "brushOffScute", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/animal/armadillo/Armadillo;spawnAtLocation(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/item/ItemEntity;")) + private void arclight$forceDrop4(CallbackInfoReturnable cir) { + this.forceDrops = false; + } + + @Inject(method = "actuallyHurt", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/animal/Animal;actuallyHurt(Lnet/minecraft/world/damagesource/DamageSource;F)V")) + private void arclight$hurtCancel(DamageSource damageSource, float f, CallbackInfo ci) { + if (!this.arclight$damageResult) { + ci.cancel(); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/camel/CamelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/camel/CamelMixin.java index d1011eb77..6f6cc63bd 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/camel/CamelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/camel/CamelMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.entity.animal.camel; import io.izzel.arclight.common.mixin.core.world.entity.animal.horse.AbstractHorseMixin; -import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.animal.camel.Camel; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -12,14 +11,4 @@ public abstract class CamelMixin extends AbstractHorseMixin { // @formatter:off @Shadow public abstract void standUpInstantly(); // @formatter:on - - @Override - protected boolean damageEntity0(DamageSource damagesource, float f) { - boolean hurt = super.damageEntity0(damagesource, f); - if (!hurt) { - return false; - } - this.standUpInstantly(); - return true; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/frog/TadpoleMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/frog/TadpoleMixin.java index 85098ab44..82607e4d7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/frog/TadpoleMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/frog/TadpoleMixin.java @@ -1,9 +1,17 @@ package io.izzel.arclight.common.mixin.core.world.entity.animal.frog; +import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.world.entity.animal.frog.Frog; import net.minecraft.world.entity.animal.frog.Tadpole; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -11,8 +19,24 @@ @Mixin(Tadpole.class) public abstract class TadpoleMixin extends PathfinderMobMixin { + // @formatter:off + @Shadow protected abstract void setAge(int i); + // @formatter:on + @Inject(method = "ageUp()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;discard()V")) private void arclight$ageUp(CallbackInfo ci) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.TRANSFORMATION); } + + @Decorate(method = "ageUp()V", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) + private void arclight$transform(@Local(ordinal = -1) Frog frog) throws Throwable { + if (CraftEventFactory.callEntityTransformEvent((Tadpole) (Object) this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { + this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled + DecorationOps.cancel().invoke(); + return; + } else { + ((ServerWorldBridge) this.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); + } + DecorationOps.blackhole().invoke(); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java index 698fb4f5f..f5282bbd9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/animal/horse/AbstractHorseMixin.java @@ -9,17 +9,25 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.ticks.ContainerSingleItem; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.entity.HumanEntity; import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.inventory.InventoryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.Arrays; +import java.util.List; + @Mixin(AbstractHorse.class) public abstract class AbstractHorseMixin extends AnimalMixin { @@ -80,4 +88,53 @@ public abstract class AbstractHorseMixin extends AnimalMixin { public int getMaxTemper() { return maxDomestication; } + + @Mixin(targets = "net/minecraft/world/entity/animal/horse/AbstractHorse$1") + public abstract static class ContainerMixin implements IInventoryBridge, ContainerSingleItem { + + @Shadow(aliases = {"field_48831", "this$0"}) private AbstractHorse outerThis; + + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; + + @Override + public List getContents() { + return Arrays.asList(this.getTheItem()); + } + + @Override + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + @Override + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + @Override + public List getViewers() { + return transaction; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + @Override + public void setMaxStackSize(int size) { + maxStack = size; + } + + @Override + public InventoryHolder getOwner() { + return (org.bukkit.entity.AbstractHorse) outerThis.bridge$getBukkitEntity(); + } + + @Override + public Location getLocation() { + return outerThis.bridge$getBukkitEntity().getLocation(); + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java index 59f2c7156..47ce80cbb 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/enderdragon/EnderDragonMixin.java @@ -7,6 +7,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; import net.minecraft.world.entity.boss.enderdragon.phases.DragonPhaseInstance; import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; @@ -146,7 +147,7 @@ private boolean checkWalls(final AABB axisalignedbb) { // TODO FIXME: exp patch for end dragon @Override - public int getExpReward() { + public int getExpReward(Entity entity) { // CraftBukkit - Moved from #tickDeath method boolean flag = this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT); short short0 = 500; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/wither/WitherBossMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/wither/WitherBossMixin.java index 48d613347..90ca2e145 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/wither/WitherBossMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/boss/wither/WitherBossMixin.java @@ -1,170 +1,69 @@ package io.izzel.arclight.common.mixin.core.world.entity.boss.wither; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerBossEvent; -import net.minecraft.util.Mth; -import net.minecraft.world.Difficulty; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.targeting.TargetingConditions; import net.minecraft.world.entity.boss.wither.WitherBoss; +import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityRegainHealthEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.entity.ExplosionPrimeEvent; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.List; - @Mixin(WitherBoss.class) public abstract class WitherBossMixin extends PathfinderMobMixin { - // @formatter:off - @Shadow public abstract int getInvulnerableTicks(); - @Shadow public abstract void setInvulnerableTicks(int time); - @Shadow @Final private int[] nextHeadUpdate; - @Shadow @Final private int[] idleHeadUpdates; - @Shadow protected abstract void performRangedAttack(int head, double x, double y, double z, boolean invulnerable); - @Shadow public abstract int getAlternativeTarget(int head); - @Shadow public abstract void setAlternativeTarget(int targetOffset, int newId); - @Shadow protected abstract void performRangedAttack(int head, LivingEntity target); - @Shadow @Final private static TargetingConditions TARGETING_CONDITIONS; - @Shadow private int destroyBlocksTick; - @Shadow @Final public ServerBossEvent bossEvent; - // @formatter:on - @Inject(method = "checkDespawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;discard()V")) private void arclight$despawn(CallbackInfo ci) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected void customServerAiStep() { - if (this.getInvulnerableTicks() > 0) { - int k1 = this.getInvulnerableTicks() - 1; - this.bossEvent.setProgress(1.0F - (float) k1 / 220.0F); - if (k1 <= 0) { - ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) { - this.level().explode((WitherBoss) (Object) this, this.getX(), this.getEyeY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); - } - if (!this.isSilent()) { - this.level().globalLevelEvent(1023, this.blockPosition(), 0); - } - } - - this.setInvulnerableTicks(k1); - if (this.tickCount % 10 == 0) { - bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); - this.heal(10.0F); - } - - } else { - super.customServerAiStep(); - - for (int i = 1; i < 3; ++i) { - if (this.tickCount >= this.nextHeadUpdate[i - 1]) { - this.nextHeadUpdate[i - 1] = this.tickCount + 10 + this.random.nextInt(10); - if (this.level().getDifficulty() == Difficulty.NORMAL || this.level().getDifficulty() == Difficulty.HARD) { - int i3 = i - 1; - int j3 = this.idleHeadUpdates[i - 1]; - this.idleHeadUpdates[i3] = this.idleHeadUpdates[i - 1] + 1; - if (j3 > 15) { - double d0 = Mth.nextDouble(this.random, this.getX() - 10.0D, this.getX() + 10.0D); - double d1 = Mth.nextDouble(this.random, this.getY() - 5.0D, this.getY() + 5.0D); - double d2 = Mth.nextDouble(this.random, this.getZ() - 10.0D, this.getZ() + 10.0D); - this.performRangedAttack(i + 1, d0, d1, d2, true); - this.idleHeadUpdates[i - 1] = 0; - } - } - - int l1 = this.getAlternativeTarget(i); - if (l1 > 0) { - LivingEntity livingentity = (LivingEntity) this.level().getEntity(l1); - if (livingentity != null && this.canAttack(livingentity) && !(this.distanceToSqr(livingentity) > 900.0D) && this.hasLineOfSight(livingentity)) { - this.performRangedAttack(i + 1, livingentity); - this.nextHeadUpdate[i - 1] = this.tickCount + 40 + this.random.nextInt(20); - this.idleHeadUpdates[i - 1] = 0; - } else { - if (CraftEventFactory.callEntityTargetLivingEvent((WitherBoss) (Object) this, livingentity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) - continue; - this.setAlternativeTarget(i, 0); - } - } else { - List list = this.level().getNearbyEntities(LivingEntity.class, TARGETING_CONDITIONS, (WitherBoss) (Object) this, this.getBoundingBox().inflate(20.0D, 8.0D, 20.0D)); - if (!list.isEmpty()) { - LivingEntity livingentity1 = list.get(this.random.nextInt(list.size())); - if (CraftEventFactory.callEntityTargetLivingEvent((WitherBoss) (Object) this, livingentity1, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) - continue; - this.setAlternativeTarget(i, livingentity1.getId()); - } - } - } - } + @Decorate(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) + private Explosion arclight$explodeEvent(Level instance, Entity arg, double d, double e, double f, float radius, boolean fire, Level.ExplosionInteraction arg2) throws Throwable { + ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), radius, fire); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + return (Explosion) DecorationOps.callsite().invoke(instance, arg, d, e, f, event.getRadius(), event.getFire(), arg2); + } + return null; + } - if (this.getTarget() != null) { - this.setAlternativeTarget(0, this.getTarget().getId()); - } else { - this.setAlternativeTarget(0, 0); + @Decorate(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;setAlternativeTarget(II)V")) + private void arclight$targetLivingEvent(WitherBoss instance, int i, int entityId) throws Throwable { + if (i > 0 && entityId != 0) { + if (CraftEventFactory.callEntityTargetLivingEvent((WitherBoss) (Object) this, (LivingEntity) this.level().getEntity(entityId), EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) { + return; } + } + DecorationOps.callsite().invoke(instance, i, entityId); + } - if (this.destroyBlocksTick > 0) { - --this.destroyBlocksTick; - if (this.destroyBlocksTick == 0 && ((WorldBridge) this.level()).bridge$forge$mobGriefing((WitherBoss) (Object) this)) { - int j1 = Mth.floor(this.getY()); - int i2 = Mth.floor(this.getX()); - int j2 = Mth.floor(this.getZ()); - boolean flag = false; - - for (int j = -1; j <= 1; ++j) { - for (int k2 = -1; k2 <= 1; ++k2) { - for (int k = 0; k <= 3; ++k) { - int l2 = i2 + j; - int l = j1 + k; - int i1 = j2 + k2; - BlockPos blockpos = new BlockPos(l2, l, i1); - BlockState blockstate = this.level().getBlockState(blockpos); - if (((BlockBridge) blockstate.getBlock()).bridge$forge$canEntityDestroy(blockstate, this.level(), blockpos, (WitherBoss) (Object) this) - && this.bridge$forge$onEntityDestroyBlock((WitherBoss) (Object) this, blockpos, blockstate)) { - if (!CraftEventFactory.callEntityChangeBlockEvent((WitherBoss) (Object) this, blockpos, Blocks.AIR.defaultBlockState())) { - continue; - } - flag = this.level().destroyBlock(blockpos, true, (WitherBoss) (Object) this) || flag; - } - } - } - } - - if (flag) { - this.level().levelEvent(null, 1022, this.blockPosition(), 0); - } - } - } + @Decorate(method = "customServerAiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;destroyBlock(Lnet/minecraft/core/BlockPos;ZLnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$damageBlock(Level instance, BlockPos blockPos, boolean b, Entity entity) throws Throwable { + if (!CraftEventFactory.callEntityChangeBlockEvent((WitherBoss) (Object) this, blockPos, Blocks.AIR.defaultBlockState())) { + return false; + } + return (boolean) DecorationOps.callsite().invoke(instance, blockPos, b, entity); + } - if (this.tickCount % 20 == 0) { - bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN); - this.heal(1.0F); - } + @Inject(method = "customServerAiStep", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;heal(F)V")) + private void arclight$healReason(CallbackInfo ci) { + bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); + } - this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth()); - } + @Inject(method = "customServerAiStep", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;heal(F)V")) + private void arclight$healReason2(CallbackInfo ci) { + bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ArmorStandMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ArmorStandMixin.java index 53ba7656a..89195c66a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ArmorStandMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ArmorStandMixin.java @@ -7,6 +7,7 @@ import io.izzel.arclight.common.mixin.core.world.entity.LivingEntityMixin; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.item.ItemEntity; @@ -56,7 +57,7 @@ public float getBukkitYaw() { if (CraftEventFactory.handleNonLivingEntityDamageEvent((net.minecraft.world.entity.decoration.ArmorStand) (Object) this, source, amount)) { cir.setReturnValue(false); } else { - arclight$callEntityDeath(); + arclight$callEntityDeath(source); } } @@ -72,23 +73,28 @@ public float getBukkitYaw() { return false; } + @Inject(method = "hurt", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) + private void arclight$damageDeath0(DamageSource source, float amount, CallbackInfoReturnable cir) { + arclight$callEntityDeath(source); + } + @Inject(method = "hurt", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) private void arclight$damageDeath1(DamageSource source, float amount, CallbackInfoReturnable cir) { - arclight$callEntityDeath(); + arclight$callEntityDeath(source); } @Inject(method = "hurt", at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) private void arclight$damageDeath2(DamageSource source, float amount, CallbackInfoReturnable cir) { - arclight$callEntityDeath(); + arclight$callEntityDeath(source); } @Inject(method = "causeDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;kill()V")) - private void arclight$deathEvent2(DamageSource source, float p_213817_2_, CallbackInfo ci) { - arclight$callEntityDeath(); + private void arclight$deathEvent2(ServerLevel serverLevel, DamageSource damageSource, float f, CallbackInfo ci) { + arclight$callEntityDeath(damageSource); } - @Redirect(method = "brokenByAnything", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;dropAllDeathLoot(Lnet/minecraft/world/damagesource/DamageSource;)V")) - private void arclight$dropLater(net.minecraft.world.entity.decoration.ArmorStand entity, DamageSource damageSourceIn) { + @Redirect(method = "brokenByAnything", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/ArmorStand;dropAllDeathLoot(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V")) + private void arclight$dropLater(net.minecraft.world.entity.decoration.ArmorStand instance, ServerLevel serverLevel, DamageSource damageSource) { } @Redirect(method = "brokenByAnything", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/Block;popResource(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;)V")) @@ -97,8 +103,8 @@ public float getBukkitYaw() { } @Inject(method = "brokenByAnything", at = @At("RETURN")) - private void arclight$spawnLast(DamageSource source, CallbackInfo ci) { - this.dropAllDeathLoot(source); + private void arclight$spawnLast(ServerLevel serverLevel, DamageSource damageSource, CallbackInfo ci) { + this.dropAllDeathLoot(serverLevel, damageSource); } @Override @@ -106,11 +112,6 @@ protected boolean shouldDropExperience() { return true; } - @Inject(method = "kill", at = @At("HEAD")) - private void arclight$deathEvent(CallbackInfo ci) { - arclight$callEntityDeath(); - } - private void arclight$tryCaptureDrops(Level worldIn, BlockPos pos, ItemStack stack) { if (!worldIn.isClientSide && !stack.isEmpty() && worldIn.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && !((WorldBridge) worldIn).bridge$forge$restoringBlockSnapshots()) { // do not drop items while restoring blockstates, prevents item dupe ItemEntity itementity = new ItemEntity(worldIn, pos.getX(), pos.getY(), pos.getZ(), stack); @@ -121,7 +122,7 @@ protected boolean shouldDropExperience() { } } - private void arclight$callEntityDeath() { + private void arclight$callEntityDeath(DamageSource damageSource) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DEATH); Collection captureDrops = this.bridge$common$getCapturedDrops(); List drops; @@ -132,10 +133,10 @@ protected boolean shouldDropExperience() { } else { drops = captureDrops.stream().map(ItemEntity::getItem).map(CraftItemStack::asCraftMirror).collect(Collectors.toList()); } - CraftEventFactory.callEntityDeathEvent((net.minecraft.world.entity.decoration.ArmorStand) (Object) this, drops); + CraftEventFactory.callEntityDeathEvent((net.minecraft.world.entity.decoration.ArmorStand) (Object) this, (damageSource == null ? this.damageSources().genericKill() : damageSource), drops); } - @Inject(method = "swapItem", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;getAbilities()Lnet/minecraft/world/entity/player/Abilities;")) + @Inject(method = "swapItem", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;hasInfiniteMaterials()Z")) public void arclight$manipulateEvent(net.minecraft.world.entity.player.Player playerEntity, net.minecraft.world.entity.EquipmentSlot slotType, ItemStack itemStack, InteractionHand hand, CallbackInfoReturnable cir) { ItemStack itemStack1 = this.getItemBySlot(slotType); @@ -156,11 +157,11 @@ protected boolean shouldDropExperience() { } @Override - public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slotIn, ItemStack stack, boolean silent) { + public void onEquipItem(net.minecraft.world.entity.EquipmentSlot slotIn, ItemStack stack, boolean silent) { switch (slotIn.getType()) { case HAND -> this.bridge$playEquipSound(slotIn, this.handItems.set(slotIn.getIndex(), stack), stack, silent); - case ARMOR -> + case HUMANOID_ARMOR -> this.bridge$playEquipSound(slotIn, this.armorItems.set(slotIn.getIndex(), stack), stack, silent); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ItemFrameMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ItemFrameMixin.java index fcc0b7ea6..723f3a92f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ItemFrameMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/ItemFrameMixin.java @@ -1,6 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.entity.decoration; -import io.izzel.arclight.common.mixin.core.world.entity.item.HangingEntityMixin; +import io.izzel.arclight.common.mixin.core.world.entity.item.BlockAttachedEntityMixin; import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -12,6 +12,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Final; @@ -22,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ItemFrame.class) -public abstract class ItemFrameMixin extends HangingEntityMixin { +public abstract class ItemFrameMixin extends BlockAttachedEntityMixin { // @formatter:off @Shadow @Final private static EntityDataAccessor DATA_ITEM; @@ -53,34 +54,12 @@ public void setItem(ItemStack itemstack, final boolean flag, final boolean playS @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) private static AABB calculateBoundingBox(Entity entity, BlockPos blockPosition, Direction direction, int width, int height) { - double d0 = 0.46875; - double locX = blockPosition.getX() + 0.5 - direction.getStepX() * 0.46875; - double locY = blockPosition.getY() + 0.5 - direction.getStepY() * 0.46875; - double locZ = blockPosition.getZ() + 0.5 - direction.getStepZ() * 0.46875; - if (entity != null) { - entity.setPosRaw(locX, locY, locZ); - } - double d2 = width; - double d3 = height; - double d4 = width; + float f = 0.46875F; + Vec3 vec3d = Vec3.atCenterOf(blockPosition).relative(direction, -0.46875D); Direction.Axis enumdirection_enumaxis = direction.getAxis(); - switch (enumdirection_enumaxis) { - case X: { - d2 = 1.0; - break; - } - case Y: { - d3 = 1.0; - break; - } - case Z: { - d4 = 1.0; - break; - } - } - d2 /= 32.0; - d3 /= 32.0; - d4 /= 32.0; - return new AABB(locX - d2, locY - d3, locZ - d4, locX + d2, locY + d3, locZ + d4); + double d0 = enumdirection_enumaxis == Direction.Axis.X ? 0.0625D : 0.75D; + double d1 = enumdirection_enumaxis == Direction.Axis.Y ? 0.0625D : 0.75D; + double d2 = enumdirection_enumaxis == Direction.Axis.Z ? 0.0625D : 0.75D; + return AABB.ofSize(vec3d, d0, d1, d2); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/LeashFenceKnotEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/LeashFenceKnotEntityMixin.java index 47ee168f4..fc2da0bfe 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/LeashFenceKnotEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/LeashFenceKnotEntityMixin.java @@ -1,15 +1,16 @@ package io.izzel.arclight.common.mixin.core.world.entity.decoration; -import io.izzel.arclight.common.mixin.core.world.entity.item.HangingEntityMixin; +import io.izzel.arclight.common.mixin.core.world.entity.item.BlockAttachedEntityMixin; import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.LeadItem; import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.AABB; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Mixin; @@ -18,7 +19,7 @@ import java.util.List; @Mixin(LeashFenceKnotEntity.class) -public abstract class LeashFenceKnotEntityMixin extends HangingEntityMixin { +public abstract class LeashFenceKnotEntityMixin extends BlockAttachedEntityMixin { /** * @author IzzelAliz @@ -31,29 +32,37 @@ public InteractionResult interact(final Player entityhuman, final InteractionHan return InteractionResult.SUCCESS; } boolean flag = false; - final double d0 = 7.0; - final List list = this.level().getEntitiesOfClass(Mob.class, new AABB(this.getX() - 7.0, this.getY() - 7.0, this.getZ() - 7.0, this.getX() + 7.0, this.getY() + 7.0, this.getZ() + 7.0)); - for (final Mob entityinsentient : list) { - if (entityinsentient.getLeashHolder() == entityhuman) { - if (CraftEventFactory.callPlayerLeashEntityEvent(entityinsentient, (LeashFenceKnotEntity) (Object) this, entityhuman, enumhand).isCancelled()) { - ((ServerPlayer) entityhuman).connection.send(new ClientboundSetEntityLinkPacket(entityinsentient, entityinsentient.getLeashHolder())); - } else { - entityinsentient.setLeashedTo((LeashFenceKnotEntity) (Object) this, true); - flag = true; + List list = LeadItem.leashableInArea(this.level(), this.getPos(), (leashable) -> { + Entity entity = leashable.getLeashHolder(); + + return entity == entityhuman || entity == (Object) this; + }); + for (var leashable : list) { + if (leashable.getLeashHolder() == entityhuman) { + if (leashable instanceof Entity entity) { + if (CraftEventFactory.callPlayerLeashEntityEvent(entity, (LeashFenceKnotEntity) (Object) this, entityhuman, enumhand).isCancelled()) { + ((ServerPlayer) entityhuman).connection.send(new ClientboundSetEntityLinkPacket(entity, leashable.getLeashHolder())); + flag = true; + continue; + } } + leashable.setLeashedTo((LeashFenceKnotEntity) (Object) this, true); + flag = true; } } boolean flag1 = false; if (!flag) { boolean die = true; - for (final Mob entityinsentient : list) { - if (entityinsentient.isLeashed() && entityinsentient.getLeashHolder() == (Object) this) { - if (CraftEventFactory.callPlayerUnleashEntityEvent(entityinsentient, entityhuman, enumhand).isCancelled()) { - die = false; - } else { - entityinsentient.dropLeash(true, !entityhuman.getAbilities().instabuild); - flag1 = true; + for (var leashable : list) { + if (leashable.isLeashed() && leashable.getLeashHolder() == (Object) this) { + if (leashable instanceof Entity entity) { + if (CraftEventFactory.callPlayerUnleashEntityEvent(entity, entityhuman, enumhand).isCancelled()) { + die = false; + continue; + } } + leashable.dropLeash(true, !entityhuman.getAbilities().instabuild); + flag1 = true; } } if (die) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/PaintingMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/PaintingMixin.java new file mode 100644 index 000000000..083e5318f --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/decoration/PaintingMixin.java @@ -0,0 +1,40 @@ +package io.izzel.arclight.common.mixin.core.world.entity.decoration; + +import io.izzel.arclight.common.mixin.core.world.entity.item.BlockAttachedEntityMixin; +import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.decoration.Painting; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(Painting.class) +public abstract class PaintingMixin extends BlockAttachedEntityMixin { + + @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) + private static AABB calculateBoundingBoxStatic(BlockPos blockposition, Direction enumdirection, int width, int height) { + // CraftBukkit end + float f = 0.46875F; + Vec3 vec3d = Vec3.atCenterOf(blockposition).relative(enumdirection, -0.46875D); + // CraftBukkit start + double d0 = offsetForPaintingSize0(width); + double d1 = offsetForPaintingSize0(height); + // CraftBukkit end + Direction enumdirection1 = enumdirection.getCounterClockWise(); + Vec3 vec3d1 = vec3d.relative(enumdirection1, d0).relative(Direction.UP, d1); + Direction.Axis enumdirection_enumaxis = enumdirection.getAxis(); + // CraftBukkit start + double d2 = enumdirection_enumaxis == Direction.Axis.X ? 0.0625D : (double) width; + double d3 = (double) height; + double d4 = enumdirection_enumaxis == Direction.Axis.Z ? 0.0625D : (double) width; + // CraftBukkit end + + return AABB.ofSize(vec3d1, d2, d3, d4); + } + + private static double offsetForPaintingSize0(int i) { + return i % 2 == 0 ? 0.5D : 0.0D; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/HangingEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/BlockAttachedEntityMixin.java similarity index 85% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/HangingEntityMixin.java rename to arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/BlockAttachedEntityMixin.java index 955078783..3dbf23c3b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/HangingEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/BlockAttachedEntityMixin.java @@ -1,6 +1,5 @@ package io.izzel.arclight.common.mixin.core.world.entity.item; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; import net.minecraft.core.BlockPos; @@ -10,7 +9,7 @@ import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.MoverType; -import net.minecraft.world.entity.decoration.HangingEntity; +import net.minecraft.world.entity.decoration.BlockAttachedEntity; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; @@ -26,11 +25,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -@Mixin(HangingEntity.class) -public abstract class HangingEntityMixin extends EntityMixin { +@Mixin(BlockAttachedEntity.class) +public abstract class BlockAttachedEntityMixin extends EntityMixin { // @formatter:off - @Shadow public BlockPos pos; + @Shadow protected BlockPos pos; + @Shadow public abstract BlockPos getPos(); // @formatter:on @Inject(method = "addAdditionalSaveData", cancellable = true, at = @At("HEAD")) @@ -40,7 +40,7 @@ public abstract class HangingEntityMixin extends EntityMixin { } } - @Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/HangingEntity;discard()V")) + @Inject(method = "tick", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;discard()V")) private void arclight$hangingBreak(CallbackInfo ci) { var state = this.level().getBlockState(new BlockPos(this.blockPosition())); HangingBreakEvent.RemoveCause cause; @@ -58,12 +58,12 @@ public abstract class HangingEntityMixin extends EntityMixin { } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/HangingEntity;kill()V")) + @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;kill()V")) private void arclight$hangingBreakByAttack(DamageSource source, float amount, CallbackInfoReturnable cir) { - Entity damager = (source.isIndirect()) ? source.getEntity() : source.getDirectEntity(); + Entity damager = (source.isDirect()) ? source.getDirectEntity() : source.getEntity(); HangingBreakEvent event; if (damager != null) { - event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), ((EntityBridge) damager).bridge$getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); + event = new HangingBreakByEntityEvent((Hanging) this.getBukkitEntity(), damager.bridge$getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.ENTITY); } else { event = new HangingBreakEvent((Hanging) this.getBukkitEntity(), source.is(DamageTypeTags.IS_EXPLOSION) ? HangingBreakEvent.RemoveCause.EXPLOSION : HangingBreakEvent.RemoveCause.DEFAULT); } @@ -73,7 +73,7 @@ public abstract class HangingEntityMixin extends EntityMixin { } } - @Inject(method = "move", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/HangingEntity;kill()V")) + @Inject(method = "move", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/decoration/BlockAttachedEntity;kill()V")) private void arclight$hangingBreakByMove(MoverType typeIn, Vec3 pos, CallbackInfo ci) { if (this.isRemoved()) { ci.cancel(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/ItemEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/ItemEntityMixin.java index 9b88517a3..a597ac25d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/ItemEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/ItemEntityMixin.java @@ -8,8 +8,10 @@ import io.izzel.arclight.common.bridge.core.network.datasync.SynchedEntityDataBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.stats.Stats; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; @@ -23,7 +25,6 @@ import org.bukkit.event.player.PlayerPickupItemEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -69,79 +70,56 @@ public abstract class ItemEntityMixin extends EntityMixin implements ItemEntityB this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DEATH); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void playerTouch(final Player entity) { - if (!this.level().isClientSide) { - if (this.pickupDelay > 0) return; - ItemStack itemstack = this.getItem(); - int i = itemstack.getCount(); + @Decorate(method = "playerTouch", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/item/ItemStack;getCount()I")) + private int arclight$playerPickup(ItemStack instance, Player entity, @Local(ordinal = -1) ItemStack itemstack) throws Throwable { + var count = (int) DecorationOps.callsite().invoke(instance); - int hook = this.bridge$forge$onItemPickup(entity); - if (hook < 0) return; - - final int canHold = ((PlayerInventoryBridge) entity.getInventory()).bridge$canHold(itemstack); - final int remaining = itemstack.getCount() - canHold; - if (this.pickupDelay <= 0 && canHold > 0) { - itemstack.setCount(canHold); - final PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent(((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(), (Item) this.getBukkitEntity(), remaining); - playerEvent.setCancelled(!((PlayerEntityBridge) entity).bridge$canPickUpLoot()); - Bukkit.getPluginManager().callEvent(playerEvent); - if (playerEvent.isCancelled()) { - itemstack.setCount(canHold + remaining); - return; - } - final EntityPickupItemEvent entityEvent = new EntityPickupItemEvent(((LivingEntityBridge) entity).bridge$getBukkitEntity(), (Item) this.getBukkitEntity(), remaining); - entityEvent.setCancelled(!((PlayerEntityBridge) entity).bridge$canPickUpLoot()); - Bukkit.getPluginManager().callEvent(entityEvent); - if (entityEvent.isCancelled()) { - itemstack.setCount(canHold + remaining); - return; - } - ItemStack current = this.getItem(); - if (!itemstack.equals(current)) { - itemstack = current; - } else { - itemstack.setCount(canHold + remaining); - } - this.pickupDelay = 0; - } else if (this.pickupDelay == 0 && hook != 1) { - this.pickupDelay = -1; + final int canHold = ((PlayerInventoryBridge) entity.getInventory()).bridge$canHold(itemstack); + final int remaining = count - canHold; + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); + final PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent(((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(), (Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!((PlayerEntityBridge) entity).bridge$canPickUpLoot()); + Bukkit.getPluginManager().callEvent(playerEvent); + if (playerEvent.isCancelled()) { + itemstack.setCount(canHold + remaining); + return (int) DecorationOps.cancel().invoke(); + } + final EntityPickupItemEvent entityEvent = new EntityPickupItemEvent(((LivingEntityBridge) entity).bridge$getBukkitEntity(), (Item) this.getBukkitEntity(), remaining); + entityEvent.setCancelled(!((PlayerEntityBridge) entity).bridge$canPickUpLoot()); + Bukkit.getPluginManager().callEvent(entityEvent); + if (entityEvent.isCancelled()) { + itemstack.setCount(canHold + remaining); + return (int) DecorationOps.cancel().invoke(); } - ItemStack copy = itemstack.copy(); - if (this.pickupDelay == 0 && (this.target == null /*|| 6000 - this.age <= 200*/ || this.target.equals(entity.getUUID())) && (hook == 1 || entity.getInventory().add(itemstack))) { - copy.setCount(copy.getCount() - itemstack.getCount()); - this.bridge$forge$firePlayerItemPickupEvent(entity, copy); - entity.take((ItemEntity) (Object) this, i); - if (itemstack.isEmpty()) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.PICKUP); - this.discard(); - itemstack.setCount(i); - } - entity.awardStat(Stats.ITEM_PICKED_UP.get(itemstack.getItem()), i); - entity.onItemPickup((ItemEntity) (Object) this); + ItemStack current = this.getItem(); + if (!itemstack.equals(current)) { + itemstack = current; + } else { + itemstack.setCount(canHold + remaining); } + this.pickupDelay = 0; + } else if (this.pickupDelay == 0) { + this.pickupDelay = -1; } + DecorationOps.blackhole().invoke(itemstack); + return count; } - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;discard()V"), - slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/item/ItemEntity;age:I"))) - private void arclight$itemDespawn(ItemEntity instance) { - if (this.bridge$common$itemDespawnEvent()) { - instance.discard(); - } + @Inject(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;discard()V")) + private void arclight$discardReason(Player player, CallbackInfo ci) { + this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.PICKUP); } - @Override - public boolean bridge$common$itemDespawnEvent() { + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;discard()V"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/item/ItemEntity;age:I"))) + private void arclight$itemDespawn(ItemEntity instance) throws Throwable { if (CraftEventFactory.callItemDespawnEvent((ItemEntity) (Object) this).isCancelled()) { this.age = 0; - return false; + DecorationOps.cancel().invoke(); + return; } - return true; + DecorationOps.callsite().invoke(instance); } @Inject(method = "setItem", at = @At("RETURN")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/PrimedTntMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/PrimedTntMixin.java index c0d786ced..5d958a9e5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/PrimedTntMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/item/PrimedTntMixin.java @@ -1,11 +1,17 @@ package io.izzel.arclight.common.mixin.core.world.entity.item; import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.particles.ParticleTypes; +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.MoverType; import net.minecraft.world.entity.item.PrimedTnt; +import net.minecraft.world.level.Explosion; +import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; import org.bukkit.Bukkit; import org.bukkit.entity.Explosive; @@ -24,6 +30,7 @@ public abstract class PrimedTntMixin extends EntityMixin { // @formatter:off @Shadow public abstract int getFuse(); @Shadow public abstract void setFuse(int p_32086_); + @Shadow public abstract void explode(); // @formatter:on public float yield; @@ -47,10 +54,8 @@ public abstract class PrimedTntMixin extends EntityMixin { */ @Overwrite public void tick() { - if (!this.isNoGravity()) { - this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.04D, 0.0D)); - } - + this.handlePortal(); + this.applyGravity(); this.move(MoverType.SELF, this.getDeltaMovement()); this.setDeltaMovement(this.getDeltaMovement().scale(0.98D)); if (this.onGround) { @@ -72,19 +77,16 @@ public void tick() { this.level().addParticle(ParticleTypes.SMOKE, this.getX(), this.getY() + 0.5D, this.getZ(), 0.0D, 0.0D, 0.0D); } } - } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public final void explode() { + @Decorate(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) + private Explosion arclight$explodeEvent(Level instance, Entity arg, DamageSource arg2, ExplosionDamageCalculator arg3, double d, double e, double f, float g, boolean bl, Level.ExplosionInteraction arg4) throws Throwable { ExplosionPrimeEvent event = new ExplosionPrimeEvent((Explosive) this.getBukkitEntity()); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - this.level().explode((PrimedTnt) (Object) this, this.getX(), this.getY(0.0625), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.TNT); + return (Explosion) DecorationOps.callsite().invoke(instance, arg, arg2, arg3, d, e, f, g, bl, arg4); + } else { + return null; } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/AbstractSkeletonMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/AbstractSkeletonMixin.java index b47f47cf2..b24416577 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/AbstractSkeletonMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/AbstractSkeletonMixin.java @@ -20,7 +20,7 @@ public abstract class AbstractSkeletonMixin extends PathfinderMobMixin { @Inject(method = "performRangedAttack", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/AbstractSkeleton;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void arclight$shootBow(LivingEntity target, float distanceFactor, CallbackInfo ci, ItemStack itemStack, AbstractArrow arrowEntity) { + private void arclight$shootBow(LivingEntity target, float distanceFactor, CallbackInfo ci, ItemStack itemStack, ItemStack projectile, AbstractArrow arrowEntity) { EntityShootBowEvent event = CraftEventFactory.callEntityShootBowEvent((AbstractSkeleton) (Object) this, this.getMainHandItem(), null, arrowEntity, InteractionHand.MAIN_HAND, 0.8F, true); if (event.isCancelled()) { event.getProjectile().remove(); @@ -28,7 +28,7 @@ public abstract class AbstractSkeletonMixin extends PathfinderMobMixin { return; } if (event.getProjectile() != arrowEntity.bridge$getBukkitEntity()) { - this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.random.nextFloat() * 0.4F + 0.8F)); ci.cancel(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/CreeperMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/CreeperMixin.java index ddebe8176..f55d83ef1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/CreeperMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/CreeperMixin.java @@ -10,6 +10,7 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.AreaEffectCloud; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.monster.Creeper; import net.minecraft.world.entity.player.Player; @@ -45,7 +46,7 @@ public abstract class CreeperMixin extends PathfinderMobMixin implements Creeper @Shadow public abstract boolean isPowered(); // @formatter:on - @Unique private Player entityIgniter; // CraftBukkit + @Unique public Player entityIgniter; // CraftBukkit @Inject(method = "mobInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Creeper;ignite()V")) private void arclight$catchIgniter(Player player, InteractionHand interactionHand, CallbackInfoReturnable cir) { @@ -72,11 +73,12 @@ public final void explodeCreeper() { if (!event.isCancelled()) { this.dead = true; this.level().explode((Creeper) (Object) this, - ((DamageSourceBridge) Explosion.getDefaultDamageSource(level(), (Creeper) (Object) this)).bridge$customCausingEntity(entityIgniter), null, + ((DamageSourceBridge) Explosion.getDefaultDamageSource(level(), (Creeper) (Object) this)).bridge$customCausingEntityDamager(entityIgniter), null, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.ExplosionInteraction.MOB); + this.spawnLingeringCloud(); + this.triggerOnDeathMobEffects(Entity.RemovalReason.KILLED); this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.EXPLODE); this.discard(); - this.spawnLingeringCloud(); } else { this.swell = 0; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/EnderManMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/EnderManMixin.java index ec85df72d..becba1ac9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/EnderManMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/EnderManMixin.java @@ -3,6 +3,7 @@ import io.izzel.arclight.common.bridge.core.entity.monster.EndermanEntityBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -11,10 +12,10 @@ import org.bukkit.event.entity.EntityTargetEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; - -import javax.annotation.Nullable; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EnderMan.class) public abstract class EnderManMixin extends PathfinderMobMixin implements EndermanEntityBridge { @@ -24,6 +25,7 @@ public abstract class EnderManMixin extends PathfinderMobMixin implements Enderm @Shadow @Final private static EntityDataAccessor DATA_CREEPY; @Shadow @Final private static EntityDataAccessor DATA_STARED_AT; @Shadow @Final private static AttributeModifier SPEED_MODIFIER_ATTACKING; + @Shadow @Final private static ResourceLocation SPEED_MODIFIER_ATTACKING_ID; // @formatter:on @Override @@ -37,7 +39,7 @@ public abstract class EnderManMixin extends PathfinderMobMixin implements Enderm } else { this.targetChangeTime = this.tickCount; this.entityData.set(DATA_CREEPY, true); - if (!modifiableattributeinstance.hasModifier(SPEED_MODIFIER_ATTACKING)) { + if (!modifiableattributeinstance.hasModifier(SPEED_MODIFIER_ATTACKING_ID)) { modifiableattributeinstance.addTransientModifier(SPEED_MODIFIER_ATTACKING); } } @@ -52,16 +54,10 @@ public boolean setTarget(LivingEntity livingEntity, EntityTargetEvent.TargetReas return true; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void setTarget(@Nullable LivingEntity entity) { - this.bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); - super.setTarget(entity); - if (arclight$targetSuccess) { - bridge$updateTarget(getTarget()); + @Inject(method = "setTarget", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/monster/Monster;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$returnIfFailed(LivingEntity livingEntity, CallbackInfo ci) { + if (!arclight$targetSuccess) { + ci.cancel(); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ShulkerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ShulkerMixin.java index de014ac1e..12404b41b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ShulkerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ShulkerMixin.java @@ -2,84 +2,36 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.monster.Shulker; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.AABB; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityTeleportEvent; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import javax.annotation.Nullable; - @Mixin(Shulker.class) public abstract class ShulkerMixin extends PathfinderMobMixin { - // @formatter:off - @Shadow @Nullable protected abstract Direction findAttachableSurface(BlockPos p_149811_); - @Shadow public abstract void setAttachFace(Direction p_149789_); - @Shadow @Final protected static EntityDataAccessor DATA_PEEK_ID; - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected boolean teleportSomewhere() { - if (!this.isNoAi() && this.isAlive()) { - BlockPos blockpos = this.blockPosition(); - - for (int i = 0; i < 5; ++i) { - BlockPos blockpos1 = blockpos.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); - if (blockpos1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockpos1) && this.level().getWorldBorder().isWithinBounds(blockpos1) && this.level().noCollision((Shulker) (Object) this, (new AABB(blockpos1)).deflate(1.0E-6D))) { - Direction direction = this.findAttachableSurface(blockpos1); - if (direction != null) { - var pos = bridge$forge$onEnderTeleport((Shulker) (Object) this, blockpos1.getX(), blockpos1.getY(), blockpos1.getZ()); - if (pos == null) { - direction = null; - } else { - blockpos1 = pos; - } - } - if (direction != null) { - EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), this.getBukkitEntity().getLocation(), new Location(((WorldBridge) this.level()).bridge$getWorld(), blockpos1.getX(), blockpos1.getY(), blockpos1.getZ())); - Bukkit.getPluginManager().callEvent(teleport); - if (!teleport.isCancelled()) { - Location to = teleport.getTo(); - blockpos1 = BlockPos.containing(to.getX(), to.getY(), to.getZ()); - } else { - return false; - } - this.unRide(); - this.setAttachFace(direction); - this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); - this.setPos((double) blockpos1.getX() + 0.5D, blockpos1.getY(), (double) blockpos1.getZ() + 0.5D); - this.level().gameEvent(GameEvent.TELEPORT, blockpos, GameEvent.Context.of((Entity) (Object) this)); - this.entityData.set(DATA_PEEK_ID, (byte) 0); - this.setTarget(null); - return true; - } - } - } - - return false; + @Decorate(method = "teleportSomewhere", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Shulker;unRide()V")) + private void arclight$teleportEvent(Shulker instance, @Local(ordinal = -1) BlockPos pos) throws Throwable { + EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), this.getBukkitEntity().getLocation(), new Location(this.level().bridge$getWorld(), pos.getX(), pos.getY(), pos.getZ())); + Bukkit.getPluginManager().callEvent(teleport); + if (!teleport.isCancelled()) { + Location to = teleport.getTo(); + pos = BlockPos.containing(to.getX(), to.getY(), to.getZ()); } else { - return false; + DecorationOps.cancel().invoke(false); + return; } + DecorationOps.blackhole().invoke(pos); + DecorationOps.callsite().invoke(instance); } @Inject(method = "hitByShulkerBullet", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/Silverfish_WakeUpFriendsGoalMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/Silverfish_WakeUpFriendsGoalMixin.java index a6caf5b3c..be1356f90 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/Silverfish_WakeUpFriendsGoalMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/Silverfish_WakeUpFriendsGoalMixin.java @@ -1,12 +1,11 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster; -import io.izzel.arclight.api.ArclightVersion; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.util.RandomSource; import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.monster.Silverfish; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.InfestedBlock; @@ -14,55 +13,22 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; @Mixin(targets = "net.minecraft.world.entity.monster.Silverfish$SilverfishWakeUpFriendsGoal") public abstract class Silverfish_WakeUpFriendsGoalMixin extends Goal { - @Shadow private int lookForFriends; @Shadow @Final private Silverfish silverfish; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void tick() { - --this.lookForFriends; - if (this.lookForFriends <= 0) { - Level world = this.silverfish.level(); - RandomSource random = this.silverfish.getRandom(); - BlockPos blockpos = this.silverfish.blockPosition(); - - for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { - for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) { - for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) { - BlockPos blockpos1 = blockpos.offset(j, i, k); - BlockState blockstate = world.getBlockState(blockpos1); - Block block = blockstate.getBlock(); - if (block instanceof InfestedBlock) { - if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockpos1, Blocks.AIR.defaultBlockState())) { - continue; - } - if (((WorldBridge) world).bridge$forge$mobGriefing(this.silverfish)) { - if (ArclightVersion.atLeast(ArclightVersion.v1_15)) { - world.destroyBlock(blockpos1, true, this.silverfish); - } else { - world.destroyBlock(blockpos1, true); - } - } else { - world.setBlock(blockpos1, ((InfestedBlock) block).getHostBlock().defaultBlockState(), 3); - } - - if (random.nextBoolean()) { - return; - } - } - } - } + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;getBlock()Lnet/minecraft/world/level/block/Block;")) + private Block arclight$entityChangeBlock(BlockState instance, @Local(ordinal = -1) BlockPos pos) throws Throwable { + var block = (Block) DecorationOps.callsite().invoke(instance); + if (block instanceof InfestedBlock) { + if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, pos, Blocks.AIR.defaultBlockState())) { + return Blocks.AIR; } } - + return block; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SlimeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SlimeMixin.java index f461d297e..e2844e33e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SlimeMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SlimeMixin.java @@ -40,7 +40,8 @@ public void remove(Entity.RemovalReason p_149847_) { if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) { Component itextcomponent = this.getCustomName(); boolean flag = this.isNoAi(); - float f = (float) i / 4.0F; + float f = this.getDimensions(this.getPose()).width(); + float f1 = f / 2.0F; int j = i / 2; int k = 2 + this.random.nextInt(3); @@ -56,8 +57,8 @@ public void remove(Entity.RemovalReason p_149847_) { arclight$slimes = new ArrayList<>(k); for (int l = 0; l < k; ++l) { - float f1 = ((float) (l % 2) - 0.5F) * f; - float f2 = ((float) (l / 2) - 0.5F) * f; + float f2 = ((float) (l % 2) - 0.5F) * f1; + float f3 = ((float) (l / 2) - 0.5F) * f1; net.minecraft.world.entity.monster.Slime slimeentity = this.getType().create(this.level()); if (slimeentity == null) continue; if (this.isPersistenceRequired()) { @@ -68,7 +69,7 @@ public void remove(Entity.RemovalReason p_149847_) { slimeentity.setNoAi(flag); slimeentity.setInvulnerable(this.isInvulnerable()); slimeentity.setSize(j, true); - slimeentity.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); + slimeentity.moveTo(this.getX() + (double) f2, this.getY() + 0.5D, this.getZ() + (double) f3, this.random.nextFloat() * 360.0F, 0.0F); arclight$slimes.add(slimeentity); } if (CraftEventFactory.callEntityTransformEvent((net.minecraft.world.entity.monster.Slime) (Object) this, arclight$slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { @@ -78,8 +79,8 @@ public void remove(Entity.RemovalReason p_149847_) { } for (int l = 0; l < arclight$slimes.size(); l++) { // Apotheosis compat, see https://github.com/IzzelAliz/Arclight/issues/1078 - float f1 = ((float) (l % 2) - 0.5F) * f; - float f2 = ((float) (l / 2) - 0.5F) * f; + float f2 = ((float) (l % 2) - 0.5F) * f; + float f3 = ((float) (l / 2) - 0.5F) * f; net.minecraft.world.entity.monster.Slime living = (net.minecraft.world.entity.monster.Slime) arclight$slimes.get(l); ((WorldBridge) this.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); this.level().addFreshEntity(living); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SpiderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SpiderMixin.java index afad8966f..2c6dd959d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SpiderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/SpiderMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnGroupData; @@ -17,7 +16,7 @@ public abstract class SpiderMixin extends PathfinderMobMixin { @Inject(method = "finalizeSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Spider;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - private void arclight$potionReason(ServerLevelAccessor worldIn, DifficultyInstance difficultyIn, MobSpawnType reason, SpawnGroupData spawnDataIn, CompoundTag dataTag, CallbackInfoReturnable cir) { + private void arclight$potionReason(ServerLevelAccessor serverLevelAccessor, DifficultyInstance difficultyInstance, MobSpawnType mobSpawnType, SpawnGroupData spawnGroupData, CallbackInfoReturnable cir) { bridge$pushEffectCause(EntityPotionEffectEvent.Cause.SPIDER_SPAWN); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/WitchMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/WitchMixin.java index 7c7cd7778..d572d5dbe 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/WitchMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/WitchMixin.java @@ -1,18 +1,26 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster; import io.izzel.arclight.common.mixin.core.world.entity.raider.RaiderMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.monster.Witch; +import net.minecraft.world.item.alchemy.PotionContents; import org.bukkit.event.entity.EntityPotionEffectEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.function.Consumer; @Mixin(Witch.class) public abstract class WitchMixin extends RaiderMixin { - @Inject(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Witch;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - private void arclight$reason(CallbackInfo ci) { - bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK); + @Decorate(method = "aiStep", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/alchemy/PotionContents;forEachEffect(Ljava/util/function/Consumer;)V")) + private void arclight$reason(PotionContents instance, Consumer consumer) throws Throwable { + Consumer wrapped = effect -> { + bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK); + consumer.accept(effect); + }; + DecorationOps.callsite().invoke(instance, wrapped); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieMixin.java index be205f57f..db912dfe9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieMixin.java @@ -1,19 +1,19 @@ package io.izzel.arclight.common.mixin.core.world.entity.monster; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtOps; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.MobSpawnType; import net.minecraft.world.entity.SpawnGroupData; @@ -24,12 +24,12 @@ import org.bukkit.entity.Zombie; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityCombustByEntityEvent; +import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.entity.EntityTransformEvent; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -50,41 +50,51 @@ public abstract class ZombieMixin extends PathfinderMobMixin { } } - @Redirect(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - private void arclight$entityCombust(Entity entity, int seconds) { + @Decorate(method = "doHurtTarget", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$entityCombust(Entity entity, float seconds) throws Throwable { EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), seconds); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - ((EntityBridge) entity).bridge$setOnFire(event.getDuration(), false); + DecorationOps.callsite().invoke(entity, (float) event.getDuration()); } } - @Eject(method = "killedEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;")) - private T arclight$transform(Villager villagerEntity, EntityType entityType, boolean flag, CallbackInfoReturnable cir) { + @SuppressWarnings("unchecked") + @Decorate(method = "killedEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/npc/Villager;convertTo(Lnet/minecraft/world/entity/EntityType;Z)Lnet/minecraft/world/entity/Mob;")) + private T arclight$transform(Villager villagerEntity, EntityType entityType, boolean flag) throws Throwable { ((WorldBridge) villagerEntity.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.INFECTION); ((MobEntityBridge) villagerEntity).bridge$pushTransformReason(EntityTransformEvent.TransformReason.INFECTION); - T t = villagerEntity.convertTo(entityType, flag); + T t = (T) DecorationOps.callsite().invoke(villagerEntity, entityType, flag); if (t == null) { - cir.setReturnValue(false); + return (T) DecorationOps.cancel().invoke(false); } return t; } @Inject(method = "finalizeSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private void arclight$mount(ServerLevelAccessor worldIn, DifficultyInstance difficultyIn, MobSpawnType reason, SpawnGroupData spawnDataIn, CompoundTag dataTag, CallbackInfoReturnable cir) { + private void arclight$mount(ServerLevelAccessor worldIn, DifficultyInstance difficultyIn, MobSpawnType reason, SpawnGroupData spawnDataIn, CallbackInfoReturnable cir) { ((WorldBridge) worldIn.getLevel()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.MOUNT); } + @Decorate(method = "hurt", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Zombie;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$spawnWithReasonForge(net.minecraft.world.entity.monster.Zombie zombie, LivingEntity livingEntity) throws Throwable { + ((WorldBridge) this.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); + if (livingEntity != null) { + ((MobEntityBridge) zombie).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); + } + DecorationOps.callsite().invoke(zombie, livingEntity); + } + @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) private static ZombieVillager zombifyVillager(ServerLevel level, Villager villager, BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ((WorldBridge) villager.level()).bridge$pushAddEntityReason(spawnReason); ((MobEntityBridge) villager).bridge$pushTransformReason(EntityTransformEvent.TransformReason.INFECTION); ZombieVillager zombieVillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); if (zombieVillager != null) { - zombieVillager.finalizeSpawn(level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new net.minecraft.world.entity.monster.Zombie.ZombieGroupData(false, true), null); + zombieVillager.finalizeSpawn(level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new net.minecraft.world.entity.monster.Zombie.ZombieGroupData(false, true)); zombieVillager.setVillagerData(villager.getVillagerData()); zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE)); - zombieVillager.setTradeOffers(villager.getOffers().createTag()); + zombieVillager.setTradeOffers(villager.getOffers().copy()); zombieVillager.setVillagerXp(villager.getVillagerXp()); ((LivingEntityBridge) villager).bridge$forge$onLivingConvert(villager, zombieVillager); if (!silent) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieVillagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieVillagerMixin.java index 9ebc3b0d5..1bacbb01a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieVillagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/monster/ZombieVillagerMixin.java @@ -19,7 +19,7 @@ @Mixin(net.minecraft.world.entity.monster.ZombieVillager.class) public abstract class ZombieVillagerMixin extends ZombieMixin { - @Inject(method = "startConverting", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombieVillager;removeEffect(Lnet/minecraft/world/effect/MobEffect;)Z")) + @Inject(method = "startConverting", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombieVillager;removeEffect(Lnet/minecraft/core/Holder;)Z")) private void arclight$convert1(UUID conversionStarterIn, int conversionTimeIn, CallbackInfo ci) { this.persist = true; bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONVERSION); @@ -42,12 +42,12 @@ public abstract class ZombieVillagerMixin extends ZombieMixin { return t; } - @Inject(method = "finishConversion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombieVillager;spawnAtLocation(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/item/ItemEntity;")) + @Inject(method = "finishConversion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/ZombieVillager;dropPreservedEquipment(Ljava/util/function/Predicate;)Ljava/util/Set;")) private void arclight$dropPre(ServerLevel world, CallbackInfo ci) { this.forceDrops = true; } - @Inject(method = "finishConversion", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/monster/ZombieVillager;spawnAtLocation(Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/entity/item/ItemEntity;")) + @Inject(method = "finishConversion", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/monster/ZombieVillager;dropPreservedEquipment(Ljava/util/function/Predicate;)Ljava/util/Set;")) private void arclight$dropPost(ServerLevel world, CallbackInfo ci) { this.forceDrops = false; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/PlayerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/PlayerMixin.java index 12e410fa9..130dbaca7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/PlayerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/PlayerMixin.java @@ -2,59 +2,47 @@ import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Either; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.InternalEntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; -import io.izzel.arclight.common.bridge.core.util.DamageSourceBridge; import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.mixin.core.world.entity.LivingEntityMixin; -import io.izzel.arclight.i18n.ArclightConfig; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; -import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.stats.Stat; -import net.minecraft.stats.Stats; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.Mth; import net.minecraft.util.Unit; import net.minecraft.world.Difficulty; -import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.MobType; import net.minecraft.world.entity.TamableAnimal; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Abilities; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.food.FoodData; +import net.minecraft.world.food.FoodProperties; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.inventory.PlayerEnderChestContainer; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.phys.AABB; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.Scoreboard; import org.bukkit.Bukkit; @@ -67,7 +55,6 @@ import org.bukkit.entity.Item; import org.bukkit.entity.Player; import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityExhaustionEvent; import org.bukkit.event.entity.EntityKnockbackEvent; import org.bukkit.event.entity.EntityPotionEffectEvent; @@ -76,22 +63,21 @@ import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerVelocityEvent; import org.bukkit.scoreboard.Team; -import org.bukkit.util.Vector; +import org.objectweb.asm.Opcodes; import org.spigotmc.SpigotWorldConfig; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import java.util.List; import java.util.Optional; @Mixin(net.minecraft.world.entity.player.Player.class) @@ -136,11 +122,10 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt @Shadow public abstract void setLastDeathLocation(Optional p_219750_); @Shadow public abstract Optional getLastDeathLocation(); @Shadow public abstract void setRemainingFireTicks(int p_36353_); + @Shadow public abstract boolean isCreative(); + @Shadow public abstract FoodData getFoodData(); // @formatter:on - @Shadow - public abstract boolean isCreative(); - public boolean fauxSleeping; public int oldLevel; @@ -170,7 +155,7 @@ public abstract class PlayerMixin extends LivingEntityMixin implements PlayerEnt cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "RETURN", ordinal = 1)) private void arclight$playerDropItem(ItemStack droppedItem, boolean dropAround, boolean traceItem, CallbackInfoReturnable cir, double d0, ItemEntity itemEntity) { Player player = (Player) this.getBukkitEntity(); - Item drop = (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity(); + Item drop = (Item) itemEntity.bridge$getBukkitEntity(); PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop); Bukkit.getPluginManager().callEvent(event); @@ -258,174 +243,69 @@ public boolean canHarmPlayer(final net.minecraft.world.entity.player.Player enti return !team.hasPlayer(Bukkit.getOfflinePlayer(this.getScoreboardName())); } - @Inject(method = "actuallyHurt", cancellable = true, at = @At("HEAD")) - private void arclight$damageEntityCustom(DamageSource damageSrc, float damageAmount, CallbackInfo ci) { - damageEntity0(damageSrc, damageAmount); - ci.cancel(); + @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;resetAttackStrengthTicker()V")) + private void arclight$skipResetAttackStrength(net.minecraft.world.entity.player.Player instance) { } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void attack(final Entity entity) { - if (entity.isAttackable() && !entity.skipAttackInteraction((net.minecraft.world.entity.player.Player) (Object) this)) { - float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); - float f2; - if (entity instanceof LivingEntity) { - f2 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) entity).getMobType()); - } else { - f2 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), MobType.UNDEFINED); - } - final float f3 = this.getAttackStrengthScale(0.5f); - f *= 0.2f + f3 * f3 * 0.8f; - f2 *= f3; - // this.resetAttackStrengthTicker(); - if (f > 0.0f || f2 > 0.0f) { - final boolean flag = f3 > 0.9f; - boolean flag2 = false; - float i = 0; - if (this.getAttributes().hasAttribute(Attributes.ATTACK_KNOCKBACK)) { - i = (float) this.getAttributeValue(Attributes.ATTACK_KNOCKBACK); // Forge: Initialize this value to the attack knockback attribute of the player, which is by default 0 - } - i += EnchantmentHelper.getKnockbackBonus((net.minecraft.world.entity.player.Player) (Object) this); - if (this.isSprinting() && flag) { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0f, 1.0f); - ++i; - flag2 = true; - } - boolean flag3 = flag && this.fallDistance > 0.0f && !this.onGround && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && entity instanceof LivingEntity; - flag3 = flag3 && !this.isSprinting(); - var hitResult = this.bridge$forge$getCriticalHit((net.minecraft.world.entity.player.Player) (Object) this, entity, flag3, flag3 ? 1.5F : 1.0F); - flag3 = hitResult != null; - if (flag3) { - f *= hitResult; - } - f += f2; - boolean flag4 = false; - final double d0 = this.walkDist - this.walkDistO; - if (flag && !flag3 && !flag2 && this.onGround && d0 < this.getSpeed()) { - final ItemStack itemstack = this.getItemInHand(InteractionHand.MAIN_HAND); - flag4 = ((ItemStackBridge) (Object) itemstack).bridge$forge$canPerformAction(ItemStackBridge.ToolAction.SWORD_SWEEP); - } - float f4 = 0.0f; - boolean flag5 = false; - final int j = EnchantmentHelper.getFireAspect((net.minecraft.world.entity.player.Player) (Object) this); - if (entity instanceof LivingEntity) { - f4 = ((LivingEntity) entity).getHealth(); - if (j > 0 && !entity.isOnFire()) { - final EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), 1); - Bukkit.getPluginManager().callEvent(combustEvent); - if (!combustEvent.isCancelled()) { - flag5 = true; - ((EntityBridge) entity).bridge$setOnFire(combustEvent.getDuration(), false); - } - } - } - final Vec3 vec3d = entity.getDeltaMovement(); - final boolean flag6 = entity.hurt(this.damageSources().playerAttack((net.minecraft.world.entity.player.Player) (Object) this), f); - if (flag6) { - if (i > 0) { - if (entity instanceof LivingEntity) { - ((LivingEntityBridge) entity).bridge$pushKnockbackCause((Entity) (Object) this, EntityKnockbackEvent.KnockbackCause.ENTITY_ATTACK); - ((LivingEntity) entity).knockback(i * 0.5f, Mth.sin(this.getYRot() * 0.017453292f), -Mth.cos(this.getYRot() * 0.017453292f)); - } else { - entity.push(-Mth.sin(this.getYRot() * 0.017453292f) * i * 0.5f, 0.1, Mth.cos(this.getYRot() * 0.017453292f) * i * 0.5f); - } - this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6)); - this.setSprinting(false); - } - if (flag4) { - final float f5 = 1.0f + EnchantmentHelper.getSweepingDamageRatio((net.minecraft.world.entity.player.Player) (Object) this) * f; - final List list = this.level().getEntitiesOfClass(LivingEntity.class, ((ItemStackBridge) (Object) this.getItemInHand(InteractionHand.MAIN_HAND)).bridge$forge$getSweepHitBox((net.minecraft.world.entity.player.Player) (Object) this, entity)); - double entityReachSq = Mth.square(this.bridge$forge$getEntityReach()); // Use entity reach instead of constant 9.0. Vanilla uses bottom center-to-center checks here, so don't update this to use canReach, since it uses closest-corner checks. - for (final LivingEntity entityliving : list) { - if (entityliving != (Object) this && entityliving != entity && !this.isAlliedTo(entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr(entityliving) < entityReachSq && entityliving.hurt(((DamageSourceBridge) this.damageSources().playerAttack((net.minecraft.world.entity.player.Player) (Object) this)).bridge$sweep(), f5)) { - ((LivingEntityBridge) entityliving).bridge$pushKnockbackCause((Entity) (Object) this, EntityKnockbackEvent.KnockbackCause.SWEEP_ATTACK); - entityliving.knockback(0.4f, Mth.sin(this.getYRot() * 0.017453292f), -Mth.cos(this.getYRot() * 0.017453292f)); - } - } - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0f, 1.0f); - this.sweepAttack(); - } - if (entity instanceof ServerPlayer && entity.hurtMarked) { - boolean cancelled = false; - final Player player = ((ServerPlayerEntityBridge) entity).bridge$getBukkitEntity(); - final Vector velocity = CraftVector.toBukkit(vec3d); - final PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - cancelled = true; - } else if (!velocity.equals(event.getVelocity())) { - player.setVelocity(event.getVelocity()); - } - if (!cancelled) { - ((ServerPlayer) entity).connection.send(new ClientboundSetEntityMotionPacket(entity)); - entity.hurtMarked = false; - entity.setDeltaMovement(vec3d); - } - } - if (flag3) { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0f, 1.0f); - this.crit(entity); - } - if (!flag3 && !flag4) { - if (flag) { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0f, 1.0f); - } else { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0f, 1.0f); - } - } - if (f2 > 0.0f) { - this.magicCrit(entity); - } - this.setLastHurtMob(entity); - if (entity instanceof LivingEntity) { - EnchantmentHelper.doPostHurtEffects((LivingEntity) entity, (net.minecraft.world.entity.player.Player) (Object) this); - } - EnchantmentHelper.doPostDamageEffects((net.minecraft.world.entity.player.Player) (Object) this, entity); - final ItemStack itemstack2 = this.getMainHandItem(); - Entity object = entity; - if (((EntityBridge) entity).bridge$forge$isPartEntity()) { - object = ((EntityBridge) entity).bridge$forge$getParent(); - } - if (!this.level().isClientSide && !itemstack2.isEmpty() && object instanceof LivingEntity) { - ItemStack copy = itemstack2.copy(); - itemstack2.hurtEnemy((LivingEntity) object, (net.minecraft.world.entity.player.Player) (Object) this); - if (itemstack2.isEmpty()) { - ((ItemBridge) copy.getItem()).bridge$forge$onPlayerDestroyItem((net.minecraft.world.entity.player.Player) (Object) this, copy, InteractionHand.MAIN_HAND); - this.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY); - } - } - if (entity instanceof LivingEntity) { - final float f6 = f4 - ((LivingEntity) entity).getHealth(); - this.awardStat(Stats.DAMAGE_DEALT, Math.round(f6 * 10.0f)); - if (j > 0) { - final EntityCombustByEntityEvent combustEvent2 = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), j * 4); - Bukkit.getPluginManager().callEvent(combustEvent2); - if (!combustEvent2.isCancelled()) { - ((EntityBridge) entity).bridge$setOnFire(combustEvent2.getDuration(), false); - } - } - if (this.level() instanceof ServerLevel && f6 > 2.0f) { - final int k = (int) (f6 * 0.5); - ((ServerLevel) this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, entity.getX(), entity.getY() + entity.getBbHeight() * 0.5f, entity.getZ(), k, 0.1, 0.0, 0.1, 0.2); - } - } - bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.ATTACK); - this.causeFoodExhaustion(((WorldBridge) level()).bridge$spigotConfig().combatExhaustion); - } else { - this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0f, 1.0f); - if (flag5) { - entity.clearFire(); - } - if (this instanceof ServerPlayerEntityBridge) { - ((ServerPlayerEntityBridge) this).bridge$getBukkitEntity().updateInventory(); - } - } + @Decorate(method = "attack", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Projectile;deflect(Lnet/minecraft/world/entity/projectile/ProjectileDeflection;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Z)Z")) + private void arclight$nonLivingDamage(Entity entity, @Local(ordinal = -1) DamageSource damageSource, @Local(ordinal = 1) float enchantDamage) throws Throwable { + if (CraftEventFactory.handleNonLivingEntityDamageEvent(entity, damageSource, enchantDamage, false)) { + DecorationOps.cancel().invoke(); + return; + } + DecorationOps.blackhole().invoke(); + } + + @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;knockback(DDD)V"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/ai/attributes/Attributes;SWEEPING_DAMAGE_RATIO:Lnet/minecraft/core/Holder;"))) + private void arclight$skipKnockback(LivingEntity instance, double d, double e, double f) { + } + + @Redirect(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private boolean arclight$applyKnockback(LivingEntity instance, DamageSource damageSource, float f) throws Throwable { + var result = (boolean) DecorationOps.callsite().invoke(instance, damageSource, f); + if (result) { + ((LivingEntityBridge) instance).bridge$pushKnockbackCause((Entity) (Object) this, EntityKnockbackEvent.KnockbackCause.SWEEP_ATTACK); + instance.knockback(0.4f, Mth.sin(this.getYRot() * 0.017453292f), -Mth.cos(this.getYRot() * 0.017453292f)); + } + return result; + } + + @Decorate(method = "attack", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/world/entity/Entity;hurtMarked:Z")) + private boolean arclight$velocityEvent(Entity entity, @Local(ordinal = -1) Vec3 deltaMovement) throws Throwable { + boolean result = (boolean) DecorationOps.callsite().invoke(entity); + if (result) { + org.bukkit.entity.Player player = (org.bukkit.entity.Player) entity.bridge$getBukkitEntity(); + org.bukkit.util.Vector velocity = CraftVector.toBukkit(deltaMovement); + + PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone()); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + result = false; + } else if (!velocity.equals(event.getVelocity())) { + player.setVelocity(event.getVelocity()); } } + return result; + } + + @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")) + private void arclight$foodExhaust(Entity entity, CallbackInfo ci) { + bridge$pushExhaustReason(EntityExhaustionEvent.ExhaustionReason.ATTACK); + } + + @Inject(method = "attack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/player/Player;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/sounds/SoundEvents;PLAYER_ATTACK_NODAMAGE:Lnet/minecraft/sounds/SoundEvent;"))) + private void arclight$updateInv(Entity entity, CallbackInfo ci) { + if (this instanceof ServerPlayerEntityBridge b) { + b.bridge$getBukkitEntity().updateInventory(); + } + } + + @Inject(method = "eat", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(Lnet/minecraft/world/food/FoodProperties;)V")) + private void arclight$eatStack(Level level, ItemStack itemStack, FoodProperties foodProperties, CallbackInfoReturnable cir) { + ((FoodStatsBridge) this.getFoodData()).bridge$pushEatStack(itemStack); } protected transient boolean arclight$forceSleep; @@ -533,13 +413,13 @@ public CraftHumanEntity getBukkitEntity() { } @Override - public void setItemSlot(EquipmentSlot slot, ItemStack stack, boolean silent) { + public void onEquipItem(EquipmentSlot slot, ItemStack stack, boolean silent) { this.verifyEquippedItem(stack); if (slot == EquipmentSlot.MAINHAND) { this.equipEventAndSound(slot, this.inventory.items.set(this.inventory.selected, stack), stack, silent); } else if (slot == EquipmentSlot.OFFHAND) { this.equipEventAndSound(slot, this.inventory.offhand.set(0, stack), stack, silent); - } else if (slot.getType() == EquipmentSlot.Type.ARMOR) { + } else if (slot.getType() == EquipmentSlot.Type.HUMANOID_ARMOR) { this.equipEventAndSound(slot, this.inventory.armor.set(slot.getIndex(), stack), stack, silent); } } @@ -566,44 +446,9 @@ public void applyExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reas arclight$exhaustReason = reason; } - @Unique - private static boolean arclight$validUsernameCheck(String name) { - var regex = ArclightConfig.spec().getCompat().getValidUsernameRegex(); - return !regex.isBlank() && name.matches(regex); - } - - @Inject(method = "isValidUsername", cancellable = true, at = @At("HEAD")) - private static void arclight$checkUsername(String name, CallbackInfoReturnable cir) { - if (arclight$validUsernameCheck(name)) { - cir.setReturnValue(true); - } - } - @Override public double bridge$platform$getBlockReach() { return isCreative() ? 5 : 4.5; } - @Override - public boolean bridge$platform$isCloseEnough(Entity entity, double dist) { - Vec3 eye = getEyePosition(); - AABB aabb = entity.getBoundingBox().inflate(entity.getPickRadius()); - return aabb.distanceToSqr(eye) < dist * dist; - } - - @Override - public boolean bridge$platform$canReach(BlockPos pos, double padding) { - double reach = bridge$platform$getBlockReach() + padding; - return getEyePosition().distanceToSqr(Vec3.atCenterOf(pos)) < reach * reach; - } - - @Override - public boolean bridge$platform$canReach(Entity entity, double padding) { - return bridge$platform$isCloseEnough(entity, bridge$forge$getEntityReach() + padding); - } - - @Override - public boolean bridge$platform$canReach(Vec3 entityHitVec, double padding) { - return getEyePosition().closerThan(entityHitVec, bridge$forge$getEntityReach() + padding); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java index 3e388c7cf..e57d1a165 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractArrowMixin.java @@ -3,27 +3,27 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.PlayerInventoryBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.ProjectileDeflection; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.entity.CraftItem; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.entity.AbstractArrow; import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.player.PlayerPickupArrowEvent; import org.bukkit.projectiles.ProjectileSource; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(net.minecraft.world.entity.projectile.AbstractArrow.class) @@ -38,17 +38,12 @@ public abstract class AbstractArrowMixin extends ProjectileMixin { @Shadow public ItemStack pickupItemStack; // @formatter:on - @Redirect(method = "tick", at = @At(value = "INVOKE", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;onHit(Lnet/minecraft/world/phys/HitResult;)V")) - private void arclight$hitEvent(net.minecraft.world.entity.projectile.AbstractArrow abstractArrow, HitResult hitResult) { - this.preOnHit(hitResult); - } - - @Redirect(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - private void arclight$fireShot(Entity entity, int seconds, EntityHitResult result) { - EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), ((EntityBridge) entity).bridge$getBukkitEntity(), seconds); + @Decorate(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$fireShot(Entity entity, float seconds) throws Throwable { + EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), seconds); Bukkit.getPluginManager().callEvent(combustEvent); if (!combustEvent.isCancelled()) { - ((EntityBridge) entity).bridge$setOnFire(combustEvent.getDuration(), false); + DecorationOps.callsite().invoke(entity, seconds); } } @@ -62,29 +57,24 @@ public abstract class AbstractArrowMixin extends ProjectileMixin { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void playerTouch(Player playerEntity) { - if (!this.level().isClientSide && (this.inGround || this.isNoPhysics()) && this.shakeTime <= 0) { - ItemStack itemstack = this.getPickupItem(); - if (this.pickup == net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED && !itemstack.isEmpty() && ((PlayerInventoryBridge) playerEntity.getInventory()).bridge$canHold(itemstack) > 0) { - ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); - PlayerPickupArrowEvent event = new PlayerPickupArrowEvent(((ServerPlayerEntityBridge) playerEntity).bridge$getBukkitEntity(), new CraftItem(((CraftServer) Bukkit.getServer()), item), (AbstractArrow) this.getBukkitEntity()); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - itemstack = item.getItem(); - } - if ((this.pickup == net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED && playerEntity.getInventory().add(itemstack)) || (this.pickup == net.minecraft.world.entity.projectile.AbstractArrow.Pickup.CREATIVE_ONLY && playerEntity.getAbilities().instabuild)) { - playerEntity.take((net.minecraft.world.entity.projectile.AbstractArrow) (Object) this, 1); - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.PICKUP); - this.discard(); + @Decorate(method = "playerTouch", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractArrow;tryPickup(Lnet/minecraft/world/entity/player/Player;)Z")) + private boolean arclight$pickupArrow(net.minecraft.world.entity.projectile.AbstractArrow instance, Player player) throws Throwable { + ItemStack itemstack = this.getPickupItem(); + if (this.pickup == net.minecraft.world.entity.projectile.AbstractArrow.Pickup.ALLOWED && !itemstack.isEmpty() && ((PlayerInventoryBridge) player.getInventory()).bridge$canHold(itemstack) > 0) { + ItemEntity item = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); + PlayerPickupArrowEvent event = new PlayerPickupArrowEvent(((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(), new CraftItem(((CraftServer) Bukkit.getServer()), item), (AbstractArrow) this.getBukkitEntity()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return (boolean) DecorationOps.cancel().invoke(); } + itemstack = item.getItem(); + } + this.pickupItemStack = itemstack; + var result = (boolean) DecorationOps.callsite().invoke(instance, player); + if (result) { + this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.PICKUP); } + return result; } @Inject(method = "setOwner", at = @At("HEAD")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java index 375c30a9a..0b9c59590 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/AbstractHurtingProjectileMixin.java @@ -1,7 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; import io.izzel.arclight.common.bridge.core.entity.projectile.DamagingProjectileEntityBridge; -import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.projectile.AbstractHurtingProjectile; import net.minecraft.world.level.Level; @@ -9,22 +9,14 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(AbstractHurtingProjectile.class) public abstract class AbstractHurtingProjectileMixin extends ProjectileMixin implements DamagingProjectileEntityBridge { - // @formatter:off - @Shadow public double xPower; - @Shadow public double yPower; - @Shadow public double zPower; - // @formatter:on - public float bukkitYield; public boolean isIncendiary; @@ -34,39 +26,18 @@ public abstract class AbstractHurtingProjectileMixin extends ProjectileMixin imp this.isIncendiary = true; } - public void setDirection(double d0, double d1, double d2) { - double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); - - this.xPower = d0 / d3 * 0.1D; - this.yPower = d1 / d3 * 0.1D; - this.zPower = d2 / d3 * 0.1D; - } - - @Override - public void bridge$setDirection(double d0, double d1, double d2) { - this.setDirection(d0, d1, d2); - } - @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractHurtingProjectile;discard()V")) private void arclight$despawn(CallbackInfo ci) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/AbstractHurtingProjectile;onHit(Lnet/minecraft/world/phys/HitResult;)V")) - private void arclight$preOnHit(AbstractHurtingProjectile abstractHurtingProjectile, HitResult hitResult) { - this.preOnHit(hitResult); + @Inject(method = "tick", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/projectile/AbstractHurtingProjectile;hitTargetOrDeflectSelf(Lnet/minecraft/world/phys/HitResult;)Lnet/minecraft/world/entity/projectile/ProjectileDeflection;")) + private void arclight$postOnHit(CallbackInfo ci, Entity owner, HitResult hitResult) { if (this.isRemoved()) { CraftEventFactory.callProjectileHitEvent((AbstractHurtingProjectile) (Object) this, hitResult); } } - @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getLookAngle()Lnet/minecraft/world/phys/Vec3;")) - private void arclight$nonLivingAttack(DamageSource source, float amount, CallbackInfoReturnable cir) { - if (CraftEventFactory.handleNonLivingEntityDamageEvent((AbstractHurtingProjectile) (Object) this, source, amount, false)) { - cir.setReturnValue(false); - } - } - @Override public void bridge$setBukkitYield(float yield) { this.bukkitYield = yield; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ArrowEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ArrowEntityMixin.java index 6678256ae..3359c097b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ArrowEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ArrowEntityMixin.java @@ -2,63 +2,19 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.projectile.ArrowEntityBridge; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.network.syncher.EntityDataAccessor; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.Arrow; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.item.alchemy.Potions; import org.bukkit.event.entity.EntityPotionEffectEvent; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Set; - @Mixin(Arrow.class) public abstract class ArrowEntityMixin extends AbstractArrowMixin implements ArrowEntityBridge { - // @formatter:off - @Shadow @Final private static EntityDataAccessor ID_EFFECT_COLOR; - @Shadow @Final public Set effects; - @Shadow private Potion potion; - // @formatter:on - @Inject(method = "doPostHurtEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;Lnet/minecraft/world/entity/Entity;)Z")) private void arclight$arrowHit(LivingEntity living, CallbackInfo ci) { ((LivingEntityBridge) living).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ARROW); } - - public void refreshEffects() { - this.getEntityData().set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); - } - - @Override - public void bridge$refreshEffects() { - refreshEffects(); - } - - public String getPotionType() { - return BuiltInRegistries.POTION.getKey(this.potion).toString(); - } - - public void setPotionType(final String string) { - this.potion = BuiltInRegistries.POTION.get(new ResourceLocation(string)); - this.getEntityData().set(ID_EFFECT_COLOR, PotionUtils.getColor(PotionUtils.getAllEffects(this.potion, this.effects))); - } - - public boolean isTipped() { - return !this.effects.isEmpty() || this.potion != Potions.EMPTY; - } - - @Override - public boolean bridge$isTipped() { - return isTipped(); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java index dfbd79b5e..5c54fdfc8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/EyeOfEnderMixin.java @@ -2,13 +2,11 @@ import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; import net.minecraft.world.entity.projectile.EyeOfEnder; -import net.minecraft.world.item.ItemStack; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EyeOfEnder.class) @@ -16,11 +14,6 @@ public abstract class EyeOfEnderMixin extends EntityMixin { @Shadow public boolean surviveAfterDeath; - @Redirect(method = "setItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;hasTag()Z")) - private boolean arclight$allowItemChange(ItemStack instance) { - return true; - } - @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/EyeOfEnder;discard()V")) private void arclight$drop(CallbackInfo ci) { this.bridge$pushEntityRemoveCause(this.surviveAfterDeath ? EntityRemoveEvent.Cause.DROP : EntityRemoveEvent.Cause.DESPAWN); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FireballMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FireballMixin.java index 60f95b0e9..deb5d4285 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FireballMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FireballMixin.java @@ -1,19 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.projectile.Fireball; -import net.minecraft.world.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Fireball.class) public abstract class FireballMixin extends AbstractHurtingProjectileMixin { - @Inject(method = "readAdditionalSaveData", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/Fireball;setItem(Lnet/minecraft/world/item/ItemStack;)V")) - private void arclight$nonNullItem(CompoundTag compound, CallbackInfo ci, ItemStack stack) { - if (stack.isEmpty()) ci.cancel(); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java index 1f8b84da5..747b27c41 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java @@ -2,12 +2,10 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.projectile.FishingHookBridge; -import net.minecraft.advancements.CriteriaTriggers; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.Stats; -import net.minecraft.tags.ItemTags; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; @@ -17,29 +15,20 @@ import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.loot.BuiltInLootTables; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.HitResult; import org.bukkit.Bukkit; import org.bukkit.entity.FishHook; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.player.PlayerFishEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.Collections; -import java.util.List; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(FishingHook.class) public abstract class FishingHookMixin extends ProjectileMixin implements FishingHookBridge { @@ -65,11 +54,6 @@ public abstract class FishingHookMixin extends ProjectileMixin implements Fishin public boolean rainInfluenced = true; public boolean skyInfluenced = true; - @Redirect(method = "checkCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;onHit(Lnet/minecraft/world/phys/HitResult;)V")) - private void arclight$collide(FishingHook fishingHook, HitResult hitResult) { - this.preOnHit(hitResult); - } - @Inject(method = "catchingFish", at = @At(value = "FIELD", shift = At.Shift.AFTER, ordinal = 0, target = "Lnet/minecraft/world/entity/projectile/FishingHook;timeUntilHooked:I")) private void arclight$attemptFail(BlockPos blockPos, CallbackInfo ci) { PlayerFishEvent event = new PlayerFishEvent(((ServerPlayerEntityBridge) this.getPlayerOwner()).bridge$getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT); @@ -85,14 +69,6 @@ public abstract class FishingHookMixin extends ProjectileMixin implements Fishin } } - @Inject(method = "catchingFish", at = @At("RETURN")) - private void arclight$modifyWaitingTime(BlockPos p_37146_, CallbackInfo ci) { - if (this.nibble <= 0 && this.timeUntilHooked <= 0 && this.timeUntilLured <= 0) { - this.timeUntilLured = Mth.nextInt(this.random, this.minWaitTime, this.maxWaitTime); - this.timeUntilLured -= (this.applyLure) ? this.lureSpeed * 20 * 5 : 0; - } - } - @Redirect(method = "catchingFish", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isRainingAt(Lnet/minecraft/core/BlockPos;)Z")) private boolean arclight$rainInfluenced(Level level, BlockPos pos) { return this.rainInfluenced && level.isRainingAt(pos); @@ -108,11 +84,21 @@ public abstract class FishingHookMixin extends ProjectileMixin implements Fishin return Mth.nextFloat(random, this.minLureAngle, this.maxLureAngle); } - @Redirect(method = "catchingFish", at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/util/Mth;nextInt(Lnet/minecraft/util/RandomSource;II)I")) + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/util/Mth;nextInt(Lnet/minecraft/util/RandomSource;II)I")) private int arclight$lureTimeParam(RandomSource random, int p_216273_, int p_216274_) { return Mth.nextInt(random, this.minLureTime, this.maxLureTime); } + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/util/Mth;nextInt(Lnet/minecraft/util/RandomSource;II)I")) + private int arclight$waitTimeParam(RandomSource random, int p_216273_, int p_216274_) { + return Mth.nextInt(random, this.minWaitTime, this.maxWaitTime); + } + + @Redirect(method = "catchingFish", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/projectile/FishingHook;lureSpeed:I")) + private int arclight$waitTimeParam2(FishingHook instance) { + return this.applyLure ? this.lureSpeed : 0; + } + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;discard()V")) private void arclight$tickDespawn(CallbackInfo ci) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); @@ -123,93 +109,63 @@ public abstract class FishingHookMixin extends ProjectileMixin implements Fishin this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - @Unique private transient Integer arclight$rodDamage; - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public int retrieve(ItemStack stack) { - Player playerentity = this.getPlayerOwner(); - if (!this.level().isClientSide && playerentity != null) { - int i = 0; - arclight$rodDamage = null; - if (this.hookedIn != null) { - PlayerFishEvent fishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) playerentity).bridge$getBukkitEntity(), this.hookedIn.bridge$getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); - Bukkit.getPluginManager().callEvent(fishEvent); - if (fishEvent.isCancelled()) { - return 0; - } - this.pullEntity(this.hookedIn); - CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) playerentity, stack, (FishingHook) (Object) this, Collections.emptyList()); - this.level().broadcastEntityEvent((FishingHook) (Object) this, (byte) 31); - i = this.hookedIn instanceof ItemEntity ? 3 : 5; - } else if (this.nibble > 0) { - LootParams params = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, stack).withParameter(LootContextParams.THIS_ENTITY, (FishingHook) (Object) this).withLuck((float) this.luck + playerentity.getLuck()).create(LootContextParamSets.FISHING); - LootTable loottable = this.level().getServer().getLootData().getLootTable(BuiltInLootTables.FISHING); - List list = loottable.getRandomItems(params); - { - var event = this.bridge$forge$onItemFished(list, this.onGround ? 2 : 1, (FishingHook) (Object) this); - if (event._1) { - this.discard(); - return event._2; - } - arclight$rodDamage = event._2; - } - CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) playerentity, stack, (FishingHook) (Object) this, list); - - for (ItemStack itemstack : list) { - ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), itemstack); - { // mixin conflict with Rapscallions and Rockhoppers https://github.com/GreenhouseTeam/rapscallions-and-rockhoppers/blob/0a5f77c60d454363b34ad7ac3ee84e8f97ae3ea1/common/src/main/java/dev/greenhouseteam/rapscallionsandrockhoppers/mixin/FishingHookMixin.java - PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) playerentity).bridge$getBukkitEntity(), itementity.bridge$getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); - playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); - Bukkit.getPluginManager().callEvent(playerFishEvent); - - if (playerFishEvent.isCancelled()) { - return 0; - } - if (playerFishEvent.getExpToDrop() > 0) { - playerentity.level().addFreshEntity(new ExperienceOrb(playerentity.level(), playerentity.getX(), playerentity.getY() + 0.5D, playerentity.getZ() + 0.5D, playerFishEvent.getExpToDrop())); - } - } - double d0 = playerentity.getX() - this.getX(); - double d1 = playerentity.getY() - this.getY(); - double d2 = playerentity.getZ() - this.getZ(); - double d3 = 0.1D; - itementity.setDeltaMovement(d0 * 0.1D, d1 * 0.1D + Math.sqrt(Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2)) * 0.08D, d2 * 0.1D); - this.level().addFreshEntity(itementity); - if (itemstack.is(ItemTags.FISHES)) { - playerentity.awardStat(Stats.FISH_CAUGHT, 1); - } - } - - i = 1; - } + @Inject(method = "retrieve", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;pullEntity(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$catchEntity(ItemStack itemStack, CallbackInfoReturnable cir) { + PlayerFishEvent fishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) this.getPlayerOwner()).bridge$getBukkitEntity(), this.hookedIn.bridge$getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_ENTITY); + Bukkit.getPluginManager().callEvent(fishEvent); + if (fishEvent.isCancelled()) { + cir.setReturnValue(0); + } + } + + @Decorate(method = "retrieve", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;setDeltaMovement(DDD)V")) + private void arclight$catchFish(ItemStack stack, @Local(ordinal = -1) ItemEntity itementity, @Local(allocate = "expToDrop") int expToDrop) throws Throwable { + PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) this.getPlayerOwner()).bridge$getBukkitEntity(), itementity.bridge$getBukkitEntity(), (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.CAUGHT_FISH); + playerFishEvent.setExpToDrop(this.random.nextInt(6) + 1); + Bukkit.getPluginManager().callEvent(playerFishEvent); - if (this.onGround) { - PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) playerentity).bridge$getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); - Bukkit.getPluginManager().callEvent(playerFishEvent); + if (playerFishEvent.isCancelled()) { + DecorationOps.cancel().invoke(0); + return; + } + expToDrop = playerFishEvent.getExpToDrop(); + DecorationOps.blackhole().invoke(expToDrop); + } - if (playerFishEvent.isCancelled()) { - return 0; - } - i = 2; + @Decorate(method = "retrieve", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z"), + slice = @Slice(from = @At(value = "NEW", target = "(Lnet/minecraft/world/level/Level;DDDI)Lnet/minecraft/world/entity/ExperienceOrb;"))) + private boolean arclight$spawnExpOrb(Level instance, Entity entity, ItemStack stack, @Local(allocate = "expToDrop") int expToDrop) throws Throwable { + if (entity instanceof ExperienceOrb orb) { + if (expToDrop <= 0) { + return false; } + orb.value = expToDrop; + } + return (boolean) DecorationOps.callsite().invoke(instance, entity); + } + + @Inject(method = "retrieve", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;onGround()Z")) + private void arclight$onGround(ItemStack itemStack, CallbackInfoReturnable cir) { + if (this.onGround()) { + PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) this.getPlayerOwner()).bridge$getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.IN_GROUND); + Bukkit.getPluginManager().callEvent(playerFishEvent); - if (i == 0) { - PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) playerentity).bridge$getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); - Bukkit.getPluginManager().callEvent(playerFishEvent); - if (playerFishEvent.isCancelled()) { - return 0; - } + if (playerFishEvent.isCancelled()) { + cir.setReturnValue(0); } + } + } - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); - this.discard(); - return arclight$rodDamage == null ? i : arclight$rodDamage; - } else { - return 0; + @Inject(method = "retrieve", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;discard()V")) + private void arclight$reelIn(ItemStack itemStack, CallbackInfoReturnable cir, Player player, int i) { + if (i == 0) { + PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.REEL_IN); + Bukkit.getPluginManager().callEvent(playerFishEvent); + if (playerFishEvent.isCancelled()) { + cir.setReturnValue(0); + return; + } } + this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/LargeFireballMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/LargeFireballMixin.java index 539024e48..aed03be93 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/LargeFireballMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/LargeFireballMixin.java @@ -1,5 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -9,13 +11,13 @@ import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.entity.ExplosionPrimeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LargeFireball.class) @@ -26,8 +28,8 @@ public abstract class LargeFireballMixin extends AbstractHurtingProjectileMixin this.isIncendiary = worldIn.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } - @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;DDDI)V", at = @At("RETURN")) - private void arclight$init(Level level, LivingEntity p_181152_, double p_181153_, double p_181154_, double p_181155_, int p_181156_, CallbackInfo ci) { + @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/phys/Vec3;I)V", at = @At("RETURN")) + private void arclight$init(Level level, LivingEntity livingEntity, Vec3 vec3, int i, CallbackInfo ci) { this.isIncendiary = level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } @@ -36,15 +38,15 @@ public abstract class LargeFireballMixin extends AbstractHurtingProjectileMixin this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); } - @Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) - private Explosion arclight$explodePrime(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Level.ExplosionInteraction interaction) { + @Decorate(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;explode(Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;)Lnet/minecraft/world/level/Explosion;")) + private Explosion arclight$explodePrime(Level world, Entity entityIn, double xIn, double yIn, double zIn, float explosionRadius, boolean causesFire, Level.ExplosionInteraction interaction) throws Throwable { ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) this.getBukkitEntity()); event.setRadius(explosionRadius); event.setFire(causesFire); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - return this.level().explode((LargeFireball) (Object) this, xIn, yIn, zIn, event.getRadius(), event.getFire(), interaction); + return (Explosion) DecorationOps.callsite().invoke(world, entityIn, xIn, yIn, zIn, event.getRadius(), event.getFire(), interaction); } else { return null; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ProjectileMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ProjectileMixin.java index f6a42b9fe..8c3c89a4c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ProjectileMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ProjectileMixin.java @@ -1,9 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.projectile.ProjectileDeflection; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import org.bukkit.craftbukkit.v.entity.CraftEntity; @@ -14,6 +14,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import javax.annotation.Nullable; @@ -23,19 +24,21 @@ public abstract class ProjectileMixin extends EntityMixin { // @formatter:off @Shadow @Nullable public abstract Entity getOwner(); @Shadow protected void onHit(HitResult result) { } + @Shadow protected abstract ProjectileDeflection hitTargetOrDeflectSelf(HitResult hitResult); + @Shadow public abstract boolean deflect(ProjectileDeflection projectileDeflection, @org.jetbrains.annotations.Nullable Entity entity, @org.jetbrains.annotations.Nullable Entity entity2, boolean bl); // @formatter:on @Inject(method = "setOwner", at = @At("RETURN")) private void arclight$updateSource(Entity entityIn, CallbackInfo ci) { if (entityIn != null) { - CraftEntity entity = ((EntityBridge) entityIn).bridge$getBukkitEntity(); + CraftEntity entity = entityIn.bridge$getBukkitEntity(); if (entity instanceof ProjectileSource) { this.projectileSource = ((ProjectileSource) entity); } } } - private boolean hitCancelled = false; + protected boolean hitCancelled = false; @Inject(method = "onHitBlock", cancellable = true, at = @At("HEAD")) private void arclight$cancelBlockHit(BlockHitResult result, CallbackInfo ci) { @@ -44,11 +47,17 @@ public abstract class ProjectileMixin extends EntityMixin { } } - protected void preOnHit(HitResult hitResult) { - org.bukkit.event.entity.ProjectileHitEvent event = CraftEventFactory.callProjectileHitEvent((Projectile) (Object) this, hitResult); - this.hitCancelled = event != null && event.isCancelled(); - if (hitResult.getType() == HitResult.Type.BLOCK || !this.hitCancelled) { - this.onHit(hitResult); + private transient boolean arclight$hitEventFired = false; + + @Inject(method = "hitTargetOrDeflectSelf", cancellable = true, at = @At("HEAD")) + private void arclight$hitEvent(HitResult hitResult, CallbackInfoReturnable cir) { + if (!arclight$hitEventFired) { + arclight$hitEventFired = true; + org.bukkit.event.entity.ProjectileHitEvent event = CraftEventFactory.callProjectileHitEvent((Projectile) (Object) this, hitResult); + this.hitCancelled = event != null && event.isCancelled(); + if (!(hitResult.getType() == HitResult.Type.BLOCK || !this.hitCancelled)) { + cir.setReturnValue(ProjectileDeflection.NONE); + } } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/SmallFireballMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/SmallFireballMixin.java index df6a93230..6fca27bb4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/SmallFireballMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/SmallFireballMixin.java @@ -1,6 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -10,6 +11,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityCombustByEntityEvent; @@ -17,29 +19,26 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(SmallFireball.class) public abstract class SmallFireballMixin extends FireballMixin { - @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;DDD)V", at = @At("RETURN")) - private void arclight$init(Level worldIn, LivingEntity shooter, double accelX, double accelY, double accelZ, CallbackInfo ci) { + @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/phys/Vec3;)V", at = @At("RETURN")) + private void arclight$init(Level level, LivingEntity livingEntity, Vec3 vec3, CallbackInfo ci) { if (this.getOwner() != null && this.getOwner() instanceof Mob) { this.isIncendiary = this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING); } } - @Redirect(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - private void arclight$entityCombust(Entity entity, int seconds) { - if (this.isIncendiary) { - EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), ((EntityBridge) entity).bridge$getBukkitEntity(), seconds); - Bukkit.getPluginManager().callEvent(event); + @Decorate(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$entityCombust(Entity entity, float seconds) throws Throwable { + EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.bridge$getBukkitEntity(), seconds); + Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) { - ((EntityBridge) entity).bridge$setOnFire(event.getDuration(), false); - } + if (!event.isCancelled()) { + DecorationOps.callsite().invoke(entity, event.getDuration()); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrowableProjectileMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrowableProjectileMixin.java index e14841749..3bc0d52b5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrowableProjectileMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrowableProjectileMixin.java @@ -5,11 +5,9 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.ThrowableProjectile; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ThrowableProjectile.class) @@ -19,9 +17,4 @@ public abstract class ThrowableProjectileMixin extends ProjectileMixin { private void arclight$init(EntityType type, LivingEntity livingEntityIn, Level worldIn, CallbackInfo ci) { this.projectileSource = ((LivingEntityBridge) livingEntityIn).bridge$getBukkitEntity(); } - - @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ThrowableProjectile;onHit(Lnet/minecraft/world/phys/HitResult;)V")) - private void arclight$projectileHit(ThrowableProjectile entity, HitResult result) { - this.preOnHit(result); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEggMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEggMixin.java index cf7a20bd3..db5cfcf77 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEggMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEggMixin.java @@ -7,6 +7,7 @@ import io.izzel.arclight.common.mod.util.Blackhole; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityDimensions; import net.minecraft.world.entity.animal.Chicken; import net.minecraft.world.entity.projectile.ThrownEgg; import net.minecraft.world.phys.HitResult; @@ -16,12 +17,16 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.player.PlayerEggThrowEvent; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; @Mixin(ThrownEgg.class) public abstract class ThrownEggMixin extends ThrowableProjectileMixin { + @Shadow @Final private static EntityDimensions ZERO_SIZED_DIMENSIONS; + /** * @author IzzelAliz * @reason @@ -63,6 +68,9 @@ protected void onHit(final HitResult result) { ((Ageable) ((EntityBridge) entity).bridge$getBukkitEntity()).setBaby(); } entity.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); + if (!entity.fudgePositionAfterSizeChange(ZERO_SIZED_DIMENSIONS)) { + break; + } ((WorldBridge) this.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.EGG); this.level().addFreshEntity(entity); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java index 100a85b8f..b88fd99d3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownEnderpearlMixin.java @@ -27,7 +27,7 @@ public abstract class ThrownEnderpearlMixin extends ThrowableProjectileMixin { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DESPAWN); } - @Inject(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + @Inject(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) private void arclight$spawnEndermite(HitResult result, CallbackInfo ci) { ((WorldBridge) this.level()).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.ENDER_PEARL); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownExperienceBottleMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownExperienceBottleMixin.java index 9bcfbb38a..89f09969c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownExperienceBottleMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownExperienceBottleMixin.java @@ -3,7 +3,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.projectile.ThrownExperienceBottle; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.alchemy.Potions; import net.minecraft.world.phys.HitResult; import org.bukkit.craftbukkit.v.event.CraftEventFactory; @@ -27,7 +27,7 @@ protected void onHit(HitResult result) { ExpBottleEvent event = CraftEventFactory.callExpBottleEvent((ThrownExperienceBottle) (Object) this, result, i); i = event.getExperience(); if (event.getShowEffect()) { - this.level().levelEvent(2002, this.blockPosition(), PotionUtils.getColor(Potions.WATER)); + this.level().levelEvent(2002, this.blockPosition(), PotionContents.getColor(Potions.WATER)); } ExperienceOrb.award((ServerLevel) this.level(), this.position(), i); this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownPotionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownPotionMixin.java index 530e31876..6084145e4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownPotionMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownPotionMixin.java @@ -4,15 +4,13 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.ThrownPotion; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.level.block.AbstractCandleBlock; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.CampfireBlock; @@ -44,10 +42,10 @@ public abstract class ThrownPotionMixin extends ThrowableItemProjectileMixin { @Unique private transient HitResult arclight$hitResult; - @Redirect(method = "onHit", at = @At(value = "INVOKE", remap = false, ordinal = 1, target = "Ljava/util/List;isEmpty()Z")) - private boolean arclight$callEvent(List list, HitResult hitResult) { + @Redirect(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/alchemy/PotionContents;hasEffects()Z")) + private boolean arclight$callEvent(PotionContents instance, HitResult hitResult) { arclight$hitResult = hitResult; - return false; + return true; } @Inject(method = "onHit", at = @At("RETURN")) @@ -65,7 +63,7 @@ public abstract class ThrownPotionMixin extends ThrowableItemProjectileMixin { * @reason */ @Overwrite - private void applySplash(List list, @Nullable Entity entity) { + private void applySplash(Iterable list, @Nullable Entity entity) { AABB axisalignedbb = this.getBoundingBox().inflate(4.0, 2.0, 4.0); List list2 = this.level().getEntitiesOfClass(LivingEntity.class, axisalignedbb); Map affected = new HashMap<>(); @@ -85,7 +83,7 @@ private void applySplash(List list, @Nullable Entity entity) } } PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent((ThrownPotion) (Object) this, arclight$hitResult, affected); - if (!event.isCancelled() && list != null && !list.isEmpty()) { + if (!event.isCancelled()) { for (org.bukkit.entity.LivingEntity victim : event.getAffectedEntities()) { if (!(victim instanceof CraftLivingEntity)) { continue; @@ -93,22 +91,23 @@ private void applySplash(List list, @Nullable Entity entity) LivingEntity entityliving2 = ((CraftLivingEntity) victim).getHandle(); double d2 = event.getIntensity(victim); for (MobEffectInstance mobeffect : list) { - MobEffect mobeffectlist = mobeffect.getEffect(); + var holder = mobeffect.getEffect(); if (!((WorldBridge) this.level()).bridge$isPvpMode() && this.getOwner() instanceof ServerPlayer && entityliving2 instanceof ServerPlayer && entityliving2 != this.getOwner()) { + var mobeffectlist = holder.value(); if (mobeffectlist == MobEffects.MOVEMENT_SLOWDOWN || mobeffectlist == MobEffects.DIG_SLOWDOWN || mobeffectlist == MobEffects.HARM || mobeffectlist == MobEffects.BLINDNESS || mobeffectlist == MobEffects.HUNGER || mobeffectlist == MobEffects.WEAKNESS || mobeffectlist == MobEffects.POISON) { continue; } } - if (mobeffectlist.isInstantenous()) { - mobeffectlist.applyInstantenousEffect((ThrownPotion) (Object) this, this.getOwner(), entityliving2, mobeffect.getAmplifier(), d2); + if (holder.value().isInstantenous()) { + holder.value().applyInstantenousEffect((ThrownPotion) (Object) this, this.getOwner(), entityliving2, mobeffect.getAmplifier(), d2); } else { int i = (int) (d2 * mobeffect.getDuration() + 0.5); if (i <= 20) { continue; } ((LivingEntityBridge) entityliving2).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.POTION_SPLASH); - entityliving2.addEffect(new MobEffectInstance(mobeffectlist, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible())); + entityliving2.addEffect(new MobEffectInstance(holder, i, mobeffect.getAmplifier(), mobeffect.isAmbient(), mobeffect.isVisible())); } } } @@ -116,7 +115,7 @@ private void applySplash(List list, @Nullable Entity entity) } @Inject(method = "makeAreaOfEffectCloud", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private void arclight$makeCloud(ItemStack p_190542_1_, Potion p_190542_2_, CallbackInfo ci, AreaEffectCloud entity) { + private void arclight$makeCloud(PotionContents potionContents, CallbackInfo ci, AreaEffectCloud entity) { LingeringPotionSplashEvent event = CraftEventFactory.callLingeringPotionSplashEvent((ThrownPotion) (Object) this, arclight$hitResult, entity); if (event.isCancelled() || entity.isRemoved()) { ci.cancel(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java index d48583244..18f5e81df 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/ThrownTridentMixin.java @@ -1,18 +1,12 @@ package io.izzel.arclight.common.mixin.core.world.entity.projectile; import io.izzel.arclight.common.bridge.core.entity.projectile.TridentEntityBridge; -import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.entity.projectile.ThrownTrident; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import org.bukkit.event.entity.EntityRemoveEvent; -import org.bukkit.event.weather.LightningStrikeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ThrownTrident.class) @@ -23,12 +17,6 @@ public abstract class ThrownTridentMixin extends AbstractArrowMixin implements T this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DROP); } - @Redirect(method = "onHitEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$lightning(Level world, Entity entityIn) { - ((ServerWorldBridge) this.level()).bridge$strikeLightning((LightningBolt) entityIn, LightningStrikeEvent.Cause.TRIDENT); - return true; - } - @Override public void bridge$setThrownStack(ItemStack itemStack) { this.pickupItemStack = itemStack; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/WindChargeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/WindChargeMixin.java deleted file mode 100644 index 40203d3fb..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/WindChargeMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.entity.projectile; - -import net.minecraft.world.entity.projectile.WindCharge; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; -import org.bukkit.event.entity.EntityRemoveEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(WindCharge.class) -public abstract class WindChargeMixin extends AbstractHurtingProjectileMixin { - - @Inject(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/WindCharge;discard()V")) - private void arclight$hitCause(HitResult hitResult, CallbackInfo ci) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); - } - - @Inject(method = "onHitBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/WindCharge;discard()V")) - private void arclight$hitBlock(BlockHitResult blockHitResult, CallbackInfo ci) { - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/windcharge/AbstractWindChargeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/windcharge/AbstractWindChargeMixin.java new file mode 100644 index 000000000..aacc4fbf6 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/windcharge/AbstractWindChargeMixin.java @@ -0,0 +1,30 @@ +package io.izzel.arclight.common.mixin.core.world.entity.projectile.windcharge; + +import io.izzel.arclight.common.mixin.core.world.entity.projectile.AbstractHurtingProjectileMixin; +import net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import org.bukkit.event.entity.EntityRemoveEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(AbstractWindCharge.class) +public abstract class AbstractWindChargeMixin extends AbstractHurtingProjectileMixin { + + @Inject(method = "onHitBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/windcharge/AbstractWindCharge;discard()V")) + private void arclight$hitBlock(BlockHitResult blockHitResult, CallbackInfo ci) { + bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); + } + + @Inject(method = "onHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/windcharge/AbstractWindCharge;discard()V")) + private void arclight$hit(HitResult hitResult, CallbackInfo ci) { + bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/windcharge/AbstractWindCharge;discard()V")) + private void arclight$outOfWorld(CallbackInfo ci) { + bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.OUT_OF_WORLD); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidManagerMixin.java index b5e250ec8..4bd74596a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidManagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidManagerMixin.java @@ -26,9 +26,9 @@ public class RaidManagerMixin { @Shadow @Final public Map raidMap; // @formatter:on - @Inject(method = "createOrExtendRaid", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;absorbBadOmen(Lnet/minecraft/world/entity/player/Player;)V")) - public void arclight$raidTrigger(ServerPlayer playerEntity, CallbackInfoReturnable cir, - DimensionType dimensionType, BlockPos pos, BlockPos pos1, List list, int i, Vec3 vec, Raid raid) { + @Inject(method = "createOrExtendRaid", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;absorbRaidOmen(Lnet/minecraft/server/level/ServerPlayer;)Z")) + public void arclight$raidTrigger(ServerPlayer playerEntity, BlockPos pos, CallbackInfoReturnable cir, + DimensionType dimensionType, List list, int i, Vec3 vec, BlockPos pos1, Raid raid) { if (!CraftEventFactory.callRaidTriggerEvent(raid, playerEntity)) { playerEntity.removeEffect(MobEffects.BAD_OMEN); this.raidMap.remove(raid.getId(), raid); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidMixin.java index e140f9b88..55998060c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raid/RaidMixin.java @@ -3,6 +3,8 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.bridge.core.world.raid.RaidBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.advancements.critereon.PlayerTrigger; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; @@ -103,15 +105,15 @@ public class RaidMixin implements RaidBridge { private transient Raider arclight$leader; private transient List arclight$raiders; - @Redirect(method = "spawnGroup", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;setLeader(ILnet/minecraft/world/entity/raid/Raider;)V")) - public void arclight$captureLeader(Raid raid, int raidId, Raider entity) { - raid.setLeader(raidId, entity); + @Decorate(method = "spawnGroup", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;setLeader(ILnet/minecraft/world/entity/raid/Raider;)V")) + public void arclight$captureLeader(Raid raid, int raidId, Raider entity) throws Throwable { + DecorationOps.callsite().invoke(raid, raidId, entity); arclight$leader = entity; } - @Redirect(method = "spawnGroup", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;joinRaid(ILnet/minecraft/world/entity/raid/Raider;Lnet/minecraft/core/BlockPos;Z)V")) - public void arclight$captureRaider(Raid raid, int wave, Raider entity, BlockPos pos, boolean flag) { - raid.joinRaid(wave, entity, pos, flag); + @Decorate(method = "spawnGroup", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/raid/Raid;joinRaid(ILnet/minecraft/world/entity/raid/Raider;Lnet/minecraft/core/BlockPos;Z)V")) + public void arclight$captureRaider(Raid raid, int wave, Raider entity, BlockPos pos, boolean flag) throws Throwable { + DecorationOps.callsite().invoke(raid, wave, entity, pos, flag); if (arclight$raiders == null) { arclight$raiders = new ArrayList<>(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raider/RaiderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raider/RaiderMixin.java index 53b476937..a82235a86 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raider/RaiderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/raider/RaiderMixin.java @@ -1,30 +1,17 @@ package io.izzel.arclight.common.mixin.core.world.entity.raider; -import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.mixin.core.world.entity.PathfinderMobMixin; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.raid.Raid; import net.minecraft.world.entity.raid.Raider; -import net.minecraft.world.item.ItemStack; -import org.bukkit.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Raider.class) public abstract class RaiderMixin extends PathfinderMobMixin { - @Inject(method = "die", locals = LocalCapture.CAPTURE_FAILHARD, require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - private void arclight$raid(DamageSource cause, CallbackInfo ci, Entity entity, Raid raid, ItemStack itemStack, Player playerEntity) { - ((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); - } - @Inject(method = "pickUpItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/item/ItemEntity;discard()V")) private void arclight$pickup(ItemEntity itemEntity, CallbackInfo ci) { this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.PICKUP); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java index 72c2a8341..2c2b0f54d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/AbstractMinecartMixin.java @@ -2,20 +2,15 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.vehicle.AbstractMinecartBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; -import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntitySelector; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MoverType; -import net.minecraft.world.entity.animal.IronGolem; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BaseRailBlock; -import net.minecraft.world.level.block.PoweredRailBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; @@ -33,8 +28,6 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.List; - @Mixin(AbstractMinecart.class) public abstract class AbstractMinecartMixin extends VehicleEntityMixin implements AbstractMinecartBridge { @@ -75,121 +68,55 @@ public abstract class AbstractMinecartMixin extends VehicleEntityMixin implement private transient Location arclight$prevLocation; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void tick() { + @Decorate(method = "tick", inject = true, at = @At("HEAD")) + private void arclight$storePreviousLocation() { this.arclight$prevLocation = new Location(null, this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); - if (this.getHurtTime() > 0) { - this.setHurtTime(this.getHurtTime() - 1); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/vehicle/AbstractMinecart;setRot(FF)V")) + private void arclight$vehicleUpdateEvent(CallbackInfo ci) { + org.bukkit.World bworld = this.level().bridge$getWorld(); + Location from = this.arclight$prevLocation; + this.arclight$prevLocation = null; + from.setWorld(bworld); + Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + Vehicle vehicle = (Vehicle) this.getBukkitEntity(); + Bukkit.getPluginManager().callEvent(new VehicleUpdateEvent(vehicle)); + if (!from.equals(to)) { + Bukkit.getPluginManager().callEvent(new VehicleMoveEvent(vehicle, from, to)); } - if (this.getDamage() > 0.0f) { - this.setDamage(this.getDamage() - 1.0f); + } + + @Decorate(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;startRiding(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$ridingCollide(Entity instance, Entity entity) throws Throwable { + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), instance.bridge$getBukkitEntity()); + Bukkit.getPluginManager().callEvent(collisionEvent); + if (collisionEvent.isCancelled()) { + return false; } - this.checkBelowWorld(); - if (this.level().isClientSide) { - if (this.lerpSteps > 0) { - this.lerpPositionAndRotationStep(this.lerpSteps, this.lerpX, this.lerpY, this.lerpZ, this.lerpYRot, this.lerpXRot); - --this.lerpSteps; - } else { - this.reapplyPosition(); - this.setRot(this.getYRot(), this.getXRot()); - } - } else { - /* - this.prevPosX = this.getPosX(); - this.prevPosY = this.getPosY(); - this.prevPosZ = this.getPosZ(); - */ - if (!this.isNoGravity()) { - this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.04, 0.0)); - } - int i = Mth.floor(this.getX()); - int j = Mth.floor(this.getY()); - int k = Mth.floor(this.getZ()); - if (this.level().getBlockState(new BlockPos(i, j - 1, k)).is(BlockTags.RAILS)) { - --j; - } - BlockPos blockposition = new BlockPos(i, j, k); - BlockState blockstate = this.level().getBlockState(blockposition); - this.onRails = BaseRailBlock.isRail(blockstate); - if (this.bridge$forge$canUseRail() && this.onRails) { - this.moveAlongTrack(blockposition, blockstate); - if (((BlockBridge) blockstate.getBlock()).bridge$forge$isActivatorRail(blockstate)) { - this.activateMinecart(i, j, k, blockstate.getValue(PoweredRailBlock.POWERED)); - } - } else { - this.comeOffTrack(); - } - this.checkInsideBlocks(); - this.setXRot(0.f); - double d5 = this.xo - this.getX(); - double d6 = this.zo - this.getZ(); - if (d5 * d5 + d6 * d6 > 0.001) { - this.setYRot((float) (Mth.atan2(d6, d5) * 180.0 / 3.141592653589793)); - if (this.flipped) { - this.setYRot(this.getYRot() + 180.0f); - } - } - double d7 = Mth.wrapDegrees(this.getYRot() - this.yRotO); - if (d7 < -170.0 || d7 >= 170.0) { - this.setYRot(this.getYRot() + 180.0f); - this.flipped = !this.flipped; - } - this.setRot(this.getYRot(), this.getXRot()); - org.bukkit.World bworld = this.level().bridge$getWorld(); - Location from = this.arclight$prevLocation; - this.arclight$prevLocation = null; - from.setWorld(bworld); - Location to = new Location(bworld, this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); - Vehicle vehicle = (Vehicle) this.getBukkitEntity(); - Bukkit.getPluginManager().callEvent(new VehicleUpdateEvent(vehicle)); - if (!from.equals(to)) { - Bukkit.getPluginManager().callEvent(new VehicleMoveEvent(vehicle, from, to)); - } - if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01) { - List list = this.level().getEntities((AbstractMinecart) (Object) this, this.getBoundingBox().inflate(0.20000000298023224, 0.0, 0.20000000298023224), EntitySelector.pushableBy((AbstractMinecart) (Object) this)); - if (!list.isEmpty()) { - for (Entity entity : list) { - if (!(entity instanceof Player) && !(entity instanceof IronGolem) && !(entity instanceof AbstractMinecart) && !this.isVehicle() && !entity.isPassenger()) { - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity).bridge$getBukkitEntity()); - Bukkit.getPluginManager().callEvent(collisionEvent); - if (!collisionEvent.isCancelled()) { - entity.startRiding((AbstractMinecart) (Object) this); - } - } else { - if (!isPassengerOfSameVehicle(entity)) { - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity).bridge$getBukkitEntity()); - Bukkit.getPluginManager().callEvent(collisionEvent); - if (collisionEvent.isCancelled()) { - continue; - } - } - entity.push((AbstractMinecart) (Object) this); - } - } - } - } else { - for (Entity entity2 : this.level().getEntities((AbstractMinecart) (Object) this, this.getBoundingBox().inflate(0.20000000298023224, 0.0, 0.20000000298023224))) { - if (!this.hasPassenger(entity2) && entity2.isPushable() && entity2 instanceof AbstractMinecart) { - VehicleEntityCollisionEvent collisionEvent2 = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity2).bridge$getBukkitEntity()); - Bukkit.getPluginManager().callEvent(collisionEvent2); - if (collisionEvent2.isCancelled()) { - continue; - } - entity2.push((AbstractMinecart) (Object) this); - } - } - } - this.updateInWaterStateAndDoFluidPushing(); - if (this.isInLava()) { - this.lavaHurt(); - this.fallDistance *= 0.5F; + return (boolean) DecorationOps.callsite().invoke(instance, entity); + } + + @Decorate(method = "tick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/Entity;push(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$pushCollide(Entity instance, Entity entity) throws Throwable { + if (!this.isPassengerOfSameVehicle(instance)) { + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), instance.bridge$getBukkitEntity()); + Bukkit.getPluginManager().callEvent(collisionEvent); + if (collisionEvent.isCancelled()) { + return; } - this.firstTick = false; } + DecorationOps.callsite().invoke(instance, entity); + } + + @Decorate(method = "tick", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/entity/Entity;push(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$pushCollide2(Entity instance, Entity entity) throws Throwable { + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), instance.bridge$getBukkitEntity()); + Bukkit.getPluginManager().callEvent(collisionEvent); + if (collisionEvent.isCancelled()) { + return; + } + DecorationOps.callsite().invoke(instance, entity); } /** @@ -198,7 +125,7 @@ public void tick() { */ @Overwrite protected double getMaxSpeed() { - return maxSpeed; + return (this.isInWater() ? this.maxSpeed / 2.0D : this.maxSpeed); } /** diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/BoatMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/BoatMixin.java index f7ccbbb9f..55b297925 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/BoatMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/BoatMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.entity.vehicle; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.vehicle.Boat; import org.bukkit.Bukkit; @@ -13,7 +15,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Boat.class) @@ -50,9 +51,9 @@ public abstract class BoatMixin extends VehicleEntityMixin { this.lastLocation = vehicle.getLocation(); } - @Redirect(method = "checkFallDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;isRemoved()Z")) - private boolean arclight$breakVehicle(Boat boatEntity) { - if (!boatEntity.isRemoved()) { + @Decorate(method = "checkFallDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;isRemoved()Z")) + private boolean arclight$breakVehicle(Boat boatEntity) throws Throwable { + if (!(boolean) DecorationOps.callsite().invoke(boatEntity)) { final Vehicle vehicle = (Vehicle) this.getBukkitEntity(); final VehicleDestroyEvent event = new VehicleDestroyEvent(vehicle, null); Bukkit.getPluginManager().callEvent(event); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java index 7f22eb045..0c6460468 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/vehicle/VehicleEntityMixin.java @@ -1,83 +1,67 @@ package io.izzel.arclight.common.mixin.core.world.entity.vehicle; import io.izzel.arclight.common.mixin.core.world.entity.EntityMixin; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.VehicleEntity; -import net.minecraft.world.level.gameevent.GameEvent; import org.bukkit.Bukkit; import org.bukkit.entity.Vehicle; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.vehicle.VehicleDamageEvent; import org.bukkit.event.vehicle.VehicleDestroyEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(VehicleEntity.class) public abstract class VehicleEntityMixin extends EntityMixin { // @formatter:off - @Shadow public abstract void setHurtDir(int rollingDirection); - @Shadow public abstract int getHurtDir(); - @Shadow public abstract void setHurtTime(int rollingAmplitude); @Shadow public abstract void setDamage(float damage); - @Shadow public abstract float getDamage(); - @Shadow protected abstract void destroy(DamageSource source); - @Shadow public abstract int getHurtTime(); - @Shadow abstract boolean shouldSourceDestroy(DamageSource p_309621_); // @formatter:on - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean hurt(DamageSource source, float amount) { - if (this.level().isClientSide || this.isRemoved()) { - return true; - } - if (this.isInvulnerableTo(source)) { - return false; - } + @Decorate(method = "hurt", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/VehicleEntity;setHurtDir(I)V")) + private void arclight$vehicleDamage(DamageSource source, float amount) throws Throwable { Vehicle vehicle = (Vehicle) this.getBukkitEntity(); org.bukkit.entity.Entity passenger = (source.getEntity() == null) ? null : source.getEntity().bridge$getBukkitEntity(); VehicleDamageEvent event = new VehicleDamageEvent(vehicle, passenger, amount); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - return false; + DecorationOps.cancel().invoke(false); + return; } amount = (float) event.getDamage(); - this.setHurtDir(-this.getHurtDir()); - this.setHurtTime(10); - this.markHurt(); - this.setDamage(this.getDamage() + amount * 10.0f); - this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity()); - boolean flag = source.getEntity() instanceof Player && ((Player) source.getEntity()).getAbilities().instabuild; - if ((flag || this.getDamage() <= 40.0f)&& !this.shouldSourceDestroy(source)) { - if (flag) { - // CraftBukkit start - VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger); - Bukkit.getPluginManager().callEvent(destroyEvent); + DecorationOps.blackhole().invoke(amount); + } + + @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/VehicleEntity;discard()V")) + private void arclight$playerDestroy(DamageSource source, float f, CallbackInfoReturnable cir) { + Vehicle vehicle = (Vehicle) this.getBukkitEntity(); + org.bukkit.entity.Entity passenger = (source.getEntity() == null) ? null : source.getEntity().bridge$getBukkitEntity(); + VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger); + Bukkit.getPluginManager().callEvent(destroyEvent); - if (destroyEvent.isCancelled()) { - this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away - return true; - } - // CraftBukkit end - this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DEATH); - this.discard(); - } - } else { - VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger); - Bukkit.getPluginManager().callEvent(destroyEvent); + if (destroyEvent.isCancelled()) { + this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away + cir.setReturnValue(true); + return; + } + this.bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.DEATH); + } + + @Inject(method = "hurt", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/VehicleEntity;destroy(Lnet/minecraft/world/damagesource/DamageSource;)V")) + private void arclight$destroy(DamageSource source, float f, CallbackInfoReturnable cir) { + Vehicle vehicle = (Vehicle) this.getBukkitEntity(); + org.bukkit.entity.Entity passenger = (source.getEntity() == null) ? null : source.getEntity().bridge$getBukkitEntity(); + VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger); + Bukkit.getPluginManager().callEvent(destroyEvent); - if (destroyEvent.isCancelled()) { - this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away - return true; - } - this.destroy(source); + if (destroyEvent.isCancelled()) { + this.setDamage(40.0F); // Maximize damage so this doesn't get triggered again right away + cir.setReturnValue(true); } - return true; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/food/FoodDataMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/food/FoodDataMixin.java index 1cadeeca3..b262bede3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/food/FoodDataMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/food/FoodDataMixin.java @@ -6,12 +6,13 @@ import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; import io.izzel.arclight.common.mod.mixins.annotation.CreateConstructor; import io.izzel.arclight.common.mod.mixins.annotation.ShadowConstructor; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.network.protocol.game.ClientboundSetHealthPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodData; import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityExhaustionEvent; @@ -21,7 +22,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(FoodData.class) @@ -50,19 +50,27 @@ public abstract class FoodDataMixin implements FoodStatsBridge { this.entityhuman = playerEntity; } - @Redirect(method = "eat(Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/ItemStack;)V", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) - private void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, Item maybeFood, ItemStack stack) { - if (this.entityhuman == null) { - foodStats.eat(foodLevelIn, foodSaturationModifier); - return; - } - FoodProperties food = this.bridge$forge$getFoodProperties(stack, this.entityhuman); - int oldFoodLevel = this.foodLevel; - FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(this.entityhuman, food.getNutrition() + oldFoodLevel, stack); - if (!event.isCancelled()) { - this.eat(event.getFoodLevel() - oldFoodLevel, food.getSaturationModifier()); + private transient ItemStack arclight$eatStack; + + @Override + public void bridge$pushEatStack(ItemStack stack) { + this.arclight$eatStack = stack; + } + + @Decorate(method = "eat(Lnet/minecraft/world/food/FoodProperties;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/food/FoodData;add(IF)V")) + private void arclight$foodLevelChange(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, FoodProperties food) throws Throwable { + var stack = this.arclight$eatStack; + this.arclight$eatStack = null; + if (this.entityhuman != null && stack != null) { + int oldFoodLevel = this.foodLevel; + FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(this.entityhuman, foodLevel, stack); + if (event.isCancelled()) { + return; + } + foodLevelIn = event.getFoodLevel() - oldFoodLevel; + ((ServerPlayerEntityBridge) this.entityhuman).bridge$getBukkitEntity().sendHealthUpdate(); } - ((ServerPlayerEntityBridge) this.entityhuman).bridge$getBukkitEntity().sendHealthUpdate(); + DecorationOps.callsite().invoke(foodStats, foodLevelIn, foodSaturationModifier); } @Inject(method = "tick", at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Ljava/lang/Math;max(II)I")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java index 9371bbd9d..bfe817393 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AbstractContainerMenuMixin.java @@ -2,15 +2,16 @@ import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import io.izzel.arclight.common.bridge.core.inventory.container.SlotBridge; import io.izzel.arclight.common.mod.server.ArclightContainer; +import io.izzel.arclight.common.mod.util.Blackhole; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.NonNullList; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.SlotAccess; -import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickAction; @@ -25,40 +26,25 @@ import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.event.Event; import org.bukkit.event.inventory.InventoryDragEvent; -import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.InventoryView; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; -import java.util.Optional; -import java.util.Set; - -import static net.minecraft.world.inventory.AbstractContainerMenu.getQuickCraftPlaceCount; @Mixin(AbstractContainerMenu.class) public abstract class AbstractContainerMenuMixin implements ContainerBridge { // @formatter:off - @Shadow public void broadcastChanges() {} - @Shadow private int quickcraftStatus; - @Shadow protected abstract void resetQuickCraft(); @Shadow private int quickcraftType; - @Shadow @Final private Set quickcraftSlots; - @Shadow public abstract boolean canDragTo(Slot slotIn); - @Shadow public abstract ItemStack quickMoveStack(Player playerIn, int index); - @Shadow public abstract boolean canTakeItemForPickAll(ItemStack stack, Slot slotIn); - @Shadow @Final public int containerId; - @Shadow public abstract Slot getSlot(int slotId); - @Shadow public static int getQuickcraftHeader(int clickedButton) { return 0; } - @Shadow public static int getQuickcraftType(int eventButton) { return 0; } - @Shadow public static boolean isValidQuickcraftType(int dragModeIn, Player player) { return false; } - @Shadow public static boolean canItemQuickReplace(@Nullable Slot slotIn, ItemStack stack, boolean stackSizeMatters) { return false; } - @Shadow protected abstract boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection); @Shadow @Final @javax.annotation.Nullable private MenuType menuType; @Shadow private ItemStack remoteCarried; @Shadow public abstract ItemStack getCarried(); @@ -121,243 +107,71 @@ public void broadcastCarriedItem() { } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private void doClick(int slotId, int dragType, ClickType clickType, Player player) { - Inventory inventory = player.getInventory(); - if (clickType == ClickType.QUICK_CRAFT) { - int j1 = this.quickcraftStatus; - this.quickcraftStatus = getQuickcraftHeader(dragType); - if ((j1 != 1 || this.quickcraftStatus != 2) && j1 != this.quickcraftStatus) { - this.resetQuickCraft(); - } else if (this.getCarried().isEmpty()) { - this.resetQuickCraft(); - } else if (this.quickcraftStatus == 0) { - this.quickcraftType = getQuickcraftType(dragType); - if (isValidQuickcraftType(this.quickcraftType, player)) { - this.quickcraftStatus = 1; - this.quickcraftSlots.clear(); - } else { - this.resetQuickCraft(); - } - } else if (this.quickcraftStatus == 1) { - Slot slot7 = this.slots.get(slotId); - ItemStack itemstack12 = this.getCarried(); - if (canItemQuickReplace(slot7, itemstack12, true) && slot7.mayPlace(itemstack12) && (this.quickcraftType == 2 || itemstack12.getCount() > this.quickcraftSlots.size()) && this.canDragTo(slot7)) { - this.quickcraftSlots.add(slot7); - } - } else if (this.quickcraftStatus == 2) { - if (!this.quickcraftSlots.isEmpty()) { - if (false && this.quickcraftSlots.size() == 1) { - int l = (this.quickcraftSlots.iterator().next()).index; - this.resetQuickCraft(); - this.doClick(l, this.quickcraftType, ClickType.PICKUP, player); - return; - } - ItemStack itemstack9 = this.getCarried().copy(); - if (itemstack9.isEmpty()) { - this.resetQuickCraft(); - return; - } - - int k1 = this.getCarried().getCount(); - - Map draggedSlots = new HashMap<>(); - - for (Slot slot8 : this.quickcraftSlots) { - ItemStack itemstack13 = this.getCarried(); - if (slot8 != null && canItemQuickReplace(slot8, itemstack13, true) && slot8.mayPlace(itemstack13) && (this.quickcraftType == 2 || itemstack13.getCount() >= this.quickcraftSlots.size()) && this.canDragTo(slot8)) { - int j3 = slot8.hasItem() ? slot8.getItem().getCount() : 0; - int k3 = Math.min(itemstack9.getMaxStackSize(), slot8.getMaxStackSize(itemstack9)); - int l3 = Math.min(getQuickCraftPlaceCount(this.quickcraftSlots, this.quickcraftType, itemstack9) + j3, k3); + @Decorate(method = "doClick", inject = true, at = @At(value = "INVOKE", ordinal = 1, target = "Ljava/util/Set;iterator()Ljava/util/Iterator;")) + private void arclight$initDraggedSlots(@Local(allocate = "draggedSlots") Map draggedSlots) throws Throwable { + draggedSlots = new HashMap<>(); + DecorationOps.blackhole().invoke(draggedSlots); + } - k1 -= l3 - j3; - // slot8.set(itemstack14); - draggedSlots.put(slot8.index, itemstack9.copyWithCount(l3)); - } - } + @Decorate(method = "doClick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/inventory/Slot;setByPlayer(Lnet/minecraft/world/item/ItemStack;)V")) + private void arclight$captureDragged(Slot instance, ItemStack itemStack, @Local(allocate = "draggedSlots") Map draggedSlots) throws Throwable { + if (draggedSlots != null) { + draggedSlots.put(instance.index, itemStack); + } else { + DecorationOps.callsite().invoke(instance, itemStack); + } + } - InventoryView view = this.getBukkitView(); - org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack9); - newcursor.setAmount(k1); - Map eventmap = new HashMap<>(); - for (Map.Entry ditem : draggedSlots.entrySet()) { - eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); - } - ItemStack oldCursor = this.getCarried(); - this.setCarried(CraftItemStack.asNMSCopy(newcursor)); - InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); - Bukkit.getPluginManager().callEvent(event); - boolean needsUpdate = event.getResult() != Event.Result.DEFAULT; - if (event.getResult() != Event.Result.DENY) { - for (Map.Entry dslot : draggedSlots.entrySet()) { - view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); - } - if (this.getCarried() != null) { - this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); - needsUpdate = true; - } - } else { - this.setCarried(oldCursor); - } - if (needsUpdate && player instanceof ServerPlayer) { - this.sendAllDataToRemote(); - } - } - this.resetQuickCraft(); - } else { - this.resetQuickCraft(); + @Decorate(method = "doClick", at = @At(value = "INVOKE", ordinal = 0, target = "Ljava/util/Iterator;hasNext()Z")) + private boolean arclight$captureEnd(Iterator iterator, + @Local(ordinal = 0) Player player, + @Local(ordinal = -1) ItemStack carried, + @Local(ordinal = -1) int count, + @Local(allocate = "draggedSlots") Map draggedSlots) throws Throwable { + boolean hasNext = (boolean) DecorationOps.callsite().invoke(iterator); + if (!hasNext && draggedSlots != null) { + InventoryView view = this.getBukkitView(); + org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(carried); + newcursor.setAmount(count); + Map eventmap = new HashMap<>(); + for (Map.Entry ditem : draggedSlots.entrySet()) { + eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue())); } - } else if (this.quickcraftStatus != 0) { - this.resetQuickCraft(); - } else if ((clickType == ClickType.PICKUP || clickType == ClickType.QUICK_MOVE) && (dragType == 0 || dragType == 1)) { - ClickAction clickaction = dragType == 0 ? ClickAction.PRIMARY : ClickAction.SECONDARY; - if (slotId == -999) { - if (!this.getCarried().isEmpty()) { - if (clickaction == ClickAction.PRIMARY) { - ItemStack carried = this.getCarried(); - this.setCarried(ItemStack.EMPTY); - player.drop(carried, true); - } else { - player.drop(this.getCarried().split(1), true); - } - } - } else if (clickType == ClickType.QUICK_MOVE) { - if (slotId < 0) { - return; + ItemStack oldCursor = this.getCarried(); + this.setCarried(CraftItemStack.asNMSCopy(newcursor)); + InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.quickcraftType == 1, eventmap); + Bukkit.getPluginManager().callEvent(event); + boolean needsUpdate = event.getResult() != Event.Result.DEFAULT; + if (event.getResult() != Event.Result.DENY) { + for (Map.Entry dslot : draggedSlots.entrySet()) { + view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue())); } - - Slot slot6 = this.slots.get(slotId); - if (!slot6.mayPickup(player)) { - return; - } - - for (ItemStack itemstack9 = this.quickMoveStack(player, slotId); !itemstack9.isEmpty() && ItemStack.isSameItem(slot6.getItem(), itemstack9); itemstack9 = this.quickMoveStack(player, slotId)) { + if (this.getCarried() != null) { + this.setCarried(CraftItemStack.asNMSCopy(event.getCursor())); + needsUpdate = true; } } else { - if (slotId < 0) { - return; - } - - Slot slot7 = this.slots.get(slotId); - ItemStack itemstack10 = slot7.getItem(); - ItemStack itemstack11 = this.getCarried(); - player.updateTutorialInventoryAction(itemstack11, slot7.getItem(), clickaction); - if (!this.tryItemClickBehaviourOverride(player, clickaction, slot7, itemstack10, itemstack11) && !this.bridge$forge$onItemStackedOn(itemstack10, itemstack11, slot7, clickaction, player, this.createCarriedSlotAccess())) { - if (itemstack10.isEmpty()) { - if (!itemstack11.isEmpty()) { - int l2 = clickaction == ClickAction.PRIMARY ? itemstack11.getCount() : 1; - this.setCarried(slot7.safeInsert(itemstack11, l2)); - } - } else if (slot7.mayPickup(player)) { - if (itemstack11.isEmpty()) { - int i3 = clickaction == ClickAction.PRIMARY ? itemstack10.getCount() : (itemstack10.getCount() + 1) / 2; - Optional optional1 = slot7.tryRemove(i3, Integer.MAX_VALUE, player); - optional1.ifPresent((p_150421_) -> { - this.setCarried(p_150421_); - slot7.onTake(player, p_150421_); - }); - } else if (slot7.mayPlace(itemstack11)) { - if (ItemStack.isSameItemSameTags(itemstack10, itemstack11)) { - int j3 = clickaction == ClickAction.PRIMARY ? itemstack11.getCount() : 1; - this.setCarried(slot7.safeInsert(itemstack11, j3)); - } else if (itemstack11.getCount() <= slot7.getMaxStackSize(itemstack11)) { - this.setCarried(itemstack10); - slot7.setByPlayer(itemstack11); - } - } else if (ItemStack.isSameItemSameTags(itemstack10, itemstack11)) { - Optional optional = slot7.tryRemove(itemstack10.getCount(), itemstack11.getMaxStackSize() - itemstack11.getCount(), player); - optional.ifPresent((p_150428_) -> { - itemstack11.grow(p_150428_.getCount()); - slot7.onTake(player, p_150428_); - }); - } - } - } - - slot7.setChanged(); - - if (player instanceof ServerPlayer && slot7.getMaxStackSize() != 64) { - ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), slot7.index, slot7.getItem())); - // Updating a crafting inventory makes the client reset the result slot, have to send it again - if (this.getBukkitView().getType() == InventoryType.WORKBENCH || this.getBukkitView().getType() == InventoryType.CRAFTING) { - ((ServerPlayer) player).connection.send(new ClientboundContainerSetSlotPacket(this.containerId, this.incrementStateId(), 0, this.getSlot(0).getItem())); - } - } + this.setCarried(oldCursor); } - } else if (clickType == ClickType.SWAP && (dragType >= 0 && dragType < 9 || dragType == 40)) { - Slot slot2 = this.slots.get(slotId); - ItemStack itemstack4 = inventory.getItem(dragType); - ItemStack itemstack7 = slot2.getItem(); - if (!itemstack4.isEmpty() || !itemstack7.isEmpty()) { - if (itemstack4.isEmpty()) { - if (slot2.mayPickup(player)) { - inventory.setItem(dragType, itemstack7); - ((SlotBridge) slot2).bridge$onSwapCraft(itemstack7.getCount()); - slot2.setByPlayer(ItemStack.EMPTY); - slot2.onTake(player, itemstack7); - } - } else if (itemstack7.isEmpty()) { - if (slot2.mayPlace(itemstack4)) { - int l1 = slot2.getMaxStackSize(itemstack4); - if (itemstack4.getCount() > l1) { - slot2.setByPlayer(itemstack4.split(l1)); - } else { - inventory.setItem(dragType, ItemStack.EMPTY); - slot2.setByPlayer(itemstack4); - } - } - } else if (slot2.mayPickup(player) && slot2.mayPlace(itemstack4)) { - int i2 = slot2.getMaxStackSize(itemstack4); - if (itemstack4.getCount() > i2) { - slot2.setByPlayer(itemstack4.split(i2)); - slot2.onTake(player, itemstack7); - if (!inventory.add(itemstack7)) { - player.drop(itemstack7, true); - } - } else { - inventory.setItem(dragType, itemstack7); - slot2.setByPlayer(itemstack4); - slot2.onTake(player, itemstack7); - } - } - } - } else if (clickType == ClickType.CLONE && player.getAbilities().instabuild && this.getCarried().isEmpty() && slotId >= 0) { - Slot slot5 = this.slots.get(slotId); - if (slot5.hasItem()) { - ItemStack itemstack6 = slot5.getItem(); - this.setCarried(itemstack6.copyWithCount(itemstack6.getMaxStackSize())); - } - } else if (clickType == ClickType.THROW && this.getCarried().isEmpty() && slotId >= 0) { - Slot slot4 = this.slots.get(slotId); - int i1 = dragType == 0 ? 1 : slot4.getItem().getCount(); - ItemStack itemstack8 = slot4.safeTake(i1, Integer.MAX_VALUE, player); - player.drop(itemstack8, true); - } else if (clickType == ClickType.PICKUP_ALL && slotId >= 0) { - Slot slot3 = this.slots.get(slotId); - ItemStack itemstack5 = this.getCarried(); - if (!itemstack5.isEmpty() && (!slot3.hasItem() || !slot3.mayPickup(player))) { - int k1 = dragType == 0 ? 0 : this.slots.size() - 1; - int j2 = dragType == 0 ? 1 : -1; - - for (int k2 = 0; k2 < 2; ++k2) { - for (int k3 = k1; k3 >= 0 && k3 < this.slots.size() && itemstack5.getCount() < itemstack5.getMaxStackSize(); k3 += j2) { - Slot slot8 = this.slots.get(k3); - if (slot8.hasItem() && canItemQuickReplace(slot8, itemstack5, true) && slot8.mayPickup(player) && this.canTakeItemForPickAll(itemstack5, slot8)) { - ItemStack itemstack12 = slot8.getItem(); - if (k2 != 0 || itemstack12.getCount() != itemstack12.getMaxStackSize()) { - ItemStack itemstack13 = slot8.safeTake(itemstack12.getCount(), itemstack5.getMaxStackSize() - itemstack5.getCount(), player); - itemstack5.grow(itemstack13.getCount()); - } - } - } - } + if (needsUpdate && player instanceof ServerPlayer) { + this.sendAllDataToRemote(); } } + return hasNext; + } + + @Inject(method = "doClick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/entity/player/Player;drop(Lnet/minecraft/world/item/ItemStack;Z)Lnet/minecraft/world/entity/item/ItemEntity;"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/inventory/ClickAction;PRIMARY:Lnet/minecraft/world/inventory/ClickAction;"))) + private void arclight$clearBeforeDrop(int i, int j, ClickType clickType, Player player, CallbackInfo ci) { + this.setCarried(ItemStack.EMPTY); + } + @Decorate(method = "doClick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/inventory/AbstractContainerMenu;setCarried(Lnet/minecraft/world/item/ItemStack;)V"), + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/inventory/ClickAction;PRIMARY:Lnet/minecraft/world/inventory/ClickAction;"))) + private void arclight$skipAfterDrop(AbstractContainerMenu instance, ItemStack itemStack) throws Throwable { + if (Blackhole.actuallyFalse()) { + DecorationOps.callsite().invoke(instance, itemStack); + } } /** diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AnvilMenuMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AnvilMenuMixin.java index f93d426e7..7dfca6da1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AnvilMenuMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/AnvilMenuMixin.java @@ -3,26 +3,27 @@ import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.AnvilMenuBridge; import io.izzel.arclight.common.bridge.core.util.IWorldPosCallableBridge; -import net.minecraft.Util; -import net.minecraft.network.chat.Component; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.DataSlot; -import net.minecraft.world.item.EnchantedBookItem; +import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.inventory.CraftInventory; import org.bukkit.craftbukkit.v.inventory.CraftInventoryAnvil; import org.bukkit.craftbukkit.v.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v.inventory.CraftItemStack; +import org.bukkit.event.inventory.PrepareAnvilEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; - -import java.util.Map; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyConstant; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(AnvilMenu.class) public abstract class AnvilMenuMixin extends ItemCombinerMixin implements AnvilMenuBridge { @@ -41,192 +42,26 @@ public abstract class AnvilMenuMixin extends ItemCombinerMixin implements AnvilM private CraftInventoryView bukkitEntity; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void createResult() { - // define constants for ModifyConstant mixins to work - cancelThisBySettingCostToMaximum = 40; - maximumRenameCostThreshold = 40; - maximumAllowedRenameCost = 39; - maximumRepairCost = 40; - - ItemStack itemstack = this.inputSlots.getItem(0); - this.cost.set(1); - int i = 0; - int j = 0; - int k = 0; - if (itemstack.isEmpty()) { - // this.outputSlot.setInventorySlotContents(0, ItemStack.EMPTY); - CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); - this.cost.set(0); - } else { - ItemStack itemstack1 = itemstack.copy(); - ItemStack itemstack2 = this.inputSlots.getItem(1); - Map map = EnchantmentHelper.getEnchantments(itemstack1); - j = j + itemstack.getBaseRepairCost() + (itemstack2.isEmpty() ? 0 : itemstack2.getBaseRepairCost()); - this.repairItemCountCost = 0; - boolean flag = false; - if (!this.bridge$forge$onAnvilChange((AnvilMenu) (Object) this, itemstack, itemstack2, resultSlots, itemName, j, this.player)) - return; - - if (!itemstack2.isEmpty()) { - flag = itemstack2.getItem() == Items.ENCHANTED_BOOK && !EnchantedBookItem.getEnchantments(itemstack2).isEmpty(); - if (itemstack1.isDamageableItem() && itemstack1.getItem().isValidRepairItem(itemstack, itemstack2)) { - int l2 = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); - if (l2 <= 0) { - // this.outputSlot.setInventorySlotContents(0, ItemStack.EMPTY); - CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); - this.cost.set(0); - return; - } - - int i3; - for (i3 = 0; l2 > 0 && i3 < itemstack2.getCount(); ++i3) { - int j3 = itemstack1.getDamageValue() - l2; - itemstack1.setDamageValue(j3); - ++i; - l2 = Math.min(itemstack1.getDamageValue(), itemstack1.getMaxDamage() / 4); - } - - this.repairItemCountCost = i3; - } else { - if (!flag && (itemstack1.getItem() != itemstack2.getItem() || !itemstack1.isDamageableItem())) { - // this.outputSlot.setInventorySlotContents(0, ItemStack.EMPTY); - CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); - this.cost.set(0); - return; - } - - if (itemstack1.isDamageableItem() && !flag) { - int l = itemstack.getMaxDamage() - itemstack.getDamageValue(); - int i1 = itemstack2.getMaxDamage() - itemstack2.getDamageValue(); - int j1 = i1 + itemstack1.getMaxDamage() * 12 / 100; - int k1 = l + j1; - int l1 = itemstack1.getMaxDamage() - k1; - if (l1 < 0) { - l1 = 0; - } - - if (l1 < itemstack1.getDamageValue()) { - itemstack1.setDamageValue(l1); - i += 2; - } - } - - Map map1 = EnchantmentHelper.getEnchantments(itemstack2); - boolean flag2 = false; - boolean flag3 = false; - - for (Enchantment enchantment1 : map1.keySet()) { - if (enchantment1 != null) { - int i2 = map.getOrDefault(enchantment1, 0); - int j2 = map1.get(enchantment1); - j2 = i2 == j2 ? j2 + 1 : Math.max(j2, i2); - boolean flag1 = enchantment1.canEnchant(itemstack); - if (this.player.getAbilities().instabuild || itemstack.getItem() == Items.ENCHANTED_BOOK) { - flag1 = true; - } - - for (Enchantment enchantment : map.keySet()) { - if (enchantment != enchantment1 && !enchantment1.isCompatibleWith(enchantment)) { - flag1 = false; - ++i; - } - } - - if (!flag1) { - flag3 = true; - } else { - flag2 = true; - if (j2 > enchantment1.getMaxLevel()) { - j2 = enchantment1.getMaxLevel(); - } - - map.put(enchantment1, j2); - int k3 = 0; - switch (enchantment1.getRarity()) { - case COMMON: - k3 = 1; - break; - case UNCOMMON: - k3 = 2; - break; - case RARE: - k3 = 4; - break; - case VERY_RARE: - k3 = 8; - } - - if (flag) { - k3 = Math.max(1, k3 / 2); - } - - i += k3 * j2; - if (itemstack.getCount() > 1) { - i = cancelThisBySettingCostToMaximum; - } - } - } - } - - if (flag3 && !flag2) { - // this.outputSlot.setInventorySlotContents(0, ItemStack.EMPTY); - CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), ItemStack.EMPTY); - this.cost.set(0); - return; - } - } - } - - if (this.itemName != null && !Util.isBlank(this.itemName)) { - if (!this.itemName.equals(itemstack.getHoverName().getString())) { - k = 1; - i += k; - itemstack1.setHoverName(Component.literal(this.itemName)); - } - } else if (itemstack.hasCustomHoverName()) { - k = 1; - i += k; - itemstack1.resetHoverName(); - } - if (flag && !this.bridge$forge$isBookEnchantable(itemstack1, itemstack2)) itemstack1 = ItemStack.EMPTY; - - this.cost.set(j + i); - if (i <= 0) { - itemstack1 = ItemStack.EMPTY; - } - - if (k == i && k > 0 && this.cost.get() >= maximumRenameCostThreshold) { - this.cost.set(maximumAllowedRenameCost); - } - - if (this.cost.get() >= maximumRepairCost && !this.player.getAbilities().instabuild) { - itemstack1 = ItemStack.EMPTY; - } - - if (!itemstack1.isEmpty()) { - int k2 = itemstack1.getBaseRepairCost(); - if (!itemstack2.isEmpty() && k2 < itemstack2.getBaseRepairCost()) { - k2 = itemstack2.getBaseRepairCost(); - } + @Decorate(method = "createResult", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V")) + private void arclight$prepareAnvilEvent(ResultContainer instance, int i, ItemStack itemStack) throws Throwable { + var event = new PrepareAnvilEvent(getBukkitView(), CraftItemStack.asCraftMirror(itemStack).clone()); + Bukkit.getServer().getPluginManager().callEvent(event); + DecorationOps.callsite().invoke(instance, i, CraftItemStack.asNMSCopy(event.getResult())); + } - if (k != i || k == 0) { - k2 = calculateIncreasedRepairCost(k2); - } + @Inject(method = "createResult", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/AnvilMenu;broadcastChanges()V")) + private void arclight$sync(CallbackInfo ci) { + this.sendAllDataToRemote(); + } - itemstack1.setRepairCost(k2); - EnchantmentHelper.setEnchantments(map, itemstack1); - } + @ModifyConstant(method = "createResult", constant = @Constant(intValue = 40)) + private int arclight$maximumRepairCost(int i) { + return i - 40 + maximumRepairCost; + } - // this.outputSlot.setInventorySlotContents(0, itemstack1); - CraftEventFactory.callPrepareAnvilEvent(getBukkitView(), itemstack1); - this.sendAllDataToRemote(); - this.broadcastChanges(); - } + @ModifyConstant(method = "createResult", constant = @Constant(intValue = 39)) + private int arclight$maximumRepairCost2(int i) { + return i - 40 + maximumRepairCost; } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingContainerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingContainerMixin.java new file mode 100644 index 000000000..b3a1a4974 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingContainerMixin.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.common.mixin.core.world.inventory; + +import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; +import net.minecraft.world.inventory.CraftingContainer; +import net.minecraft.world.item.crafting.RecipeHolder; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(CraftingContainer.class) +public interface CraftingContainerMixin extends IInventoryBridge { + + @Override + default RecipeHolder getCurrentRecipe() { + return null; + } + + @Override + default void setCurrentRecipe(RecipeHolder recipe) { + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingMenuMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingMenuMixin.java index 773f15e80..27dd51283 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingMenuMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/CraftingMenuMixin.java @@ -2,9 +2,13 @@ import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.inventory.CraftingInventoryBridge; +import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; import io.izzel.arclight.common.bridge.core.inventory.container.PosContainerBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -21,6 +25,7 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.inventory.CraftInventoryCrafting; import org.bukkit.craftbukkit.v.inventory.CraftInventoryView; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; @@ -28,7 +33,6 @@ import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -60,14 +64,17 @@ public abstract class CraftingMenuMixin extends AbstractContainerMenuMixin imple private static transient boolean arclight$isRepair; @Redirect(method = "slotChangedCraftingGrid", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/Optional;isPresent()Z")) - private static boolean arclight$testRepair(Optional> optional) { + private static boolean arclight$testRepair(Optional> optional, AbstractContainerMenu abstractContainerMenu, Level level, Player player, CraftingContainer craftingContainer) { + ((IInventoryBridge) craftingContainer).setCurrentRecipe(optional.orElse(null)); arclight$isRepair = optional.map(RecipeHolder::value).orElse(null) instanceof RepairItemRecipe; return optional.isPresent(); } - @ModifyVariable(method = "slotChangedCraftingGrid", ordinal = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V")) - private static ItemStack arclight$preCraft(ItemStack stack, AbstractContainerMenu container, Level level, Player player, CraftingContainer craftingContainer, ResultContainer resultContainer) { - return CraftEventFactory.callPreCraftEvent(craftingContainer, resultContainer, stack, ((ContainerBridge) container).bridge$getBukkitView(), arclight$isRepair); + @Decorate(method = "slotChangedCraftingGrid", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V")) + private static void arclight$preCraft(ResultContainer instance, int i, ItemStack itemStack, AbstractContainerMenu abstractContainerMenu, Level level, Player player, CraftingContainer craftingContainer, ResultContainer resultContainer, @Nullable RecipeHolder recipeHolder, + @Local(ordinal = -1) ItemStack stack) throws Throwable { + stack = CraftEventFactory.callPreCraftEvent(craftingContainer, instance, itemStack, ((ContainerBridge) abstractContainerMenu).bridge$getBukkitView(), arclight$isRepair); + DecorationOps.callsite().invoke(instance, i, stack); } @Inject(method = "(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/inventory/ContainerLevelAccess;)V", at = @At("RETURN")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/EnchantmentContainerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/EnchantmentContainerMixin.java index 66cadf9f2..4fe9d30ea 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/EnchantmentContainerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/EnchantmentContainerMixin.java @@ -5,30 +5,24 @@ import io.izzel.arclight.common.bridge.core.inventory.EnchantmentMenuBridge; import io.izzel.arclight.common.bridge.core.inventory.container.PosContainerBridge; import io.izzel.arclight.common.bridge.core.util.IWorldPosCallableBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.stats.Stats; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.core.Holder; +import net.minecraft.core.IdMap; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.Registries; import net.minecraft.util.RandomSource; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerLevelAccess; -import net.minecraft.world.inventory.DataSlot; import net.minecraft.world.inventory.EnchantmentMenu; -import net.minecraft.world.item.EnchantedBookItem; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentInstance; -import net.minecraft.world.level.block.EnchantmentTableBlock; +import net.minecraft.world.level.Level; import org.bukkit.Bukkit; -import org.bukkit.NamespacedKey; +import org.bukkit.craftbukkit.v.enchantments.CraftEnchantment; import org.bukkit.craftbukkit.v.inventory.CraftInventoryEnchanting; import org.bukkit.craftbukkit.v.inventory.CraftInventoryView; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; @@ -40,13 +34,14 @@ import org.bukkit.event.enchantment.PrepareItemEnchantEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -57,12 +52,9 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix // @formatter:off @Shadow @Final private Container enchantSlots; @Shadow @Final private ContainerLevelAccess access; - @Shadow @Final private RandomSource random; - @Shadow @Final private DataSlot enchantmentSeed; @Shadow @Final public int[] costs; @Shadow @Final public int[] enchantClue; @Shadow @Final public int[] levelClue; - @Shadow protected abstract List getEnchantmentList(ItemStack stack, int enchantSlot, int level); // @formatter:on private CraftInventoryView bukkitEntity = null; @@ -78,186 +70,94 @@ public abstract class EnchantmentContainerMixin extends AbstractContainerMenuMix if (!bridge$isCheckReachable()) cir.setReturnValue(true); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void slotsChanged(Container inventoryIn) { - if (inventoryIn == this.enchantSlots) { - ItemStack itemstack = inventoryIn.getItem(0); - if (!itemstack.isEmpty()) { - // morejs https://github.com/AlmostReliable/morejs/blob/fd738a28a054d780031c7666fc8a01533c86f63b/Common/src/main/java/com/almostreliable/morejs/mixin/enchanting/EnchantmentMenuMixin.java - boolean enchantable = itemstack.isEnchantable(); - this.access.execute((level, pos) -> { - float power = 0; + private transient boolean arclight$enchantable; - for (BlockPos blockpos : EnchantmentTableBlock.BOOKSHELF_OFFSETS) { - if (EnchantmentTableBlock.isValidBookShelf(level, pos, blockpos)) { - power += this.bridge$forge$getEnchantPowerBonus(level.getBlockState(pos.offset(blockpos)), level, pos.offset(blockpos)); - } - } - - this.random.setSeed(this.enchantmentSeed.get()); - - for (int i1 = 0; i1 < 3; ++i1) { - this.costs[i1] = EnchantmentHelper.getEnchantmentCost(this.random, i1, (int) power, itemstack); - this.enchantClue[i1] = -1; - this.levelClue[i1] = -1; - if (this.costs[i1] < i1 + 1) { - this.costs[i1] = 0; - } - this.costs[i1] = this.bridge$forge$onEnchantmentLevelSet(level, pos, i1, (int) power, itemstack, costs[i1]); - } - - for (int j1 = 0; j1 < 3; ++j1) { - if (this.costs[j1] > 0) { - List list = this.getEnchantmentList(itemstack, j1, this.costs[j1]); - if (list != null && !list.isEmpty()) { - EnchantmentInstance enchantmentdata = list.get(this.random.nextInt(list.size())); - this.enchantClue[j1] = BuiltInRegistries.ENCHANTMENT.getId(enchantmentdata.enchantment); - this.levelClue[j1] = enchantmentdata.level; - } - } - } + @Decorate(method = "slotsChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEnchantable()Z")) + private boolean arclight$relaxCondition(ItemStack instance) throws Throwable { + arclight$enchantable = (boolean) DecorationOps.callsite().invoke(instance); + return true; + } + private transient int arclight$power; - CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.enchantments.EnchantmentOffer[] offers = new EnchantmentOffer[3]; - for (int j = 0; j < 3; ++j) { - org.bukkit.enchantments.Enchantment enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(BuiltInRegistries.ENCHANTMENT.byId(this.enchantClue[j])))) : null; - offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; - } + @Decorate(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;getEnchantmentCost(Lnet/minecraft/util/RandomSource;IILnet/minecraft/world/item/ItemStack;)I")) + private int arclight$lastPower(RandomSource random, int i, int power, ItemStack arg) throws Throwable { + return (int) DecorationOps.callsite().invoke(random, i, arclight$power = power, arg); + } - PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(((ServerPlayerEntityBridge) this.playerInventory.player).bridge$getBukkitEntity(), this.getBukkitView(), ((IWorldPosCallableBridge) this.access).bridge$getLocation().getBlock(), item, offers, (int) power); - event.setCancelled(!enchantable); - Bukkit.getPluginManager().callEvent(event); + @Decorate(method = "*", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/EnchantmentMenu;broadcastChanges()V")) + private void arclight$prepareEnchantEvent(@Local(ordinal = 0) ItemStack itemstack, + @Local(ordinal = 0) Level level) { + var registry = level.registryAccess().registryOrThrow(Registries.ENCHANTMENT); + CraftItemStack item = CraftItemStack.asCraftMirror(itemstack); + var offers = new EnchantmentOffer[3]; + for (int j = 0; j < 3; ++j) { + var enchantment = (this.enchantClue[j] >= 0) ? org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(registry.getKey(registry.byId(this.enchantClue[j])))) : null; + offers[j] = (enchantment != null) ? new EnchantmentOffer(enchantment, this.levelClue[j], this.costs[j]) : null; + } - if (event.isCancelled()) { - for (int j = 0; j < 3; ++j) { - this.costs[j] = 0; - this.enchantClue[j] = -1; - this.levelClue[j] = -1; - } - return; - } + PrepareItemEnchantEvent event = new PrepareItemEnchantEvent(((ServerPlayerEntityBridge) this.playerInventory.player).bridge$getBukkitEntity(), this.getBukkitView(), ((IWorldPosCallableBridge) this.access).bridge$getLocation().getBlock(), item, offers, arclight$power); + event.setCancelled(!arclight$enchantable); + Bukkit.getPluginManager().callEvent(event); - for (int j = 0; j < 3; j++) { - EnchantmentOffer offer = event.getOffers()[j]; - if (offer != null) { - this.costs[j] = offer.getCost(); - this.enchantClue[j] = BuiltInRegistries.ENCHANTMENT.getId(BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); - this.levelClue[j] = offer.getEnchantmentLevel(); - } else { - this.costs[j] = 0; - this.enchantClue[j] = -1; - this.levelClue[j] = -1; - } - } + if (event.isCancelled()) { + for (int j = 0; j < 3; ++j) { + this.costs[j] = 0; + this.enchantClue[j] = -1; + this.levelClue[j] = -1; + } + return; + } - this.broadcastChanges(); - }); + for (int j = 0; j < 3; j++) { + EnchantmentOffer offer = event.getOffers()[j]; + if (offer != null) { + this.costs[j] = offer.getCost(); + this.enchantClue[j] = registry.getId(registry.get(CraftNamespacedKey.toMinecraft(offer.getEnchantment().getKey()))); + this.levelClue[j] = offer.getEnchantmentLevel(); } else { - for (int i = 0; i < 3; ++i) { - this.costs[i] = 0; - this.enchantClue[i] = -1; - this.levelClue[i] = -1; - } + this.costs[j] = 0; + this.enchantClue[j] = -1; + this.levelClue[j] = -1; } } - } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean clickMenuButton(net.minecraft.world.entity.player.Player playerIn, int id) { - ItemStack itemstack = this.enchantSlots.getItem(0); - ItemStack itemstack1 = this.enchantSlots.getItem(1); - int i = id + 1; - if ((itemstack1.isEmpty() || itemstack1.getCount() < i) && !playerIn.getAbilities().instabuild) { - return false; - } else if (this.costs[id] <= 0 || itemstack.isEmpty() || (playerIn.experienceLevel < i || playerIn.experienceLevel < this.costs[id]) && !playerIn.getAbilities().instabuild) { - return false; - } else { - this.access.execute((p_217003_6_, p_217003_7_) -> { - ItemStack itemstack2 = itemstack; - List list = this.getEnchantmentList(itemstack, id, this.costs[id]); - if (true || !list.isEmpty()) { - - // playerIn.onEnchant(itemstack, i); - Map enchants = new java.util.HashMap<>(); - for (EnchantmentInstance obj : list) { - enchants.put(org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(obj.enchantment))), obj.level); - } - CraftItemStack item = CraftItemStack.asCraftMirror(itemstack2); - - var hintedEnchantment = org.bukkit.enchantments.Enchantment.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.ENCHANTMENT.getKey(net.minecraft.world.item.enchantment.Enchantment.byId(enchantClue[id])))); - int hintedEnchantmentLevel = levelClue[id]; - EnchantItemEvent event = new EnchantItemEvent(((Player) ((PlayerEntityBridge) playerIn).bridge$getBukkitEntity()), this.getBukkitView(), ((IWorldPosCallableBridge) this.access).bridge$getLocation().getBlock(), item, this.costs[id], enchants, hintedEnchantment, hintedEnchantmentLevel, id); - Bukkit.getPluginManager().callEvent(event); - - int level = event.getExpLevelCost(); - if (event.isCancelled() || (level > playerIn.experienceLevel && !playerIn.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { - return; - } - boolean flag = itemstack.is(Items.BOOK); - - if (flag) { - itemstack2 = new ItemStack(Items.ENCHANTED_BOOK); - - CompoundTag tag = itemstack.getTag(); - if (tag != null) { - itemstack2.setTag(tag.copy()); - } - ((ItemStackBridge) (Object) itemstack2).bridge$platform$copyAdditionalFrom(itemstack); - - this.enchantSlots.setItem(0, itemstack2); - } - - for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { - try { - if (flag) { - NamespacedKey enchantId = entry.getKey().getKey(); - net.minecraft.world.item.enchantment.Enchantment nms = BuiltInRegistries.ENCHANTMENT.get(CraftNamespacedKey.toMinecraft(enchantId)); - if (nms == null) { - continue; - } - - EnchantmentInstance weightedrandomenchant = new EnchantmentInstance(nms, entry.getValue()); - EnchantedBookItem.addEnchantment(itemstack2, weightedrandomenchant); - } else { - item.addUnsafeEnchantment(entry.getKey(), entry.getValue()); - } - } catch (IllegalArgumentException e) { - /* Just swallow invalid enchantments */ - } - } - playerIn.onEnchantmentPerformed(itemstack, i); - - if (!playerIn.getAbilities().instabuild) { - itemstack1.shrink(i); - if (itemstack1.isEmpty()) { - this.enchantSlots.setItem(1, ItemStack.EMPTY); - } - } + @SuppressWarnings("unchecked") + @Decorate(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/EnchantmentMenu;getEnchantmentList(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/ItemStack;II)Ljava/util/List;"), + slice = @Slice(to = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;onEnchantmentPerformed(Lnet/minecraft/world/item/ItemStack;I)V"))) + private List arclight$itemEnchantEvent(EnchantmentMenu instance, RegistryAccess registryAccess, ItemStack itemStack, int i, int j, + @Local(ordinal = -1) Level level, + @Local(ordinal = -1) net.minecraft.world.entity.player.Player playerIn) throws Throwable { + var list = (List) DecorationOps.callsite().invoke(instance, registryAccess, itemStack, i, j); + IdMap> registry = level.registryAccess().registryOrThrow(Registries.ENCHANTMENT).asHolderIdMap(); + + Map enchants = new java.util.HashMap<>(); + for (EnchantmentInstance enchantmentInstance : list) { + enchants.put(CraftEnchantment.minecraftHolderToBukkit(enchantmentInstance.enchantment), enchantmentInstance.level); + } + CraftItemStack item = CraftItemStack.asCraftMirror(itemStack); - playerIn.awardStat(Stats.ENCHANT_ITEM); - if (playerIn instanceof ServerPlayer) { - CriteriaTriggers.ENCHANTED_ITEM.trigger((ServerPlayer) playerIn, itemstack2, i); - } + var hintedEnchantment = CraftEnchantment.minecraftHolderToBukkit(registry.byId(enchantClue[i])); + int hintedEnchantmentLevel = levelClue[i]; + EnchantItemEvent event = new EnchantItemEvent(((Player) ((PlayerEntityBridge) playerIn).bridge$getBukkitEntity()), this.getBukkitView(), ((IWorldPosCallableBridge) this.access).bridge$getLocation().getBlock(), item, this.costs[i], enchants, hintedEnchantment, hintedEnchantmentLevel, i); + Bukkit.getPluginManager().callEvent(event); - this.enchantSlots.setChanged(); - this.enchantmentSeed.set(playerIn.getEnchantmentSeed()); - this.slotsChanged(this.enchantSlots); - p_217003_6_.playSound(null, p_217003_7_, SoundEvents.ENCHANTMENT_TABLE_USE, SoundSource.BLOCKS, 1.0F, p_217003_6_.random.nextFloat() * 0.1F + 0.9F); - } + int levelCost = event.getExpLevelCost(); + if (event.isCancelled() || (levelCost > playerIn.experienceLevel && !playerIn.getAbilities().instabuild) || event.getEnchantsToAdd().isEmpty()) { + return (List) DecorationOps.cancel().invoke(); + } + var newList = new ArrayList(); + for (Map.Entry entry : event.getEnchantsToAdd().entrySet()) { + Holder nms = CraftEnchantment.bukkitToMinecraftHolder(entry.getKey()); + if (nms == null) { + continue; + } - }); - return true; + EnchantmentInstance enchantmentInstance = new EnchantmentInstance(nms, entry.getValue()); + newList.add(enchantmentInstance); } + return newList; } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/GrindstoneContainerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/GrindstoneContainerMixin.java index 4561a83fc..6f1dd959f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/GrindstoneContainerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/GrindstoneContainerMixin.java @@ -38,7 +38,7 @@ public abstract class GrindstoneContainerMixin extends AbstractContainerMenuMixi CraftEventFactory.callPrepareGrindstoneEvent(getBukkitView(), itemStack); } - @Inject(method = "createResult", at = @At(value = "INVOKE", ordinal = 3, target = "Lnet/minecraft/world/inventory/GrindstoneMenu;broadcastChanges()V")) + @Inject(method = "createResult", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/GrindstoneMenu;broadcastChanges()V")) private void arclight$sync(CallbackInfo ci) { sendAllDataToRemote(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/HorseInventoryContainerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/HorseInventoryContainerMixin.java index 605211f1a..0ab5be2ca 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/HorseInventoryContainerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/HorseInventoryContainerMixin.java @@ -26,8 +26,8 @@ public abstract class HorseInventoryContainerMixin extends AbstractContainerMenu Inventory playerInventory; @Inject(method = "", at = @At("RETURN")) - public void arclight$init(int id, Inventory playerInventory, Container horseInventory, AbstractHorse horse, CallbackInfo ci) { - this.playerInventory = playerInventory; + public void arclight$init(int i, Inventory inventory, Container container, AbstractHorse abstractHorse, int j, CallbackInfo ci) { + this.playerInventory = inventory; } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/SmithingTableContainerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/SmithingTableContainerMixin.java index 4f253acf0..b0ff3a94e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/SmithingTableContainerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/inventory/SmithingTableContainerMixin.java @@ -2,13 +2,16 @@ import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.core.util.IWorldPosCallableBridge; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.inventory.SmithingMenu; import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.inventory.CraftInventory; import org.bukkit.craftbukkit.v.inventory.CraftInventorySmithing; import org.bukkit.craftbukkit.v.inventory.CraftInventoryView; +import org.bukkit.craftbukkit.v.inventory.CraftItemStack; +import org.bukkit.event.inventory.PrepareSmithingEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -19,8 +22,10 @@ public abstract class SmithingTableContainerMixin extends ItemCombinerMixin { private CraftInventoryView bukkitEntity; @Redirect(method = "createResult", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/ResultContainer;setItem(ILnet/minecraft/world/item/ItemStack;)V")) - private void arclight$prepareSmithing(ResultContainer craftResultInventory, int index, ItemStack stack) { - CraftEventFactory.callPrepareSmithingEvent(getBukkitView(), stack); + private void arclight$prepareSmithing(ResultContainer craftResultInventory, int index, ItemStack stack) throws Throwable { + PrepareSmithingEvent event = new PrepareSmithingEvent(getBukkitView(), CraftItemStack.asCraftMirror(stack).clone()); + Bukkit.getServer().getPluginManager().callEvent(event); + DecorationOps.callsite().invoke(craftResultInventory, index, CraftItemStack.asNMSCopy(event.getResult())); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorItemMixin.java new file mode 100644 index 000000000..6c33448f0 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorItemMixin.java @@ -0,0 +1,57 @@ +package io.izzel.arclight.common.mixin.core.world.item; + +import io.izzel.arclight.common.mod.server.block.DispenserBlockHooks; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.core.dispenser.BlockSource; +import net.minecraft.core.dispenser.DispenseItemBehavior; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ArmorItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.DispenserBlock; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.block.CraftBlock; +import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; +import org.bukkit.craftbukkit.v.inventory.CraftItemStack; +import org.bukkit.event.block.BlockDispenseArmorEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ArmorItem.class) +public class ArmorItemMixin { + + @Decorate(method = "dispenseArmor", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;setItemSlot(Lnet/minecraft/world/entity/EquipmentSlot;Lnet/minecraft/world/item/ItemStack;)V")) + private static void arclight$dispense(LivingEntity instance, EquipmentSlot equipmentSlot, ItemStack stack, BlockSource blockSource, ItemStack itemStack, @Local(ordinal = -1) ItemStack itemstack1) throws Throwable { + Level world = blockSource.level(); + org.bukkit.block.Block block = CraftBlock.at(world, blockSource.pos()); + CraftItemStack craftItem = CraftItemStack.asCraftMirror(itemstack1); + + BlockDispenseArmorEvent event = new BlockDispenseArmorEvent(block, craftItem.clone(), (CraftLivingEntity) instance.bridge$getBukkitEntity()); + if (!DispenserBlockHooks.isEventFired()) { + Bukkit.getPluginManager().callEvent(event); + } + + if (event.isCancelled()) { + itemStack.grow(1); + DecorationOps.cancel().invoke(false); + return; + } + + if (!event.getItem().equals(craftItem)) { + itemStack.grow(1); + // Chain to handler for new item + ItemStack eventStack = CraftItemStack.asNMSCopy(event.getItem()); + DispenseItemBehavior idispensebehavior = DispenserBlock.DISPENSER_REGISTRY.get(eventStack.getItem()); + if (idispensebehavior != DispenseItemBehavior.NOOP && idispensebehavior != ArmorItem.DISPENSE_ITEM_BEHAVIOR) { + idispensebehavior.dispense(blockSource, eventStack); + DecorationOps.cancel().invoke(true); + return; + } + } + + DecorationOps.callsite().invoke(instance, equipmentSlot, CraftItemStack.asNMSCopy(event.getItem())); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorStandItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorStandItemMixin.java index 720f009ee..806a65945 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorStandItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ArmorStandItemMixin.java @@ -1,6 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.mod.util.DistValidate; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.item.ArmorStandItem; @@ -8,9 +11,7 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ArmorStandItem.class) public class ArmorStandItemMixin { @@ -23,11 +24,12 @@ public class ArmorStandItemMixin { arclight$entity = armorStandEntity; } - @Inject(method = "useOn", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) - public void arclight$entityPlace(UseOnContext context, CallbackInfoReturnable cir) { - if (DistValidate.isValid(context) && CraftEventFactory.callEntityPlaceEvent(context, arclight$entity).isCancelled()) { - cir.setReturnValue(InteractionResult.FAIL); + @Decorate(method = "useOn", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)V")) + public void arclight$entityPlace(UseOnContext context, @Local(ordinal = -1) ArmorStand armorStand) throws Throwable { + if (DistValidate.isValid(context) && CraftEventFactory.callEntityPlaceEvent(context, armorStand).isCancelled()) { + DecorationOps.cancel().invoke(InteractionResult.FAIL); + return; } - arclight$entity = null; + DecorationOps.blackhole().invoke(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BlockItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BlockItemMixin.java index f18dba890..bc5fcbeb5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BlockItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BlockItemMixin.java @@ -1,21 +1,15 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; import io.izzel.arclight.common.mod.util.DistValidate; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.PlaceOnWaterBlockItem; import net.minecraft.world.item.SolidBucketItem; import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.level.block.state.properties.Property; -import net.minecraft.world.phys.shapes.CollisionContext; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlockStates; @@ -23,9 +17,7 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockCanBuildEvent; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -37,7 +29,6 @@ public abstract class BlockItemMixin { // @formatter:off @Shadow protected abstract boolean mustSurvive(); - @Shadow private static > BlockState updateState(BlockState p_219988_0_, Property p_219988_1_, String p_219988_2_) { return null; } // @formatter:on private transient org.bukkit.block.BlockState arclight$state; @@ -73,32 +64,11 @@ public abstract class BlockItemMixin { this.arclight$state = null; } - @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) - private static BlockState getBlockState(BlockState blockState, CompoundTag nbt) { - StateDefinition statecontainer = blockState.getBlock().getStateDefinition(); - for (String s : nbt.getAllKeys()) { - Property iproperty = statecontainer.getProperty(s); - if (iproperty != null) { - String s1 = nbt.get(s).getAsString(); - blockState = updateState(blockState, iproperty, s1); - } - } - return blockState; - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected boolean canPlace(BlockPlaceContext context, BlockState state) { - net.minecraft.world.entity.player.Player playerentity = context.getPlayer(); - CollisionContext iselectioncontext = playerentity == null ? CollisionContext.empty() : CollisionContext.of(playerentity); - boolean original = (!this.mustSurvive() || state.canSurvive(context.getLevel(), context.getClickedPos())) && context.getLevel().isUnobstructed(state, context.getClickedPos(), iselectioncontext); - + @Inject(method = "canPlace", cancellable = true, at = @At("RETURN")) + private void arclight$blockCanBuild(BlockPlaceContext context, BlockState state, CallbackInfoReturnable cir) { Player player = (context.getPlayer() instanceof ServerPlayerEntityBridge) ? ((ServerPlayerEntityBridge) context.getPlayer()).bridge$getBukkitEntity() : null; - BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), original); + BlockCanBuildEvent event = new BlockCanBuildEvent(CraftBlock.at(context.getLevel(), context.getClickedPos()), player, CraftBlockData.fromData(state), cir.getReturnValue()); if (DistValidate.isValid(context)) Bukkit.getPluginManager().callEvent(event); - return event.isBuildable(); + cir.setReturnValue(event.isBuildable()); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BoatItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BoatItemMixin.java index b0290828b..cd7da9fa2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BoatItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BoatItemMixin.java @@ -1,7 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.mod.util.DistValidate; -import net.minecraft.stats.Stats; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; @@ -11,22 +13,18 @@ import net.minecraft.world.item.BoatItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; -import java.util.List; import java.util.function.Predicate; @Mixin(BoatItem.class) @@ -42,65 +40,28 @@ public BoatItemMixin(Properties properties) { super(properties); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public @NotNull InteractionResultHolder use(@NotNull Level worldIn, Player playerIn, @NotNull InteractionHand handIn) { - ItemStack itemstack = playerIn.getItemInHand(handIn); - BlockHitResult result = getPlayerPOVHitResult(worldIn, playerIn, ClipContext.Fluid.ANY); - if (result.getType() == HitResult.Type.MISS) { - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } else { - Vec3 vec3d = playerIn.getViewVector(1.0F); - double d0 = 5.0D; - List list = worldIn.getEntities(playerIn, playerIn.getBoundingBox().expandTowards(vec3d.scale(5.0D)).inflate(1.0D), ENTITY_PREDICATE); - if (!list.isEmpty()) { - Vec3 vec3d1 = playerIn.getEyePosition(1.0F); - - for (Entity entity : list) { - AABB axisalignedbb = entity.getBoundingBox().inflate(entity.getPickRadius()); - if (axisalignedbb.contains(vec3d1)) { - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } - } + @Decorate(method = "use", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/BoatItem;getBoat(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/phys/HitResult;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/entity/vehicle/Boat;")) + private void arclight$interact(Level level, Player player, InteractionHand interactionHand, + @Local(ordinal = 0) ItemStack itemstack, @Local(ordinal = 0) HitResult result) throws Throwable { + if (DistValidate.isValid(level)) { + PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(player, Action.RIGHT_CLICK_BLOCK, ((BlockHitResult) result).getBlockPos(), ((BlockHitResult) result).getDirection(), itemstack, false, interactionHand, result.getLocation()); + if (event.isCancelled()) { + DecorationOps.cancel().invoke(new InteractionResultHolder<>(InteractionResult.PASS, itemstack)); + return; } + } + DecorationOps.blackhole().invoke(); + } - if (result.getType() == HitResult.Type.BLOCK) { - if (DistValidate.isValid(worldIn)) { - PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(playerIn, Action.RIGHT_CLICK_BLOCK, result.getBlockPos(), result.getDirection(), itemstack, false, handIn, result.getLocation()); - - if (event.isCancelled()) { - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } - } - - Boat boatentity = this.getBoat(worldIn, result, itemstack, playerIn); - boatentity.setVariant(this.type); - boatentity.setYRot(playerIn.getYRot()); - if (!worldIn.noCollision(boatentity, boatentity.getBoundingBox().inflate(-0.1D))) { - return new InteractionResultHolder<>(InteractionResult.FAIL, itemstack); - } else { - if (!worldIn.isClientSide) { - if (DistValidate.isValid(worldIn) && CraftEventFactory.callEntityPlaceEvent(worldIn, result.getBlockPos(), result.getDirection(), playerIn, boatentity, handIn).isCancelled()) { - return new InteractionResultHolder<>(InteractionResult.FAIL, itemstack); - } - if (!worldIn.addFreshEntity(boatentity)) { - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } - - if (!playerIn.getAbilities().instabuild) { - itemstack.shrink(1); - } - } - - playerIn.awardStat(Stats.ITEM_USED.get(this)); - return InteractionResultHolder.sidedSuccess(itemstack, worldIn.isClientSide()); - } - } else { - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } + @Decorate(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$entityPlace(Level instance, Entity entity, @NotNull Level worldIn, Player playerIn, @NotNull InteractionHand handIn, + @Local(ordinal = 0) ItemStack itemstack, @Local(ordinal = 0) HitResult result) throws Throwable { + if (DistValidate.isValid(worldIn) && CraftEventFactory.callEntityPlaceEvent(worldIn, ((BlockHitResult) result).getBlockPos(), ((BlockHitResult) result).getDirection(), playerIn, entity, handIn).isCancelled()) { + return (boolean) DecorationOps.cancel().invoke(new InteractionResultHolder<>(InteractionResult.FAIL, itemstack)); + } + if (!(boolean) DecorationOps.callsite().invoke(instance, entity)) { + return (boolean) DecorationOps.cancel().invoke(new InteractionResultHolder<>(InteractionResult.PASS, itemstack)); } + return true; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BowItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BowItemMixin.java deleted file mode 100644 index 190bb5b86..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/BowItemMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.item; - -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.mixin.Decorate; -import io.izzel.arclight.mixin.DecorationOps; -import io.izzel.arclight.mixin.Local; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.projectile.AbstractArrow; -import net.minecraft.world.item.BowItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import org.bukkit.craftbukkit.v.entity.CraftEntity; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; - -import java.util.function.Consumer; - -@Mixin(BowItem.class) -public abstract class BowItemMixin extends ItemMixin { - - // @formatter:off - @Shadow public abstract int getUseDuration(ItemStack stack); - @Shadow public static float getPowerForTime(int charge) { return 0; } - // @formatter:on - - @Decorate(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V")) - private void arclight$entityShootBow( - ItemStack instance, int i, T livingEntity, Consumer consumer, - ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft, - @Local(ordinal = -1) ItemStack projectile, @Local(ordinal = -1) AbstractArrow abstractArrow, - @Local(ordinal = -1) float power, @Local(ordinal = -1) boolean consumeItem, - @Local(allocate = "projectileEntity") Entity projectileEntity - ) throws Throwable { - EntityShootBowEvent event = CraftEventFactory.callEntityShootBowEvent(entityLiving, stack, projectile, abstractArrow, entityLiving.getUsedItemHand(), power, !consumeItem); - if (event.isCancelled()) { - event.getProjectile().remove(); - DecorationOps.cancel().invoke(); - return; - } - consumeItem = !event.shouldConsumeItem(); - projectileEntity = ((CraftEntity) event.getProjectile()).getHandle(); - DecorationOps.blackhole().invoke(consumeItem, projectileEntity); - DecorationOps.callsite().invoke(instance, i, livingEntity, consumer); - } - - @Decorate(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$addProjectile(Level instance, Entity entity, ItemStack itemStack, Level level, LivingEntity livingEntity, int i, - @Local(allocate = "projectileEntity") Entity projectileEntity) throws Throwable { - if (entity == projectileEntity) { - if (!(boolean) DecorationOps.callsite().invoke(instance, entity)) { - if (livingEntity instanceof ServerPlayerEntityBridge) { - ((ServerPlayerEntityBridge) livingEntity).bridge$getBukkitEntity().updateInventory(); - } - return false; - } - return true; - } else { - return false; - } - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ChorusFruitItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ChorusFruitItemMixin.java index bccc193ca..a55e48e33 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ChorusFruitItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ChorusFruitItemMixin.java @@ -1,77 +1,24 @@ package io.izzel.arclight.common.mixin.core.world.item; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.mod.util.DistValidate; +import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.animal.Fox; import net.minecraft.world.item.ChorusFruitItem; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.Vec3; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent; -import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(ChorusFruitItem.class) public class ChorusFruitItemMixin extends ItemMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public @NotNull ItemStack finishUsingItem(@NotNull ItemStack stack, @NotNull Level worldIn, @NotNull LivingEntity entityLiving) { - ItemStack itemstack = super.finishUsingItem(stack, worldIn, entityLiving); - if (!worldIn.isClientSide) { - - for (int i = 0; i < 16; ++i) { - double d3 = entityLiving.getX() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; - double d4 = Mth.clamp(entityLiving.getY() + (double) (entityLiving.getRandom().nextInt(16) - 8), 0.0D, worldIn.getHeight() - 1); - double d5 = entityLiving.getZ() + (entityLiving.getRandom().nextDouble() - 0.5D) * 16.0D; - - if (entityLiving instanceof ServerPlayer && DistValidate.isValid(worldIn)) { - Player player = ((ServerPlayerEntityBridge) entityLiving).bridge$getBukkitEntity(); - PlayerTeleportEvent event = new PlayerTeleportEvent(player, player.getLocation(), new Location(player.getWorld(), d3, d4, d5), PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - break; - } - d3 = event.getTo().getX(); - d4 = event.getTo().getY(); - d5 = event.getTo().getZ(); - } - - if (entityLiving.isPassenger()) { - entityLiving.stopRiding(); - } - Vec3 vec3d = entityLiving.position(); - if (this.bridge$forge$onChorusFruitTeleport(entityLiving, d3, d4, d5)) return itemstack; - if (entityLiving.randomTeleport(d3, d4, d5, true)) { - worldIn.gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of(entityLiving)); - SoundEvent soundevent = entityLiving instanceof Fox ? SoundEvents.FOX_TELEPORT : SoundEvents.CHORUS_FRUIT_TELEPORT; - SoundSource soundSource = entityLiving instanceof Fox ? SoundSource.NEUTRAL : SoundSource.PLAYERS; - worldIn.playSound(null, entityLiving.getX(), entityLiving.getY(), entityLiving.getZ(), soundevent, soundSource); - entityLiving.resetFallDistance(); - break; - } - } - - if (entityLiving instanceof net.minecraft.world.entity.player.Player) { - ((net.minecraft.world.entity.player.Player) entityLiving).getCooldowns().addCooldown((Item) (Object) this, 20); - } + @Inject(method = "finishUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;randomTeleport(DDDZ)Z")) + private void arclight$teleportCause(ItemStack itemStack, Level level, LivingEntity livingEntity, CallbackInfoReturnable cir) { + if (livingEntity instanceof ServerPlayer p) { + ((ServerPlayNetHandlerBridge) p.connection).bridge$pushTeleportCause(PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT); } - - return itemstack; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/CrossbowItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/CrossbowItemMixin.java deleted file mode 100644 index 4587adf20..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/CrossbowItemMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.item; - -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.mod.util.DistValidate; -import io.izzel.arclight.mixin.Eject; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.item.CrossbowItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -@Mixin(CrossbowItem.class) -public class CrossbowItemMixin { - - @Inject(method = "shootProjectile", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V")) - private static void arclight$entityShoot(Level worldIn, LivingEntity shooter, InteractionHand handIn, ItemStack crossbow, ItemStack projectile, float soundPitch, boolean isCreativeMode, float velocity, float inaccuracy, float projectileAngle, CallbackInfo ci, - boolean flag, Projectile proj) { - if (!DistValidate.isValid(worldIn)) { - arclight$capturedBoolean = true; - return; - } - EntityShootBowEvent event = CraftEventFactory.callEntityShootBowEvent(shooter, crossbow, projectile, proj, shooter.getUsedItemHand(), soundPitch, true); - if (event.isCancelled()) { - event.getProjectile().remove(); - ci.cancel(); - } - arclight$capturedBoolean = event.getProjectile() == ((EntityBridge) proj).bridge$getBukkitEntity(); - } - - private static transient boolean arclight$capturedBoolean; - - @Eject(method = "shootProjectile", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private static boolean arclight$addEntity(Level world, Entity entityIn, CallbackInfo ci, Level worldIn, LivingEntity shooter) { - if (arclight$capturedBoolean) { - if (!world.addFreshEntity(entityIn)) { - if (shooter instanceof ServerPlayer) { - ((ServerPlayerEntityBridge) shooter).bridge$getBukkitEntity().updateInventory(); - } - ci.cancel(); - } - } - return true; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/DyeItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/DyeItemMixin.java index 0ee257e21..552de855c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/DyeItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/DyeItemMixin.java @@ -2,8 +2,10 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DyeColor; @@ -16,7 +18,6 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(DyeItem.class) public class DyeItemMixin { @@ -25,15 +26,17 @@ public class DyeItemMixin { @Shadow @Final private DyeColor dyeColor; // @formatter:on - @Eject(method = "interactLivingEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Sheep;setColor(Lnet/minecraft/world/item/DyeColor;)V")) - private void arclight$sheepDyeWool(net.minecraft.world.entity.animal.Sheep sheepEntity, DyeColor color, CallbackInfoReturnable cir, ItemStack stack, Player playerIn, LivingEntity target, InteractionHand hand) { + @Decorate(method = "interactLivingEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/Sheep;setColor(Lnet/minecraft/world/item/DyeColor;)V")) + private void arclight$sheepDyeWool(net.minecraft.world.entity.animal.Sheep sheepEntity, DyeColor color, ItemStack stack, Player playerIn, LivingEntity target, InteractionHand hand) throws Throwable { byte bColor = (byte) this.dyeColor.getId(); SheepDyeWoolEvent event = new SheepDyeWoolEvent((Sheep) ((LivingEntityBridge) target).bridge$getBukkitEntity(), org.bukkit.DyeColor.getByWoolData(bColor), ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity()); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - cir.setReturnValue(false); + DecorationOps.cancel().invoke(InteractionResult.PASS); + return; } else { - sheepEntity.setColor(DyeColor.byId(event.getColor().getWoolData())); + DecorationOps.callsite().invoke(sheepEntity, DyeColor.byId(event.getColor().getWoolData())); } + DecorationOps.blackhole().invoke(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EggItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EggItemMixin.java index 4605ef8a5..7f286c99f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EggItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EggItemMixin.java @@ -1,7 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -11,13 +12,11 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.EggItem; import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EggItem.class) public abstract class EggItemMixin extends Item { @@ -30,14 +29,13 @@ public EggItemMixin(Properties properties) { private void arclight$muteSound(Level world, Player player, double x, double y, double z, SoundEvent soundIn, SoundSource category, float volume, float pitch) { } - @Eject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$updateIfFail(Level world, Entity entityIn, CallbackInfoReturnable> cir, Level worldIn, Player playerIn, @NotNull InteractionHand handIn) { - if (!worldIn.addFreshEntity(entityIn)) { + @Decorate(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$updateIfFail(Level world, Entity entityIn, Level worldIn, Player playerIn, @NotNull InteractionHand handIn) throws Throwable { + if (!(boolean) DecorationOps.callsite().invoke(world, entityIn)) { if (playerIn instanceof ServerPlayerEntityBridge) { ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().updateInventory(); } - cir.setReturnValue(InteractionResultHolder.fail(playerIn.getItemInHand(handIn))); - return false; + return (boolean) DecorationOps.cancel().invoke(InteractionResultHolder.fail(playerIn.getItemInHand(handIn))); } else { worldIn.playSound(null, playerIn.getX(), playerIn.getY(), playerIn.getZ(), SoundEvents.EGG_THROW, SoundSource.PLAYERS, 0.5F, 0.4F / (world.getRandom().nextFloat() * 0.4F + 0.8F)); return true; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderCrystalItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderCrystalItemMixin.java index 5e8728bcb..5a871d27a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderCrystalItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderCrystalItemMixin.java @@ -1,6 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.mod.util.DistValidate; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.boss.enderdragon.EndCrystal; import net.minecraft.world.item.EndCrystalItem; @@ -8,26 +11,16 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EndCrystalItem.class) public class EnderCrystalItemMixin { - @Redirect(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/boss/enderdragon/EndCrystal;setShowBottom(Z)V")) - public void arclight$captureEntity(EndCrystal enderCrystalEntity, boolean showBottom) { - arclight$enderCrystalEntity = enderCrystalEntity; - enderCrystalEntity.setShowBottom(showBottom); - } - - private transient EndCrystal arclight$enderCrystalEntity; - - @Inject(method = "useOn", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - public void arclight$entityPlace(UseOnContext context, CallbackInfoReturnable cir) { - if (DistValidate.isValid(context) && CraftEventFactory.callEntityPlaceEvent(context, arclight$enderCrystalEntity).isCancelled()) { - cir.setReturnValue(InteractionResult.FAIL); + @Decorate(method = "useOn", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private void arclight$entityPlace(UseOnContext context, @Local(ordinal = -1) EndCrystal enderCrystalEntity) throws Throwable { + if (DistValidate.isValid(context) && CraftEventFactory.callEntityPlaceEvent(context, enderCrystalEntity).isCancelled()) { + DecorationOps.cancel().invoke(InteractionResult.FAIL); + return; } - arclight$enderCrystalEntity = null; + DecorationOps.blackhole().invoke(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderEyeItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderEyeItemMixin.java index aeba7391d..118d28f98 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderEyeItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderEyeItemMixin.java @@ -1,26 +1,24 @@ package io.izzel.arclight.common.mixin.core.world.item; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.EnderEyeItem; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EnderEyeItem.class) public class EnderEyeItemMixin { - @Eject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$returnIfFail(Level world, Entity entityIn, CallbackInfoReturnable> cir, Level worldIn, Player playerIn, InteractionHand handIn) { - if (!world.addFreshEntity(entityIn)) { - cir.setReturnValue(new InteractionResultHolder<>(InteractionResult.FAIL, playerIn.getItemInHand(handIn))); - return false; + @Decorate(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$returnIfFail(Level world, Entity entityIn, Level worldIn, Player playerIn, InteractionHand handIn) throws Throwable { + if (!(boolean) DecorationOps.callsite().invoke(world, entityIn)) { + return (boolean) DecorationOps.cancel().invoke(new InteractionResultHolder<>(InteractionResult.FAIL, playerIn.getItemInHand(handIn))); } else { return true; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderPearlItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderPearlItemMixin.java index 0082d66da..35ff12ace 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderPearlItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/EnderPearlItemMixin.java @@ -47,9 +47,7 @@ public EnderPearlItemMixin(Properties properties) { playerIn.getCooldowns().addCooldown(this, 20); playerIn.awardStat(Stats.ITEM_USED.get(this)); - if (!playerIn.getAbilities().instabuild) { - itemstack.shrink(1); - } + itemstack.consume(1, playerIn); return InteractionResultHolder.sidedSuccess(itemstack, worldIn.isClientSide()); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FishingRodItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FishingRodItemMixin.java index 253e5f641..8c16713a6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FishingRodItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FishingRodItemMixin.java @@ -1,78 +1,32 @@ package io.izzel.arclight.common.mixin.core.world.item; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.mod.util.DistValidate; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.stats.Stats; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.item.FishingRodItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; -import net.minecraft.world.level.gameevent.GameEvent; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftEquipmentSlot; -import org.bukkit.entity.FishHook; import org.bukkit.event.player.PlayerFishEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; @Mixin(FishingRodItem.class) public class FishingRodItemMixin extends ItemMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public InteractionResultHolder use(Level worldIn, Player playerIn, InteractionHand handIn) { - ItemStack itemstack = playerIn.getItemInHand(handIn); - if (playerIn.fishing != null) { - if (!worldIn.isClientSide) { - int i = playerIn.fishing.retrieve(itemstack); - ItemStack original = itemstack.copy(); - itemstack.hurtAndBreak(i, playerIn, (player) -> { - player.broadcastBreakEvent(handIn); - }); - if (itemstack.isEmpty()) { - this.bridge$forge$onPlayerDestroyItem(playerIn, original, handIn); - } - } + @Decorate(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$fishEvent(Level instance, Entity entity, Level level, Player player, InteractionHand interactionHand) throws Throwable { + var itemstack = player.getItemInHand(interactionHand); + PlayerFishEvent playerFishEvent = new PlayerFishEvent((org.bukkit.entity.Player) player.bridge$getBukkitEntity(), null, (org.bukkit.entity.FishHook) entity.bridge$getBukkitEntity(), CraftEquipmentSlot.getHand(interactionHand), PlayerFishEvent.State.FISHING); + Bukkit.getPluginManager().callEvent(playerFishEvent); - playerIn.swing(handIn); - worldIn.playSound(null, playerIn.getX(), playerIn.getY(), playerIn.getZ(), SoundEvents.FISHING_BOBBER_RETRIEVE, SoundSource.NEUTRAL, 1.0F, 0.4F / (worldIn.getRandom().nextFloat() * 0.4F + 0.8F)); - playerIn.gameEvent(GameEvent.ITEM_INTERACT_FINISH); - } else { - if (!worldIn.isClientSide) { - int k = EnchantmentHelper.getFishingSpeedBonus(itemstack); - int j = EnchantmentHelper.getFishingLuckBonus(itemstack); - - FishingHook hook = new FishingHook(playerIn, worldIn, j, k); - if (DistValidate.isValid(worldIn)) { - PlayerFishEvent playerFishEvent = new PlayerFishEvent(((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity(), null, (FishHook) ((EntityBridge) hook).bridge$getBukkitEntity(), CraftEquipmentSlot.getHand(handIn), PlayerFishEvent.State.FISHING); - Bukkit.getPluginManager().callEvent(playerFishEvent); - - if (playerFishEvent.isCancelled()) { - playerIn.fishing = null; - return new InteractionResultHolder<>(InteractionResult.PASS, itemstack); - } - } - worldIn.playSound(null, playerIn.getX(), playerIn.getY(), playerIn.getZ(), SoundEvents.FISHING_BOBBER_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (worldIn.getRandom().nextFloat() * 0.4F + 0.8F)); - worldIn.addFreshEntity(new FishingHook(playerIn, worldIn, j, k)); - } - - // playerIn.swingArm(handIn); - playerIn.awardStat(Stats.ITEM_USED.get((Item) (Object) this)); - playerIn.gameEvent(GameEvent.ITEM_INTERACT_START); + if (playerFishEvent.isCancelled()) { + player.fishing = null; + return (boolean) DecorationOps.cancel().invoke(InteractionResultHolder.pass(itemstack)); } - - return InteractionResultHolder.sidedSuccess(itemstack, worldIn.isClientSide()); + return (boolean) DecorationOps.callsite().invoke(instance, entity); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FlintAndSteelItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FlintAndSteelItemMixin.java index 7a27947cf..d6414ba0a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FlintAndSteelItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/FlintAndSteelItemMixin.java @@ -3,6 +3,7 @@ import io.izzel.arclight.common.mod.util.DistValidate; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.FlintAndSteelItem; import net.minecraft.world.item.context.UseOnContext; @@ -25,9 +26,7 @@ public class FlintAndSteelItemMixin { BlockPos blockpos = context.getClickedPos(); BlockPos blockpos1 = blockpos.relative(context.getClickedFace()); if (CraftEventFactory.callBlockIgniteEvent(world, blockpos1, BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL, playerentity).isCancelled()) { - context.getItemInHand().hurtAndBreak(1, playerentity, (entity) -> { - entity.broadcastBreakEvent(context.getHand()); - }); + context.getItemInHand().hurtAndBreak(1, playerentity, LivingEntity.getSlotForHand(context.getHand())); cir.setReturnValue(InteractionResult.PASS); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ItemStackMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ItemStackMixin.java index 41dbd5ffd..2126c0d29 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ItemStackMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ItemStackMixin.java @@ -2,10 +2,14 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.PatchedDataComponentMap; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -13,12 +17,12 @@ import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.bukkit.event.player.PlayerItemDamageEvent; -import org.objectweb.asm.Opcodes; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.function.Consumer; @@ -28,6 +32,8 @@ public abstract class ItemStackMixin implements ItemStackBridge { // @formatter:off @Shadow private int count; + @Shadow @Final PatchedDataComponentMap components; + @Shadow @Deprecated @Nullable private Item item; // @formatter:on private static final Logger LOG = LogManager.getLogger("Arclight"); @@ -38,32 +44,43 @@ public void convertStack(int version) { } } - @Override - public void bridge$convertStack(int version) { - this.convertStack(version); - } - - @ModifyVariable(method = "hurt", index = 1, at = @At(value = "JUMP", opcode = Opcodes.IFGT, ordinal = 0)) - private int arclight$itemDamage(int i, int amount, RandomSource rand, ServerPlayer damager) { + @Decorate(method = "hurtAndBreak(ILnet/minecraft/server/level/ServerLevel;Lnet/minecraft/server/level/ServerPlayer;Ljava/util/function/Consumer;)V", + require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;processDurabilityChange(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;I)I")) + private int arclight$itemDamage(ServerLevel serverLevel, ItemStack itemStack, int i, @Local(ordinal = 0) ServerPlayer damager) throws Throwable { + int result = (int) DecorationOps.callsite().invoke(serverLevel, itemStack, i); if (damager != null) { - PlayerItemDamageEvent event = new PlayerItemDamageEvent(((ServerPlayerEntityBridge) damager).bridge$getBukkitEntity(), CraftItemStack.asCraftMirror((ItemStack) (Object) this), i); + PlayerItemDamageEvent event = new PlayerItemDamageEvent(((ServerPlayerEntityBridge) damager).bridge$getBukkitEntity(), CraftItemStack.asCraftMirror((ItemStack) (Object) this), result); event.getPlayer().getServer().getPluginManager().callEvent(event); - if (i != event.getDamage() || event.isCancelled()) { + if (result != event.getDamage() || event.isCancelled()) { event.getPlayer().updateInventory(); } if (event.isCancelled()) { - return -1; + return (int) DecorationOps.cancel().invoke(); } - return event.getDamage(); + result = event.getDamage(); } - return i; + return result; } - @Inject(method = "hurtAndBreak", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) - private void arclight$itemBreak(int amount, T entityIn, Consumer onBroken, CallbackInfo ci) { - if (this.count == 1 && entityIn instanceof Player) { - CraftEventFactory.callPlayerItemBreakEvent(((Player) entityIn), (ItemStack) (Object) this); + @Inject(method = "hurtAndBreak(ILnet/minecraft/server/level/ServerLevel;Lnet/minecraft/server/level/ServerPlayer;Ljava/util/function/Consumer;)V", require = 0, at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V")) + private void arclight$itemBreak(int amount, ServerLevel level, @Nullable ServerPlayer serverPlayer, Consumer onBroken, CallbackInfo ci) { + if (this.count == 1 && serverPlayer != null) { + CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, (ItemStack) (Object) this); } } + + public void restorePatch(DataComponentPatch datacomponentpatch) { + this.components.restorePatch(datacomponentpatch); + } + + @Override + public void bridge$restorePatch(DataComponentPatch datacomponentpatch) { + this.restorePatch(datacomponentpatch); + } + + @Deprecated + public void setItem(@Nullable Item item) { + this.item = item; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/LeadItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/LeadItemMixin.java index a0e2ebcf3..a17b5f9ff 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/LeadItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/LeadItemMixin.java @@ -1,29 +1,31 @@ package io.izzel.arclight.common.mixin.core.world.item; -import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.item.LeadItem; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; import org.bukkit.Bukkit; -import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.v.CraftEquipmentSlot; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.entity.Hanging; -import org.bukkit.entity.Player; import org.bukkit.event.hanging.HangingPlaceEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + @Mixin(LeadItem.class) public class LeadItemMixin { @@ -39,39 +41,27 @@ public class LeadItemMixin { arclight$hand = p_42834_.getHand(); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public static InteractionResult bindPlayerMobs(net.minecraft.world.entity.player.Player player, Level worldIn, BlockPos fence) { - LeashFenceKnotEntity leashknotentity = null; - boolean flag = false; - double d0 = 7.0D; - int i = fence.getX(); - int j = fence.getY(); - int k = fence.getZ(); - - for (Mob mobentity : worldIn.getEntitiesOfClass(Mob.class, new AABB((double) i - 7.0D, (double) j - 7.0D, (double) k - 7.0D, (double) i + 7.0D, (double) j + 7.0D, (double) k + 7.0D))) { - if (mobentity.getLeashHolder() == player) { - if (leashknotentity == null) { - leashknotentity = LeashFenceKnotEntity.getOrCreateKnot(worldIn, fence); - HangingPlaceEvent event = new HangingPlaceEvent((Hanging) leashknotentity.bridge$getBukkitEntity(), player != null ? (Player) ((PlayerEntityBridge) player).bridge$getBukkitEntity() : null, CraftBlock.at(worldIn, fence), BlockFace.SELF, CraftEquipmentSlot.getHand(arclight$hand)); - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - leashknotentity.discard(); - return InteractionResult.PASS; - } - } - if (CraftEventFactory.callPlayerLeashEntityEvent(mobentity, leashknotentity, player, arclight$hand).isCancelled()) { - continue; - } - mobentity.setLeashedTo(leashknotentity, true); - flag = true; + @SuppressWarnings("unchecked") + @Decorate(method = "bindPlayerMobs", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/LeadItem;leashableInArea(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Ljava/util/function/Predicate;)Ljava/util/List;")) + private static List arclight$leashEvent(Level level, BlockPos blockPos, Predicate predicate, net.minecraft.world.entity.player.Player player) throws Throwable { + var leashableList = (List) DecorationOps.callsite().invoke(level, blockPos, predicate); + var leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, blockPos); + var hand = CraftEquipmentSlot.getHand(arclight$hand); + var event = new HangingPlaceEvent((org.bukkit.entity.Hanging) leashFenceKnotEntity.bridge$getBukkitEntity(), player != null ? (org.bukkit.entity.Player) player.bridge$getBukkitEntity() : null, CraftBlock.at(level, blockPos), org.bukkit.block.BlockFace.SELF, hand); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + leashFenceKnotEntity.discard(); + return (List) DecorationOps.cancel().invoke(InteractionResult.PASS); + } + var newList = leashableList.stream().filter(it -> { + if (it instanceof Entity leashed) { + return !CraftEventFactory.callPlayerLeashEntityEvent(leashed, leashFenceKnotEntity, player, arclight$hand).isCancelled(); } + return true; + }).collect(Collectors.toCollection(ArrayList::new)); + if (newList.isEmpty()) { + leashFenceKnotEntity.discard(); } - - return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + return newList; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MapItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MapItemMixin.java deleted file mode 100644 index e444ffb5f..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MapItemMixin.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.item; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.MapItem; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import javax.annotation.Nullable; - -@Mixin(MapItem.class) -public abstract class MapItemMixin { - - /** - * @author IzzelAliz - * @reason - */ - @Nullable - @Overwrite - public static Integer getMapId(ItemStack stack) { - CompoundTag compoundnbt = stack.getTag(); - return compoundnbt != null && compoundnbt.contains("map", 99) ? compoundnbt.getInt("map") : -1; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MerchantOfferMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MerchantOfferMixin.java index 9d360d54c..7bce29102 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MerchantOfferMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MerchantOfferMixin.java @@ -4,19 +4,19 @@ import io.izzel.arclight.common.mod.mixins.annotation.CreateConstructor; import io.izzel.arclight.common.mod.mixins.annotation.ShadowConstructor; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; import org.bukkit.craftbukkit.v.inventory.CraftMerchantRecipe; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; @Mixin(MerchantOffer.class) -public class MerchantOfferMixin implements MerchantOfferBridge { +public abstract class MerchantOfferMixin implements MerchantOfferBridge { // @formatter:off - @Shadow public ItemStack baseCostA; + @Shadow public ItemCost baseCostA; @Shadow private int demand; // @formatter:on @@ -27,13 +27,13 @@ public CraftMerchantRecipe asBukkit() { } @ShadowConstructor - public void arclight$constructor(ItemStack buyingStackFirstIn, ItemStack buyingStackSecondIn, ItemStack sellingStackIn, int usesIn, int maxUsesIn, int givenEXPIn, float priceMultiplierIn, int demand) { + public void arclight$constructor(ItemCost itemCost, Optional optional, ItemStack itemStack, int i, int j, boolean bl, int k, int l, float f, int m) { throw new RuntimeException(); } @CreateConstructor - public void arclight$constructor(ItemStack buyingStackFirstIn, ItemStack buyingStackSecondIn, ItemStack sellingStackIn, int usesIn, int maxUsesIn, int givenEXPIn, float priceMultiplierIn, int demand, CraftMerchantRecipe bukkit) { - arclight$constructor(buyingStackFirstIn, buyingStackSecondIn, sellingStackIn, usesIn, maxUsesIn, givenEXPIn, priceMultiplierIn, demand); + public void arclight$constructor(ItemCost itemCost, Optional optional, ItemStack itemStack, int i, int j, boolean bl, int k, int l, float f, int m, CraftMerchantRecipe bukkit) { + arclight$constructor(itemCost, optional, itemStack, i, j, bl, k, l, f, m); this.bukkitHandle = bukkit; } @@ -41,11 +41,4 @@ public CraftMerchantRecipe asBukkit() { public CraftMerchantRecipe bridge$asBukkit() { return asBukkit(); } - - @Inject(method = "getCostA", cancellable = true, at = @At("HEAD")) - private void arclight$fix(CallbackInfoReturnable cir) { - if (this.baseCostA.getCount() <= 0) { - cir.setReturnValue(ItemStack.EMPTY); - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MinecartItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MinecartItemMixin.java index 76d5d2450..10da33f97 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MinecartItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/MinecartItemMixin.java @@ -1,7 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.mod.util.DistValidate; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; @@ -10,19 +11,16 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(MinecartItem.class) public class MinecartItemMixin { - @Eject(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$entityPlace(ServerLevel world, Entity entityIn, CallbackInfoReturnable cir, UseOnContext context) { + @Decorate(method = "useOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$entityPlace(ServerLevel world, Entity entityIn, UseOnContext context) throws Throwable { if (DistValidate.isValid(world) && CraftEventFactory.callEntityPlaceEvent(context, entityIn).isCancelled()) { - cir.setReturnValue(InteractionResult.FAIL); - return false; - } else if (!world.addFreshEntity(entityIn)) { - cir.setReturnValue(InteractionResult.PASS); - return false; + return (boolean) DecorationOps.cancel().invoke(InteractionResult.FAIL); + } else if (!(boolean) DecorationOps.callsite().invoke(world, entityIn)) { + return (boolean) DecorationOps.cancel().invoke(InteractionResult.PASS); } else { return true; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/PotionItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/PotionItemMixin.java index ddebcd186..6333b6843 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/PotionItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/PotionItemMixin.java @@ -1,21 +1,21 @@ package io.izzel.arclight.common.mixin.core.world.item; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.PotionItem; -import net.minecraft.world.level.Level; import org.bukkit.event.entity.EntityPotionEffectEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(PotionItem.class) public class PotionItemMixin { - @Inject(method = "finishUsingItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - public void arclight$drinkPotion(ItemStack stack, Level worldIn, LivingEntity entityLiving, CallbackInfoReturnable cir) { - ((LivingEntityBridge) entityLiving).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.POTION_DRINK); + @Decorate(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) + private static boolean arclight$drinkPotion(LivingEntity instance, MobEffectInstance mobEffectInstance) throws Throwable { + ((LivingEntityBridge) instance).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.POTION_DRINK); + return (boolean) DecorationOps.callsite().invoke(instance, mobEffectInstance); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ProjectileWeaponItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ProjectileWeaponItemMixin.java new file mode 100644 index 000000000..cdba953e8 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/ProjectileWeaponItemMixin.java @@ -0,0 +1,41 @@ +package io.izzel.arclight.common.mixin.core.world.item; + +import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.ProjectileWeaponItem; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; + +@Mixin(ProjectileWeaponItem.class) +public class ProjectileWeaponItemMixin { + + @Decorate(method = "shoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$shootBow(ServerLevel instance, Entity entity, ServerLevel serverLevel, LivingEntity livingEntity, InteractionHand interactionHand, ItemStack itemStack, + List list, float f, @Local(ordinal = -1) ItemStack itemstack1) throws Throwable { + var event = CraftEventFactory.callEntityShootBowEvent(livingEntity, itemStack, itemstack1, entity, interactionHand, f, true); + if (event.isCancelled()) { + event.getProjectile().remove(); + return (boolean) DecorationOps.cancel().invoke(); + } + + if (event.getProjectile() == entity.bridge$getBukkitEntity()) { + if (!(boolean) DecorationOps.callsite().invoke(instance, entity)) { + if (livingEntity instanceof net.minecraft.server.level.ServerPlayer) { + ((ServerPlayerEntityBridge) livingEntity).bridge$getBukkitEntity().updateInventory(); + } + return false; + } + } + return true; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/SnowballItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/SnowballItemMixin.java index 865b2ca50..a8dd7f74e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/SnowballItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/SnowballItemMixin.java @@ -37,9 +37,7 @@ public SnowballItemMixin(Properties properties) { snowballentity.setItem(itemstack); snowballentity.shootFromRotation(playerIn, playerIn.getXRot(), playerIn.getYRot(), 0.0F, 1.5F, 1.0F); if (worldIn.addFreshEntity(snowballentity)) { - if (!playerIn.getAbilities().instabuild) { - itemstack.shrink(1); - } + itemstack.consume(1, playerIn); worldIn.playSound(null, playerIn.getX(), playerIn.getY(), playerIn.getZ(), SoundEvents.SNOWBALL_THROW, SoundSource.NEUTRAL, 0.5F, 0.4F / (worldIn.getRandom().nextFloat() * 0.4F + 0.8F)); } else if (playerIn instanceof ServerPlayer) { ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().updateInventory(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/TridentItemMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/TridentItemMixin.java index 33af8aaf5..1ab0e2bc1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/TridentItemMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/TridentItemMixin.java @@ -3,43 +3,41 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.entity.projectile.TridentEntityBridge; import io.izzel.arclight.common.mod.util.DistValidate; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TridentItem; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.Level; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.function.Consumer; @Mixin(TridentItem.class) public class TridentItemMixin { - @Redirect(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V")) - public void arclight$muteDamage(ItemStack stack, int amount, LivingEntity entityIn, Consumer onBroken) { - int j = EnchantmentHelper.getRiptide(stack); - if (j != 0) stack.hurtAndBreak(amount, entityIn, onBroken); + @Decorate(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V")) + private void arclight$muteDamage(ItemStack instance, int i, LivingEntity livingEntity, EquipmentSlot equipmentSlot, @Local(ordinal = -1) float f) throws Throwable { + if (f != 0) { + DecorationOps.callsite().invoke(instance, i, livingEntity, equipmentSlot); + } } - @Eject(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - public boolean arclight$addEntity(Level world, Entity entityIn, CallbackInfo ci, ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) { - if (!world.addFreshEntity(entityIn)) { + @Decorate(method = "releaseUsing", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + public boolean arclight$addEntity(Level world, Entity entityIn, ItemStack stack, Level worldIn, LivingEntity entityLiving, int timeLeft) throws Throwable { + if (!(boolean) DecorationOps.callsite().invoke(world, entityIn)) { if (entityLiving instanceof ServerPlayer) { ((ServerPlayerEntityBridge) entityLiving).bridge$getBukkitEntity().updateInventory(); } - ci.cancel(); - return false; + return (boolean) DecorationOps.cancel().invoke(); } - stack.hurtAndBreak(1, entityLiving, (entity) -> - entity.broadcastBreakEvent(entityLiving.getUsedItemHand())); + stack.hurtAndBreak(1, entityLiving, LivingEntity.getSlotForHand(entityLiving.getUsedItemHand())); ((TridentEntityBridge) entityIn).bridge$setThrownStack(stack.copy()); return true; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/IngredientMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/IngredientMixin.java index 6c67d9bec..f45f3837f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/IngredientMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/IngredientMixin.java @@ -1,11 +1,14 @@ package io.izzel.arclight.common.mixin.core.world.item.crafting; import io.izzel.arclight.common.bridge.core.world.item.crafting.IngredientBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.Ingredient; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; import javax.annotation.Nullable; @@ -19,34 +22,15 @@ public abstract class IngredientMixin implements IngredientBridge { public boolean exact; - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean test(@Nullable ItemStack itemstack) { - if (itemstack == null) { - return false; - } else if (this.isEmpty()) { - return itemstack.isEmpty(); - } else { - ItemStack[] items = this.getItems(); - for (ItemStack stack : items) { - // CraftBukkit start - if (exact) { - if (ItemStack.isSameItemSameTags(itemstack, stack)) { - return true; - } - continue; - } - // CraftBukkit end - if (stack.is(itemstack.getItem())) { - return true; - } + @Decorate(method = "test(Lnet/minecraft/world/item/ItemStack;)Z", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;is(Lnet/minecraft/world/item/Item;)Z")) + private boolean arclight$exactMatch(ItemStack instance, Item arg, @Nullable ItemStack itemstack) throws Throwable { + if (exact) { + if (ItemStack.isSameItemSameComponents(itemstack, instance)) { + return (boolean) DecorationOps.cancel().invoke(true); } - return false; } + return (boolean) DecorationOps.callsite().invoke(instance, arg); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/RecipeManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/RecipeManagerMixin.java index e72df5ea5..6bc9d8aa8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/RecipeManagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/crafting/RecipeManagerMixin.java @@ -1,21 +1,18 @@ package io.izzel.arclight.common.mixin.core.world.item.crafting; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeManagerBridge; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.util.GsonHelper; import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeInput; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; @@ -24,8 +21,14 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import javax.annotation.Nullable; +import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -33,56 +36,23 @@ public abstract class RecipeManagerMixin implements RecipeManagerBridge { // @formatter:off - @Shadow public Map, Map>> recipes; @Shadow private boolean hasErrors; @Shadow @Final private static Logger LOGGER; @Shadow private Map> byName; - @Shadow protected static RecipeHolder fromJson(ResourceLocation p_44046_, JsonObject p_44047_) { return null; } - @Shadow protected abstract > Map> byType(RecipeType p_44055_); + @Shadow public Multimap, RecipeHolder> byType; + @Shadow protected abstract > Collection> byType(RecipeType recipeType); // @formatter:on - @Override - public RecipeHolder bridge$platform$loadRecipe(ResourceLocation key, JsonElement element) { - return fromJson(key, GsonHelper.convertToJsonObject(element, "top element")); + @Inject(method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", at = @At("RETURN")) + private void arclight$makeMutable(Map map, ResourceManager resourceManager, ProfilerFiller profilerFiller, CallbackInfo ci) { + this.byName = new HashMap<>(this.byName); + this.byType = LinkedHashMultimap.create(this.byType); } - /** - * @author IzzelAluz - * @reason - */ - @Overwrite - @SuppressWarnings("unchecked") - protected void apply(Map objectIn, ResourceManager resourceManagerIn, ProfilerFiller profilerIn) { - this.hasErrors = false; - Map, Object2ObjectLinkedOpenHashMap>> map = Maps.newHashMap(); - - for (RecipeType type : BuiltInRegistries.RECIPE_TYPE) { - map.put(type, new Object2ObjectLinkedOpenHashMap<>()); - } - - ImmutableMap.Builder> builder = ImmutableMap.builder(); - for (Map.Entry entry : objectIn.entrySet()) { - ResourceLocation resourcelocation = entry.getKey(); - if (resourcelocation.getPath().startsWith("_")) - continue; //Forge: filter anything beginning with "_" as it's used for metadata. - - try { - RecipeHolder irecipe = this.bridge$platform$loadRecipe(resourcelocation, entry.getValue()); - if (irecipe == null) { - LOGGER.debug("Skipping loading recipe {} as it's conditions were not met", resourcelocation); - continue; - } - map.computeIfAbsent(irecipe.value().getType(), (recipeType) -> new Object2ObjectLinkedOpenHashMap<>()) - .putAndMoveToFirst(resourcelocation, irecipe); - builder.put(resourcelocation, irecipe); - } catch (IllegalArgumentException | JsonParseException jsonparseexception) { - LOGGER.error("Parsing error loading recipe {}", resourcelocation, jsonparseexception); - } - } - - this.recipes = (Map) map; - this.byName = Maps.newHashMap(builder.build()); - LOGGER.info("Loaded {} recipes", map.size()); + @Inject(method = "replaceRecipes", at = @At("RETURN")) + private void arclight$replaceMutable(Iterable> iterable, CallbackInfo ci) { + this.byName = new HashMap<>(this.byName); + this.byType = LinkedHashMultimap.create(this.byType); } /** @@ -90,36 +60,29 @@ protected void apply(Map objectIn, ResourceManage * @reason */ @Overwrite - public > Optional> getRecipeFor(RecipeType recipeTypeIn, C inventoryIn, Level worldIn) { - Optional> optional = this.byType(recipeTypeIn).values().stream().filter((recipe) -> { - return recipe.value().matches(inventoryIn, worldIn); - }).findFirst(); - ((IInventoryBridge) inventoryIn).setCurrentRecipe(optional.orElse(null)); - return optional; + public > Optional> getRecipeFor(RecipeType recipes, I i0, Level world, @Nullable RecipeHolder recipeholder) { + // CraftBukkit start + List> list = this.byType(recipes).stream().filter((recipeholder1) -> { + return recipeholder1.value().matches(i0, world); + }).toList(); + Optional> recipe = (list.isEmpty() || i0.isEmpty()) ? Optional.empty() : (recipeholder != null && recipeholder.value().matches(i0, world) ? Optional.of(recipeholder) : Optional.of(list.getLast())); // CraftBukkit - SPIGOT-4638: last recipe gets priority + return recipe; + // CraftBukkit end } public void addRecipe(RecipeHolder recipe) { - if (this.recipes instanceof ImmutableMap) { - this.recipes = new HashMap<>(recipes); + if (this.byType instanceof ImmutableMultimap, RecipeHolder>) { + this.byType = LinkedHashMultimap.create(this.byType); } if (this.byName instanceof ImmutableMap) { this.byName = new HashMap<>(byName); } - Map> original = this.recipes.get(recipe.value().getType()); - Object2ObjectLinkedOpenHashMap> map; - if (!(original instanceof Object2ObjectLinkedOpenHashMap)) { - Object2ObjectLinkedOpenHashMap> hashMap = new Object2ObjectLinkedOpenHashMap<>(); - hashMap.putAll(original); - this.recipes.put(recipe.value().getType(), hashMap); - map = hashMap; - } else { - map = ((Object2ObjectLinkedOpenHashMap>) original); - } + Collection> map = this.byType.get(recipe.value().getType()); - if (this.byName.containsKey(recipe.id()) || map.containsKey(recipe.id())) { + if (this.byName.containsKey(recipe.id())) { throw new IllegalStateException("Duplicate recipe ignored with ID " + recipe.id()); } else { - map.putAndMoveToFirst(recipe.id(), recipe); + map.add(recipe); this.byName.put(recipe.id(), recipe); } } @@ -130,18 +93,13 @@ public void addRecipe(RecipeHolder recipe) { } public boolean removeRecipe(ResourceLocation mcKey) { - for (var recipes : recipes.values()) { - recipes.remove(mcKey); - } + byType.values().removeIf(recipe -> recipe.id().equals(mcKey)); return byName.remove(mcKey) != null; } public void clearRecipes() { - this.recipes = new HashMap<>(); - for (RecipeType type : BuiltInRegistries.RECIPE_TYPE) { - this.recipes.put(type, new Object2ObjectLinkedOpenHashMap<>()); - } - this.byName = new HashMap<>(); + this.byType = LinkedHashMultimap.create(); + this.byName = Maps.newHashMap(); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/DamageEnchantmentMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/DamageEnchantmentMixin.java deleted file mode 100644 index 987ecfd43..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/DamageEnchantmentMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.item.enchantment; - -import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.enchantment.DamageEnchantment; -import org.bukkit.event.entity.EntityPotionEffectEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(DamageEnchantment.class) -public class DamageEnchantmentMixin { - - @Inject(method = "doPostAttack", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) - public void arclight$entityDamage(LivingEntity user, Entity target, int level, CallbackInfo ci) { - ((LivingEntityBridge) target).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK); - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/FrostWalkerEnchantmentMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/FrostWalkerEnchantmentMixin.java deleted file mode 100644 index d9ecead7b..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/FrostWalkerEnchantmentMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.item.enchantment; - -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.enchantment.FrostWalkerEnchantment; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.FrostedIceBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.shapes.CollisionContext; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -@Mixin(FrostWalkerEnchantment.class) -public class FrostWalkerEnchantmentMixin { - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public static void onEntityMoved(LivingEntity living, Level worldIn, BlockPos pos, int level) { - if (living.onGround()) { - BlockState blockstate = Blocks.FROSTED_ICE.defaultBlockState(); - int f = Math.min(16, 2 + level); - BlockPos.MutableBlockPos blockpos$mutable = new BlockPos.MutableBlockPos(); - - for (BlockPos blockpos : BlockPos.betweenClosed(pos.offset(-f, -1, -f), pos.offset(f, -1, f))) { - if (blockpos.closerToCenterThan(living.position(), f)) { - blockpos$mutable.set(blockpos.getX(), blockpos.getY() + 1, blockpos.getZ()); - BlockState blockstate1 = worldIn.getBlockState(blockpos$mutable); - if (blockstate1.isAir()) { - BlockState blockstate2 = worldIn.getBlockState(blockpos); - if (blockstate2 == FrostedIceBlock.meltsInto() && blockstate.canSurvive(worldIn, blockpos) && worldIn.isUnobstructed(blockstate, blockpos, CollisionContext.empty()) && !((WorldBridge) worldIn).bridge$forge$onBlockPlace(blockpos, living, Direction.UP)) { - if (CraftEventFactory.handleBlockFormEvent(worldIn, blockpos, blockstate, living)) { - worldIn.scheduleTick(blockpos, Blocks.FROSTED_ICE, Mth.nextInt(living.getRandom(), 60, 120)); - } - } - } - } - } - } - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ApplyMobEffectMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ApplyMobEffectMixin.java new file mode 100644 index 000000000..a80867dba --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ApplyMobEffectMixin.java @@ -0,0 +1,22 @@ +package io.izzel.arclight.common.mixin.core.world.item.enchantment.effects; + +import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.enchantment.EnchantedItemInUse; +import net.minecraft.world.item.enchantment.effects.ApplyMobEffect; +import net.minecraft.world.phys.Vec3; +import org.bukkit.event.entity.EntityPotionEffectEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ApplyMobEffect.class) +public class ApplyMobEffectMixin { + + @Inject(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;addEffect(Lnet/minecraft/world/effect/MobEffectInstance;)Z")) + private void arclight$cause(ServerLevel serverLevel, int i, EnchantedItemInUse enchantedItemInUse, Entity entity, Vec3 vec3, CallbackInfo ci) { + ((LivingEntityBridge) entity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.ATTACK); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/IgniteMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/IgniteMixin.java new file mode 100644 index 000000000..a7748dae9 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/IgniteMixin.java @@ -0,0 +1,39 @@ +package io.izzel.arclight.common.mixin.core.world.item.enchantment.effects; + +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.enchantment.EnchantedItemInUse; +import net.minecraft.world.item.enchantment.LevelBasedValue; +import net.minecraft.world.item.enchantment.effects.Ignite; +import org.bukkit.Bukkit; +import org.bukkit.event.entity.EntityCombustByEntityEvent; +import org.bukkit.event.entity.EntityCombustEvent; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Ignite.class) +public class IgniteMixin { + + @Shadow @Final private LevelBasedValue duration; + + @Decorate(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$combustEvent(Entity instance, float f, ServerLevel serverLevel, int i, EnchantedItemInUse enchantedItemInUse) throws Throwable { + EntityCombustEvent entityCombustEvent; + if (enchantedItemInUse.owner() != null) { + entityCombustEvent = new EntityCombustByEntityEvent(enchantedItemInUse.owner().bridge$getBukkitEntity(), instance.bridge$getBukkitEntity(), this.duration.calculate(i)); + } else { + entityCombustEvent = new EntityCombustEvent(instance.bridge$getBukkitEntity(), this.duration.calculate(i)); + } + + Bukkit.getPluginManager().callEvent(entityCombustEvent); + if (entityCombustEvent.isCancelled()) { + return; + } + + DecorationOps.callsite().invoke(instance, f); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceBlockMixin.java new file mode 100644 index 000000000..b5c65393e --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceBlockMixin.java @@ -0,0 +1,21 @@ +package io.izzel.arclight.common.mixin.core.world.item.enchantment.effects; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.enchantment.EnchantedItemInUse; +import net.minecraft.world.item.enchantment.effects.ReplaceBlock; +import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ReplaceBlock.class) +public class ReplaceBlockMixin { + + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) + private boolean arclight$changeBlock(ServerLevel instance, BlockPos pos, BlockState blockState, ServerLevel serverLevel, int i, EnchantedItemInUse enchantedItemInUse, Entity entity) { + return CraftEventFactory.handleBlockFormEvent(instance, pos, blockState, entity); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceDiskMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceDiskMixin.java new file mode 100644 index 000000000..113a95670 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/item/enchantment/effects/ReplaceDiskMixin.java @@ -0,0 +1,21 @@ +package io.izzel.arclight.common.mixin.core.world.item.enchantment.effects; + +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.enchantment.EnchantedItemInUse; +import net.minecraft.world.item.enchantment.effects.ReplaceDisk; +import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ReplaceDisk.class) +public class ReplaceDiskMixin { + + @Redirect(method = "apply", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) + private boolean arclight$changeBlock(ServerLevel instance, BlockPos pos, BlockState blockState, ServerLevel serverLevel, int i, EnchantedItemInUse enchantedItemInUse, Entity entity) { + return CraftEventFactory.handleBlockFormEvent(instance, pos, blockState, entity); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/ExplosionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/ExplosionMixin.java index 49eb3aa82..ac18a5434 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/ExplosionMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/ExplosionMixin.java @@ -1,38 +1,24 @@ package io.izzel.arclight.common.mixin.core.world.level; import com.google.common.collect.Lists; -import com.google.common.collect.Sets; import com.mojang.datafixers.util.Pair; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.util.DamageSourceBridge; import io.izzel.arclight.common.bridge.core.world.ExplosionBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.Util; import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.ProtectionEnchantment; import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BaseFireBlock; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.TntBlock; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -46,18 +32,16 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.function.BiConsumer; @Mixin(Explosion.class) public abstract class ExplosionMixin implements ExplosionBridge { @@ -71,18 +55,11 @@ public abstract class ExplosionMixin implements ExplosionBridge { @Shadow @Final private double y; @Shadow @Final private double z; @Shadow @Final public Entity source; - @Shadow @Final private Map hitPlayers; @Accessor("source") public abstract Entity bridge$getExploder(); @Accessor("radius") public abstract float bridge$getSize(); @Accessor("radius") public abstract void bridge$setSize(float size); @Accessor("blockInteraction") public abstract Explosion.BlockInteraction bridge$getMode(); - @Shadow @Final private boolean fire; - @Shadow @Final private RandomSource random; - @Shadow @Final private ExplosionDamageCalculator damageCalculator; - @Shadow public abstract boolean interactsWithBlocks(); @Shadow @Final @Mutable private DamageSource damageSource; - @Shadow @Final private SoundEvent explosionSound; - @Shadow private static void addOrAppendStack(List> p_311090_, ItemStack p_311817_, BlockPos p_309821_) { } // @formatter:on public float yield; @@ -99,151 +76,60 @@ public abstract class ExplosionMixin implements ExplosionBridge { this.damageSource = ((DamageSourceBridge) (this.damageSource == null ? worldIn.damageSources().explosion((Explosion) (Object) this) : this.damageSource)).bridge$customCausingEntity(exploderIn); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void explode() { + @Inject(method = "explode", cancellable = true, at = @At("HEAD")) + private void arclight$returnRadius(CallbackInfo ci) { if (this.radius < 0.1F) { - return; + ci.cancel(); } - this.level.gameEvent(this.source, GameEvent.EXPLODE, new Vec3(this.x, this.y, this.z)); - Set set = Sets.newHashSet(); - int i = 16; - - for (int j = 0; j < 16; ++j) { - for (int k = 0; k < 16; ++k) { - for (int l = 0; l < 16; ++l) { - if (j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15) { - double d0 = ((float) j / 15.0F * 2.0F - 1.0F); - double d1 = ((float) k / 15.0F * 2.0F - 1.0F); - double d2 = ((float) l / 15.0F * 2.0F - 1.0F); - double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); - d0 = d0 / d3; - d1 = d1 / d3; - d2 = d2 / d3; - float f = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F); - double d4 = this.x; - double d6 = this.y; - double d8 = this.z; - - for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) { - BlockPos blockpos = BlockPos.containing(d4, d6, d8); - BlockState blockstate = this.level.getBlockState(blockpos); - FluidState fluidstate = this.level.getFluidState(blockpos); - - if (!this.level.isInWorldBounds(blockpos)) { - break; - } + } - Optional optional = this.damageCalculator.getBlockExplosionResistance((Explosion) (Object) this, this.level, blockpos, blockstate, fluidstate); - if (optional.isPresent()) { - f -= (optional.get() + 0.3F) * 0.3F; - } + @Decorate(method = "explode", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z")) + private boolean arclight$handleMultiPart(Entity entity, DamageSource damageSource, float f, @Local(ordinal = -1) List list) throws Throwable { + // Special case ender dragon only give knockback if no damage is cancelled + // Thinks to note: + // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) + // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon + // - Damaging EntityEnderDragon does nothing + // - EntityEnderDragon hitbock always covers the other parts and is therefore always present + if (((EntityBridge) entity).bridge$forge$isPartEntity()) { + throw DecorationOps.jumpToLoopStart(); + } - if (f > 0.0F && this.damageCalculator.shouldBlockExplode((Explosion) (Object) this, this.level, blockpos, blockstate, f)) { - set.add(blockpos); - } + ((EntityBridge) entity).bridge$setLastDamageCancelled(false); - d4 += d0 * (double) 0.3F; - d6 += d1 * (double) 0.3F; - d8 += d2 * (double) 0.3F; - } - } + var result = false; + var parts = ((EntityBridge) entity).bridge$forge$getParts(); + if (parts != null) { + for (var part : parts) { + // Calculate damage separately for each part + if (list.contains(part)) { + result |= part.hurt(damageSource, f); } } + } else { + result = (boolean) DecorationOps.callsite().invoke(entity, damageSource, f); } - this.toBlow.addAll(set); - float f3 = this.radius * 2.0F; - int k1 = Mth.floor(this.x - (double) f3 - 1.0D); - int l1 = Mth.floor(this.x + (double) f3 + 1.0D); - int i2 = Mth.floor(this.y - (double) f3 - 1.0D); - int i1 = Mth.floor(this.y + (double) f3 + 1.0D); - int j2 = Mth.floor(this.z - (double) f3 - 1.0D); - int j1 = Mth.floor(this.z + (double) f3 + 1.0D); - List list = this.level.getEntities(this.source, new AABB(k1, i2, j2, l1, i1, j1)); - this.bridge$forge$onExplosionDetonate(this.level, (Explosion) (Object) this, list, f3); - Vec3 vec3d = new Vec3(this.x, this.y, this.z); - - for (Entity entity : list) { - if (!entity.ignoreExplosion((Explosion) (Object) this)) { - double d12 = Math.sqrt(entity.distanceToSqr(vec3d)) / f3; - if (d12 <= 1.0D) { - double d5 = entity.getX() - this.x; - double d7 = entity.getEyeY() - this.y; - double d9 = entity.getZ() - this.z; - double d13 = Math.sqrt(d5 * d5 + d7 * d7 + d9 * d9); - if (d13 != 0.0D) { - d5 = d5 / d13; - d7 = d7 / d13; - d9 = d9 / d13; - if (this.damageCalculator.shouldDamageEntity((Explosion) (Object) this, entity)) { - // CraftBukkit start - - // Special case ender dragon only give knockback if no damage is cancelled - // Thinks to note: - // - Setting a velocity to a ComplexEntityPart is ignored (and therefore not needed) - // - Damaging ComplexEntityPart while forward the damage to EntityEnderDragon - // - Damaging EntityEnderDragon does nothing - // - EntityEnderDragon hitbock always covers the other parts and is therefore always present - if (((EntityBridge) entity).bridge$forge$isPartEntity()) { - continue; - } - - ((EntityBridge) entity).bridge$setLastDamageCancelled(false); - - var parts = ((EntityBridge) entity).bridge$forge$getParts(); - if (parts != null) { - for (var part : parts) { - // Calculate damage separately for each part - if (list.contains(part)) { - part.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount((Explosion) (Object) this, entity)); - } - } - } else { - entity.hurt(this.damageSource, this.damageCalculator.getEntityDamageAmount((Explosion) (Object) this, entity)); - } - - if (((EntityBridge) entity).bridge$isLastDamageCancelled()) { - continue; - } - } - - double d10 = (1.0D - d12) * Explosion.getSeenPercent(vec3d, entity); - - double d11; - if (entity instanceof LivingEntity) { - d11 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d10); - } else { - d11 = d10; - } - - d5 *= d11; - d7 *= d11; - d9 *= d11; - Vec3 vec3d1 = new Vec3(d5, d7, d9); - - // CraftBukkit start - Call EntityKnockbackEvent - if (entity instanceof LivingEntity) { - var result = entity.getDeltaMovement().add(vec3d1); - var event = CraftEventFactory.callEntityKnockbackEvent((CraftLivingEntity) entity.bridge$getBukkitEntity(), source, EntityKnockbackEvent.KnockbackCause.EXPLOSION, d13, vec3d1, result.x, result.y, result.z); - vec3d1 = (event.isCancelled()) ? Vec3.ZERO : new Vec3(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()); - } - // CraftBukkit end - - entity.setDeltaMovement(entity.getDeltaMovement().add(vec3d1)); - if (entity instanceof Player playerentity) { - if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.getAbilities().flying)) { - this.hitPlayers.put(playerentity, vec3d1); - } - } - } - } - } + if (((EntityBridge) entity).bridge$isLastDamageCancelled()) { + throw DecorationOps.jumpToLoopStart(); } + return result; + } + @Decorate(method = "explode", at = @At(value = "NEW", ordinal = 0, target = "(DDD)Lnet/minecraft/world/phys/Vec3;"), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ExplosionDamageCalculator;getKnockbackMultiplier(Lnet/minecraft/world/entity/Entity;)F"))) + private Vec3 arclight$knockBack(double d, double e, double f, @Local(ordinal = -1) Entity entity) throws Throwable { + var vec3 = (Vec3) DecorationOps.callsite().invoke(d, e, f); + double dx = entity.getX() - this.x; + double dy = entity.getEyeY() - this.y; + double dz = entity.getZ() - this.z; + var force = dx * dx + dy * dy + dz * dz; + if (entity instanceof LivingEntity) { + var result = entity.getDeltaMovement().add(vec3); + var event = CraftEventFactory.callEntityKnockbackEvent((CraftLivingEntity) entity.bridge$getBukkitEntity(), source, EntityKnockbackEvent.KnockbackCause.EXPLOSION, force, vec3, result.x, result.y, result.z); + vec3 = (event.isCancelled()) ? Vec3.ZERO : new Vec3(event.getFinalKnockback().getX(), event.getFinalKnockback().getY(), event.getFinalKnockback().getZ()).subtract(entity.getDeltaMovement()); + } + return vec3; } public boolean wasCanceled = false; @@ -253,70 +139,34 @@ public void explode() { return wasCanceled; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void finalizeExplosion(boolean spawnParticles) { - if (this.level.isClientSide) { - this.level.playLocalSound(this.x, this.y, this.z, this.explosionSound, SoundSource.BLOCKS, 4.0F, (1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F, false); - } - - boolean flag = this.interactsWithBlocks(); - if (spawnParticles) { - ParticleOptions particleType; - if (this.radius >= 2.0F && flag) { - particleType = ParticleTypes.EXPLOSION_EMITTER; - } else { - particleType = ParticleTypes.EXPLOSION; - } - this.level.addParticle(particleType, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + @Inject(method = "finalizeExplosion", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/Util;shuffle(Ljava/util/List;Lnet/minecraft/util/RandomSource;)V")) + private void arclight$blockExplode(boolean bl, CallbackInfo ci) { + if (this.callBlockExplodeEvent()) { + this.wasCanceled = true; + ci.cancel(); } + } - if (flag) { - this.level.getProfiler().push("explosion_blocks"); - List> list = new ArrayList<>(); - Util.shuffle(this.toBlow, this.level.random); - - if (this.callBlockExplodeEvent()) { - this.wasCanceled = true; + @Decorate(method = "finalizeExplosion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;onExplosionHit(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/Explosion;Ljava/util/function/BiConsumer;)V")) + private void arclight$tntPrime(BlockState instance, Level level, BlockPos pos, Explosion explosion, BiConsumer biConsumer) throws Throwable { + if (instance.getBlock() instanceof TntBlock) { + var sourceEntity = source == null ? null : source; + var sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; + if (!CraftEventFactory.callTNTPrimeEvent(this.level, pos, TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { + this.level.sendBlockUpdated(pos, Blocks.AIR.defaultBlockState(), instance, 3); // Update the block on the client return; } - - for (BlockPos blockpos : this.toBlow) { - BlockState blockstate = this.level.getBlockState(blockpos); - Block block = blockstate.getBlock(); - // CraftBukkit start - TNTPrimeEvent - if (block instanceof TntBlock) { - var sourceEntity = source == null ? null : source; - var sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; - if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockpos, TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { - this.level.sendBlockUpdated(blockpos, Blocks.AIR.defaultBlockState(), blockstate, 3); // Update the block on the client - continue; - } - } - // CraftBukkit end - this.level.getBlockState(blockpos).onExplosionHit(this.level, blockpos, (Explosion) (Object) this, (itemstack, pos) -> { - addOrAppendStack(list, itemstack, pos); - }); - } - - for (Pair pair : list) { - Block.popResource(this.level, pair.getSecond(), pair.getFirst()); - } } + DecorationOps.callsite().invoke(instance, level, pos, explosion, biConsumer); + } - if (this.fire) { - for (BlockPos blockpos2 : this.toBlow) { - if (this.random.nextInt(3) == 0 && this.level.getBlockState(blockpos2).isAir() && this.level.getBlockState(blockpos2.below()).isSolidRender(this.level, blockpos2.below())) { - BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.level, blockpos2, (Explosion) (Object) this); - if (!event.isCancelled()) { - this.level.setBlockAndUpdate(blockpos2, BaseFireBlock.getState(this.level, blockpos2)); - } - } - } + @Redirect(method = "finalizeExplosion", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlockAndUpdate(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Z")) + private boolean arclight$blockIgnite(Level instance, BlockPos blockPos, BlockState blockState) throws Throwable { + BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.level, blockPos, (Explosion) (Object) this); + if (event.isCancelled()) { + return false; } + return (boolean) DecorationOps.callsite().invoke(instance, blockPos, blockState); } @Inject(method = "addOrAppendStack", cancellable = true, at = @At("HEAD")) @@ -325,8 +175,8 @@ public void finalizeExplosion(boolean spawnParticles) { } private boolean callBlockExplodeEvent() { - org.bukkit.World world = ((WorldBridge) this.level).bridge$getWorld(); - org.bukkit.entity.Entity exploder = this.source == null ? null : ((EntityBridge) this.source).bridge$getBukkitEntity(); + org.bukkit.World world = this.level.bridge$getWorld(); + org.bukkit.entity.Entity exploder = this.source == null ? null : this.source.bridge$getBukkitEntity(); Location location = new Location(world, this.x, this.y, this.z); List blockList = Lists.newArrayList(); for (int i = this.toBlow.size() - 1; i >= 0; i--) { @@ -347,7 +197,9 @@ private boolean callBlockExplodeEvent() { bukkitBlocks = event.blockList(); this.yield = event.getYield(); } else { - BlockExplodeEvent event = new BlockExplodeEvent(location.getBlock(), blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F); + org.bukkit.block.Block block = location.getBlock(); + org.bukkit.block.BlockState blockState = (((DamageSourceBridge) damageSource).bridge$directBlockState() != null) ? ((DamageSourceBridge) damageSource).bridge$directBlockState() : block.getState(); + BlockExplodeEvent event = new BlockExplodeEvent(block, blockState, blockList, this.blockInteraction == Explosion.BlockInteraction.DESTROY_WITH_DECAY ? 1.0F / this.radius : 1.0F); Bukkit.getPluginManager().callEvent(event); cancelled = event.isCancelled(); bukkitBlocks = event.blockList(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java index b90749c5f..61742f310 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java @@ -85,12 +85,17 @@ public abstract class LevelMixin implements WorldBridge, LevelAccessor, LevelWri @Shadow public abstract LevelData getLevelData(); @Shadow public abstract ResourceKey dimension(); @Shadow public abstract DimensionType dimensionType(); - @Shadow public abstract void setBlocksDirty(BlockPos arg, BlockState arg2, BlockState arg3);@Shadow@Final public boolean isClientSide;@Shadow public abstract void sendBlockUpdated(BlockPos arg, BlockState arg2, BlockState arg3, int i);@Shadow public abstract void updateNeighbourForOutputSignal(BlockPos arg, Block arg2);@Shadow public abstract void onBlockStateChange(BlockPos arg, BlockState arg2, BlockState arg3);@Accessor("thread") public abstract Thread arclight$getMainThread(); + @Shadow public abstract void setBlocksDirty(BlockPos arg, BlockState arg2, BlockState arg3); + @Shadow @Final public boolean isClientSide; + @Shadow public abstract void sendBlockUpdated(BlockPos arg, BlockState arg2, BlockState arg3, int i); + @Shadow public abstract void updateNeighbourForOutputSignal(BlockPos arg, Block arg2); + @Shadow public abstract void onBlockStateChange(BlockPos arg, BlockState arg2, BlockState arg3); + @Shadow public abstract RegistryAccess registryAccess(); + @Accessor("thread") public abstract Thread arclight$getMainThread(); // @formatter:on protected CraftWorld world; public boolean pvpMode; - public boolean keepSpawnInMemory = true; public final Object2LongOpenHashMap ticksPerSpawnCategory = new Object2LongOpenHashMap<>(); public boolean populating; public org.bukkit.generator.ChunkGenerator generator; @@ -159,10 +164,10 @@ public abstract class LevelMixin implements WorldBridge, LevelAccessor, LevelWri return this.spigotConfig; } - @Inject(method = "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z", + @Inject(method = "setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;II)Z", at = @At("HEAD"), cancellable = true) - private void arclight$hooks(BlockPos pos, BlockState newState, int flags, CallbackInfoReturnable cir) { - if (!processCaptures(pos, newState, flags)) { + private void arclight$hooks(BlockPos pos, BlockState newState, int flags, int i, CallbackInfoReturnable cir) { + if (!ArclightCaptures.setLastEntityChangeBlockResult(processCaptures(pos, newState, flags))) { cir.setReturnValue(false); } } @@ -309,11 +314,6 @@ public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { return this.pvpMode; } - @Override - public boolean bridge$isKeepSpawnInMemory() { - return this.keepSpawnInMemory; - } - @Override public boolean bridge$isPopulating() { return this.populating; @@ -371,7 +371,7 @@ public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { private transient Explosion.BlockInteraction arclight$blockInteractionOverride; - @ModifyVariable(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;ZLnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/sounds/SoundEvent;)Lnet/minecraft/world/level/Explosion;", + @ModifyVariable(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;ZLnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)Lnet/minecraft/world/level/Explosion;", ordinal = 0, at = @At("HEAD"), argsOnly = true) private Level.ExplosionInteraction arclight$standardExplodePre(Level.ExplosionInteraction interaction) { if (interaction == ArclightConstants.STANDARD) { @@ -381,7 +381,7 @@ public BlockEntity getBlockEntity(BlockPos pos, boolean validate) { return interaction; } - @ModifyVariable(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;ZLnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/sounds/SoundEvent;)Lnet/minecraft/world/level/Explosion;", + @ModifyVariable(method = "explode(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lnet/minecraft/world/level/ExplosionDamageCalculator;DDDFZLnet/minecraft/world/level/Level$ExplosionInteraction;ZLnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/particles/ParticleOptions;Lnet/minecraft/core/Holder;)Lnet/minecraft/world/level/Explosion;", at = @At(value = "LOAD", ordinal = 0)) private Explosion.BlockInteraction arclight$standardExplodePost(Explosion.BlockInteraction interaction) { try { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/Level_ExplosionInteractionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/Level_ExplosionInteractionMixin.java index 0f354f6f9..16378ddc7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/Level_ExplosionInteractionMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/Level_ExplosionInteractionMixin.java @@ -12,5 +12,5 @@ public class Level_ExplosionInteractionMixin { @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL) - private static final Level.ExplosionInteraction STANDARD = EnumHelper.makeEnum(Level.ExplosionInteraction.class, "STANDARD", Level.ExplosionInteraction.values().length, List.of(), List.of()); + private static final Level.ExplosionInteraction STANDARD = EnumHelper.makeEnum(Level.ExplosionInteraction.class, "STANDARD", Level.ExplosionInteraction.values().length, List.of(String.class), List.of("standard")); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BaseFireBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BaseFireBlockMixin.java index a86e41e6c..44d655f52 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BaseFireBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BaseFireBlockMixin.java @@ -1,7 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.block; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -23,13 +24,13 @@ public class BaseFireBlockMixin { // fireExtinguished implemented per class - @Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setSecondsOnFire(I)V")) - private void arclight$onFire(Entity instance, int seconds, BlockState state, Level level, BlockPos pos) { - var event = new EntityCombustByBlockEvent(CraftBlock.at(level, pos), ((EntityBridge) instance).bridge$getBukkitEntity(), seconds); + @Decorate(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;igniteForSeconds(F)V")) + private void arclight$onFire(Entity instance, float f, BlockState blockState, Level level, BlockPos blockPos) throws Throwable { + var event = new EntityCombustByBlockEvent(CraftBlock.at(level, blockPos), instance.bridge$getBukkitEntity(), f); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - ((EntityBridge) instance).bridge$setOnFire(event.getDuration(), false); + DecorationOps.callsite().invoke(instance, event.getDuration()); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BedBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BedBlockMixin.java index 48388652c..5922919f6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BedBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BedBlockMixin.java @@ -2,7 +2,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; -import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -34,7 +33,7 @@ public abstract class BedBlockMixin { * @reason */ @Overwrite - public InteractionResult use(BlockState p_49515_, Level level, BlockPos p_49517_, Player p_49518_, InteractionHand p_49519_, BlockHitResult p_49520_) { + public InteractionResult useWithoutItem(BlockState p_49515_, Level level, BlockPos p_49517_, Player p_49518_, BlockHitResult p_49520_) { if (level.isClientSide) { return InteractionResult.CONSUME; } else { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BigDripleafBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BigDripleafBlockMixin.java index ffcf4286b..2018838b3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BigDripleafBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BigDripleafBlockMixin.java @@ -42,7 +42,7 @@ public class BigDripleafBlockMixin { if (entity instanceof Player) { cancellable = CraftEventFactory.callPlayerInteractEvent((Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); } else { - cancellable = new EntityInteractEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(level, pos)); + cancellable = new EntityInteractEvent(entity.bridge$getBukkitEntity(), CraftBlock.at(level, pos)); Bukkit.getPluginManager().callEvent((EntityInteractEvent) cancellable); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BlockMixin.java index 23c1af16d..3e4e828a5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/BlockMixin.java @@ -1,7 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block; -import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; +import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import io.izzel.arclight.common.mixin.core.world.level.block.state.BlockBehaviourMixin; import io.izzel.arclight.common.mod.util.ArclightCaptures; import io.izzel.arclight.common.mod.util.DistValidate; @@ -9,13 +9,13 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.valueproviders.IntProvider; +import net.minecraft.util.valueproviders.UniformInt; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; @@ -58,18 +58,21 @@ public int getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPo } protected int tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { - if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemstack) == 0) { - int i = intprovider.sample(worldserver.random); - if (i > 0) { - return i; - } + int i = EnchantmentHelper.processBlockExperience(worldserver, itemstack, intprovider.sample(worldserver.getRandom())); + if (i > 0) { + return i; } return 0; } + @Override + public int bridge$tryDropExperience(ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, IntProvider intprovider) { + return tryDropExperience(worldserver, blockposition, itemstack, intprovider); + } + @Override public int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) { - return 0; + return this.bridge$tryDropExperience(world, blockPos, itemStack, UniformInt.of(1, 5)); } @Inject(method = "playerDestroy", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;causeFoodExhaustion(F)V")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ButtonBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ButtonBlockMixin.java index f5a92f0c3..acedbfc5a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ButtonBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ButtonBlockMixin.java @@ -2,7 +2,7 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; import net.minecraft.world.level.Level; @@ -63,8 +63,8 @@ public class ButtonBlockMixin { } } - @Inject(method = "use", cancellable = true, at = @At(value = "HEAD")) - public void arclight$blockRedstone1(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", cancellable = true, at = @At(value = "HEAD")) + public void arclight$blockRedstone1(BlockState state, Level worldIn, BlockPos pos, Player player, BlockHitResult hit, CallbackInfoReturnable cir) { if (!state.getValue(POWERED)) { boolean powered = state.getValue(POWERED); Block block = CraftBlock.at(worldIn, pos); @@ -75,7 +75,7 @@ public class ButtonBlockMixin { Bukkit.getPluginManager().callEvent(event); if ((event.getNewCurrent() > 0) == (powered)) { - cir.setReturnValue(true); + cir.setReturnValue(InteractionResult.SUCCESS); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CampfireBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CampfireBlockMixin.java index 4af416317..36aef8d21 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CampfireBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CampfireBlockMixin.java @@ -27,8 +27,8 @@ public class CampfireBlockMixin { } } - @Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;inFire()Lnet/minecraft/world/damagesource/DamageSource;")) + @Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/damagesource/DamageSources;campfire()Lnet/minecraft/world/damagesource/DamageSource;")) private DamageSource arclight$fireDamage(DamageSources instance, BlockState blockState, Level level, BlockPos blockPos) { - return ((DamageSourceBridge) instance.inFire()).bridge$directBlock(CraftBlock.at(level, blockPos)); + return ((DamageSourceBridge) instance.campfire()).bridge$directBlock(CraftBlock.at(level, blockPos)); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CommandBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CommandBlockMixin.java index 3e926cae0..324c381d4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CommandBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/CommandBlockMixin.java @@ -1,49 +1,30 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.CommandBlock; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.CommandBlockEntity; -import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.event.block.BlockRedstoneEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.injection.At; @Mixin(CommandBlock.class) public abstract class CommandBlockMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { - if (!worldIn.isClientSide) { - BlockEntity tileentity = worldIn.getBlockEntity(pos); - if (tileentity instanceof CommandBlockEntity commandblocktileentity) { - boolean flag = worldIn.hasNeighborSignal(pos); - boolean flag1 = commandblocktileentity.isPowered(); - - org.bukkit.block.Block bukkitBlock = CraftBlock.at(worldIn, pos); - int old = flag1 ? 15 : 0; - int current = flag ? 15 : 0; - BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); - Bukkit.getPluginManager().callEvent(eventRedstone); - flag = eventRedstone.getNewCurrent() > 0; - - commandblocktileentity.setPowered(flag); - if (!flag1 && !commandblocktileentity.isAutomatic() && commandblocktileentity.getMode() != CommandBlockEntity.Mode.SEQUENCE) { - if (flag) { - commandblocktileentity.markConditionMet(); - worldIn.scheduleTick(pos, (CommandBlock) (Object) this, 1); - } - - } - } - } + @Decorate(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;hasNeighborSignal(Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$blockRedstone(Level instance, BlockPos pos) throws Throwable { + var flag = (boolean) DecorationOps.callsite().invoke(instance, pos); + var blockEntity = ((CommandBlockEntity) instance.getBlockEntity(pos)); + boolean flag1 = blockEntity.isPowered(); + org.bukkit.block.Block bukkitBlock = CraftBlock.at(instance, pos); + int old = flag1 ? 15 : 0; + int current = flag ? 15 : 0; + BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(bukkitBlock, old, current); + Bukkit.getPluginManager().callEvent(eventRedstone); + return eventRedstone.getNewCurrent() > 0; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ComposterBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ComposterBlockMixin.java index fc710a728..64c05d4bf 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ComposterBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/ComposterBlockMixin.java @@ -1,6 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; +import io.izzel.arclight.common.mod.util.ArclightCaptures; import it.unimi.dsi.fastutil.objects.Object2FloatMap; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; @@ -13,14 +14,12 @@ import net.minecraft.world.level.block.ComposterBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.IntegerProperty; -import net.minecraft.world.level.gameevent.GameEvent; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.inventory.CraftBlockInventoryHolder; import org.bukkit.craftbukkit.v.util.DummyGeneratorAccess; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -36,7 +35,6 @@ public abstract class ComposterBlockMixin { @Shadow static BlockState empty(@Nullable Entity p_270236_, BlockState p_270873_, LevelAccessor p_270963_, BlockPos p_270211_) { return null; } // @formatter:on - @SuppressWarnings({"InvalidMemberReference", "UnresolvedMixinReference", "MixinAnnotationTarget", "InvalidInjectorMethodSignature"}) @Redirect(method = "getContainer", at = @At(value = "NEW", target = "()Lnet/minecraft/world/level/block/ComposterBlock$EmptyContainer;")) public ComposterBlock.EmptyContainer arclight$newEmpty(BlockState blockState, LevelAccessor world, BlockPos blockPos) { ComposterBlock.EmptyContainer inventory = new ComposterBlock.EmptyContainer(); @@ -44,26 +42,10 @@ public abstract class ComposterBlockMixin { return inventory; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public static BlockState insertItem(Entity entity, BlockState state, ServerLevel world, ItemStack stack, BlockPos pos) { - int i = state.getValue(LEVEL); - if (i < 7 && COMPOSTABLES.containsKey(stack.getItem())) { - double rand = world.random.nextDouble(); - BlockState state1 = addItem(entity, state, DummyGeneratorAccess.INSTANCE, pos, stack, rand); - - if (state == state1 || !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state1)) { - return state; - } - - state1 = addItem(entity, state, world, pos, stack, rand); - stack.shrink(1); - return state1; - } else { - return state; + @Inject(method = "insertItem", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/ComposterBlock;addItem(Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/LevelAccessor;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/level/block/state/BlockState;")) + private static void arclight$changeBlockEvent(Entity entity, BlockState blockState, ServerLevel serverLevel, ItemStack itemStack, BlockPos blockPos, CallbackInfoReturnable cir) { + if (!ArclightCaptures.getLastEntityChangeBlockResult()) { + cir.setReturnValue(blockState); } } @@ -76,21 +58,4 @@ public static BlockState insertItem(Entity entity, BlockState state, ServerLevel } } } - - private static BlockState addItem(Entity entity, BlockState state, LevelAccessor world, BlockPos pos, ItemStack stack, double rand) { - int i = state.getValue(LEVEL); - float f = COMPOSTABLES.getFloat(stack.getItem()); - if ((i != 0 || !(f > 0.0F)) && !(rand < (double) f)) { - return state; - } else { - int j = i + 1; - BlockState blockstate = state.setValue(LEVEL, j); - world.setBlock(pos, blockstate, 3); - world.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, blockstate)); - if (j == 7) { - world.scheduleTick(pos, state.getBlock(), 20); - } - return blockstate; - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DetectorRailBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DetectorRailBlockMixin.java index ea0000fdb..c7049bd3e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DetectorRailBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DetectorRailBlockMixin.java @@ -1,5 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.DetectorRailBlock; @@ -8,34 +11,27 @@ import org.bukkit.block.Block; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.event.block.BlockRedstoneEvent; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.List; @Mixin(DetectorRailBlock.class) public class DetectorRailBlockMixin { - private transient boolean arclight$flag; - - @Inject(method = "checkPressed", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "JUMP", ordinal = 1, opcode = Opcodes.IFEQ)) - public void arclight$blockRedstone(Level worldIn, BlockPos pos, BlockState state, CallbackInfo ci, boolean flag, boolean flag1) { + @Decorate(method = "checkPressed", at = @At(value = "INVOKE", target = "Ljava/util/List;isEmpty()Z")) + private boolean arclight$blockRedstone(List instance, Level level, BlockPos blockPos, BlockState blockState, + @Local(ordinal = 0) boolean flag) throws Throwable { + boolean result = (boolean) DecorationOps.callsite().invoke(instance); + boolean flag1 = !result; if (flag != flag1) { - Block block = CraftBlock.at(worldIn, pos); + Block block = CraftBlock.at(level, blockPos); BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(block, flag ? 15 : 0, flag1 ? 15 : 0); Bukkit.getPluginManager().callEvent(eventRedstone); - arclight$flag = eventRedstone.getNewCurrent() > 0; + flag1 = eventRedstone.getNewCurrent() > 0; } - } - - // todo 注入顺序 - @ModifyVariable(method = "checkPressed", index = 5, name = "flag1", at = @At(value = "JUMP", ordinal = 1, opcode = Opcodes.IFEQ)) - public boolean arclight$blockRedstone(boolean flag1) { - return arclight$flag; + return !flag1; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin.java new file mode 100644 index 000000000..efd8ad73d --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin.java @@ -0,0 +1,24 @@ +package io.izzel.arclight.common.mixin.core.world.level.block; + +import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.DispenserBlock; +import net.minecraft.world.level.block.state.BlockState; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(DispenserBlock.class) +public class DispenserBlockMixin { + + @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC) + private static boolean eventFired = false; + + @Inject(method = "dispenseFrom", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/DispenserBlockEntity;setItem(ILnet/minecraft/world/item/ItemStack;)V")) + private void arclight$reset(ServerLevel serverLevel, BlockState blockState, BlockPos blockPos, CallbackInfo ci) { + eventFired = false; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin_Accessor.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin_Accessor.java deleted file mode 100644 index d994f34b2..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DispenserBlockMixin_Accessor.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.block; - -import net.minecraft.core.dispenser.DispenseItemBehavior; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.DispenserBlock; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(DispenserBlock.class) -public interface DispenserBlockMixin_Accessor { - - @Accessor("DISPENSER_REGISTRY") - static Map getDispenseBehaviorRegistry() { - return null; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DragonEggBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DragonEggBlockMixin.java index 07be6861f..64489ed91 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DragonEggBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DragonEggBlockMixin.java @@ -1,44 +1,34 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.DragonEggBlock; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.border.WorldBorder; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.event.block.BlockFromToEvent; -import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(DragonEggBlock.class) public class DragonEggBlockMixin { - @Inject(method = "teleport", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/Level;isClientSide:Z")) - public void arclight$blockFromTo(BlockState blockState, Level world, BlockPos blockPos, CallbackInfo ci, - WorldBorder wb, int i, BlockPos pos) { + @Decorate(method = "teleport", inject = true, at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/Level;isClientSide:Z")) + private void arclight$blockFromTo(BlockState blockState, Level world, BlockPos blockPos, + @Local(ordinal = -1) BlockPos pos) throws Throwable { org.bukkit.block.Block from = CraftBlock.at(world, blockPos); org.bukkit.block.Block to = CraftBlock.at(world, pos); BlockFromToEvent event = new BlockFromToEvent(from, to); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - ci.cancel(); + DecorationOps.cancel().invoke(); + return; } else { - arclight$toBlock = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); + pos = new BlockPos(event.getToBlock().getX(), event.getToBlock().getY(), event.getToBlock().getZ()); } + DecorationOps.blackhole().invoke(pos); } - - private transient BlockPos arclight$toBlock; - - @ModifyVariable(method = "teleport", ordinal = 1, name = "blockpos", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 2)) - public BlockPos arclight$setPos(BlockPos pos) { - return arclight$toBlock; - } - } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DropperBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DropperBlockMixin.java index b9ce47e33..07b6fd83c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DropperBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/DropperBlockMixin.java @@ -1,88 +1,43 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; -import net.minecraft.core.BlockPos; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.Direction; -import net.minecraft.core.dispenser.BlockSource; -import net.minecraft.core.dispenser.DispenseItemBehavior; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.CompoundContainer; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.DispenserBlock; import net.minecraft.world.level.block.DropperBlock; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.entity.DispenserBlockEntity; -import net.minecraft.world.level.block.entity.HopperBlockEntity; -import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.inventory.CraftInventoryDoubleChest; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.inventory.Inventory; -import org.slf4j.Logger; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; @Mixin(DropperBlock.class) public abstract class DropperBlockMixin extends BlockMixin { - @Shadow @Final private static DispenseItemBehavior DISPENSE_BEHAVIOUR; - @Shadow @Final private static Logger LOGGER; - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void dispenseFrom(ServerLevel worldIn, BlockState state, BlockPos pos) { - DispenserBlockEntity dispensertileentity = worldIn.getBlockEntity(pos, BlockEntityType.DROPPER).orElse(null); - - if (dispensertileentity == null) { - LOGGER.warn("Ignoring dispensing attempt for Dropper without matching block entity at {}", pos); + @Decorate(method = "dispenseFrom", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/entity/HopperBlockEntity;addItem(Lnet/minecraft/world/Container;Lnet/minecraft/world/Container;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/core/Direction;)Lnet/minecraft/world/item/ItemStack;")) + private ItemStack arclight$moveItemEvent(Container from, Container to, ItemStack stack, Direction direction) throws Throwable { + CraftItemStack craftItemStack = CraftItemStack.asCraftMirror(stack); + Inventory destinationInventory; + // Have to special case large chests as they work oddly + if (to instanceof CompoundContainer) { + destinationInventory = new CraftInventoryDoubleChest((CompoundContainer) to); } else { - BlockSource blocksource = new BlockSource(worldIn, pos, state, dispensertileentity); - - int i = dispensertileentity.getRandomSlot(worldIn.getRandom()); - if (i < 0) { - worldIn.levelEvent(1001, pos, 0); - } else { - ItemStack itemstack = dispensertileentity.getItem(i); - if (!itemstack.isEmpty() && this.bridge$forge$dropperInsertHook(worldIn, pos, dispensertileentity, i, itemstack)) { - Direction direction = worldIn.getBlockState(pos).getValue(DispenserBlock.FACING); - Container iinventory = HopperBlockEntity.getContainerAt(worldIn, pos.relative(direction)); - ItemStack itemstack1; - if (iinventory == null) { - itemstack1 = DISPENSE_BEHAVIOUR.dispense(blocksource, itemstack); - } else { - ItemStack split = itemstack.copy().split(1); - CraftItemStack craftItemStack = CraftItemStack.asCraftMirror(split); - Inventory destinationInventory; - // Have to special case large chests as they work oddly - if (iinventory instanceof CompoundContainer) { - destinationInventory = new CraftInventoryDoubleChest((CompoundContainer) iinventory); - } else { - destinationInventory = ((IInventoryBridge) iinventory).getOwnerInventory(); - } - InventoryMoveItemEvent event = new InventoryMoveItemEvent(((IInventoryBridge) dispensertileentity).getOwner().getInventory(), craftItemStack, destinationInventory, true); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - itemstack1 = HopperBlockEntity.addItem(dispensertileentity, iinventory, CraftItemStack.asNMSCopy(event.getItem()), direction.getOpposite()); - if (event.getItem().equals(craftItemStack) && itemstack1.isEmpty()) { - itemstack1 = itemstack.copy(); - itemstack1.shrink(1); - } else { - itemstack1 = itemstack.copy(); - } - } - - dispensertileentity.setItem(i, itemstack1); - } - } + destinationInventory = ((IInventoryBridge) to).getOwnerInventory(); + } + InventoryMoveItemEvent event = new InventoryMoveItemEvent(((IInventoryBridge) from).getOwner().getInventory(), craftItemStack, destinationInventory, true); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + return (ItemStack) DecorationOps.cancel().invoke(); + } + var result = (ItemStack) DecorationOps.callsite().invoke(from, to, CraftItemStack.asNMSCopy(event.getItem()), direction); + if (result.isEmpty() && !event.getItem().equals(craftItemStack)) { + result = stack.copyWithCount(1); } + return result; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndGatewayBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndGatewayBlockMixin.java new file mode 100644 index 000000000..7c2c0a900 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndGatewayBlockMixin.java @@ -0,0 +1,25 @@ +package io.izzel.arclight.common.mixin.core.world.level.block; + +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.EndGatewayBlock; +import net.minecraft.world.level.portal.DimensionTransition; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EndGatewayBlock.class) +public class EndGatewayBlockMixin { + + @Inject(method = "getPortalDestination", at = @At("RETURN")) + private void arclight$setCause(ServerLevel serverLevel, Entity entity, BlockPos blockPos, CallbackInfoReturnable cir) { + var dimensionTransition = cir.getReturnValue(); + if (dimensionTransition != null) { + ((DimensionTransitionBridge) ((Object) dimensionTransition)).bridge$setTeleportCause(PlayerTeleportEvent.TeleportCause.END_GATEWAY); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndPortalBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndPortalBlockMixin.java index f95c0b1e9..2526b82b5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndPortalBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/EndPortalBlockMixin.java @@ -1,36 +1,62 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; +import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.EndPortalBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.portal.DimensionTransition; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.craftbukkit.v.CraftWorld; +import org.bukkit.craftbukkit.v.util.CraftLocation; import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Slice; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EndPortalBlock.class) public class EndPortalBlockMixin { - @Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;getLevel(Lnet/minecraft/resources/ResourceKey;)Lnet/minecraft/server/level/ServerLevel;")) - public ServerLevel arclight$enterPortal(MinecraftServer minecraftServer, ResourceKey dimension, BlockState state, Level worldIn, BlockPos pos, Entity entityIn) { - ServerLevel world = minecraftServer.getLevel(dimension); - EntityPortalEnterEvent event = new EntityPortalEnterEvent(entityIn.bridge$getBukkitEntity(), - new Location(worldIn.bridge$getWorld(), pos.getX(), pos.getY(), pos.getZ())); + @Inject(method = "entityInside", at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/Level;isClientSide:Z")) + public void arclight$enterPortal(BlockState blockState, Level level, BlockPos pos, Entity entity, CallbackInfo ci) { + EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.bridge$getBukkitEntity(), + new Location(level.bridge$getWorld(), pos.getX(), pos.getY(), pos.getZ())); Bukkit.getPluginManager().callEvent(event); - if (entityIn instanceof ServerPlayer && world != null) { - ((ServerPlayerEntityBridge) entityIn).bridge$changeDimension(world, PlayerTeleportEvent.TeleportCause.END_PORTAL); - return null; + } + + @Inject(method = "getPortalDestination", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;findRespawnPositionAndUseSpawnBlock(ZLnet/minecraft/world/level/portal/DimensionTransition$PostDimensionTransition;)Lnet/minecraft/world/level/portal/DimensionTransition;")) + private void arclight$pushCause(ServerLevel serverLevel, Entity entity, BlockPos blockPos, CallbackInfoReturnable cir) { + ((ServerPlayerEntityBridge) entity).bridge$pushRespawnReason(PlayerRespawnEvent.RespawnReason.END_PORTAL); + } + + @Inject(method = "getPortalDestination", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/feature/EndPlatformFeature;createEndPlatform(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/core/BlockPos;Z)V")) + private void arclight$pushEntity(ServerLevel serverLevel, Entity entity, BlockPos blockPos, CallbackInfoReturnable cir) { + ArclightCaptures.captureEndPortalEntity(entity, true); + } + + @Inject(method = "getPortalDestination", at = @At("RETURN"), cancellable = true, + slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/portal/DimensionTransition;PLAY_PORTAL_SOUND:Lnet/minecraft/world/level/portal/DimensionTransition$PostDimensionTransition;"))) + private void arclight$fireEvent(ServerLevel serverLevel, Entity entity, BlockPos blockPos, CallbackInfoReturnable cir) { + var dt = cir.getReturnValue(); + var event = ((EntityBridge) entity).bridge$callPortalEvent(entity, CraftLocation.toBukkit(dt.pos(), dt.newLevel().bridge$getWorld(), dt.yRot(), dt.xRot()), PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); + if (event == null) { + cir.setReturnValue(null); + return; } - return world; + Location to = event.getTo(); + var newDt = new DimensionTransition(((CraftWorld) to.getWorld()).getHandle(), CraftLocation.toVec3D(to), entity.getDeltaMovement(), to.getYaw(), to.getPitch(), DimensionTransition.PLAY_PORTAL_SOUND.then(DimensionTransition.PLACE_PORTAL_TICKET)); + ((DimensionTransitionBridge) (Object) newDt).bridge$setTeleportCause(PlayerTeleportEvent.TeleportCause.END_PORTAL); + cir.setReturnValue(newDt); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java index f0c5d9aff..b1edb7d5c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.world.level.block.FireBlockBridge; -import io.izzel.arclight.common.mod.mixins.annotation.InlineMethod; import it.unimi.dsi.fastutil.objects.Object2IntMap; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -31,7 +30,6 @@ public abstract class FireBlockMixin extends BaseFireBlockMixin implements FireB @Shadow @Final private Object2IntMap burnOdds; // @formatter:on - @InlineMethod @Redirect(method = "tick", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/server/level/ServerLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) public boolean arclight$fireSpread(ServerLevel world, BlockPos mutablePos, BlockState newState, int flags, BlockState state, ServerLevel worldIn, BlockPos pos) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LeverBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LeverBlockMixin.java index 3c7839d53..109ac0d94 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LeverBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LeverBlockMixin.java @@ -1,7 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.LeverBlock; @@ -26,8 +26,8 @@ public class LeverBlockMixin { @Shadow @Final public static BooleanProperty POWERED; // @formatter:on - @Inject(method = "use", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/LeverBlock;pull(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) - public void arclight$blockRedstone(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/LeverBlock;pull(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)V")) + public void arclight$blockRedstone(BlockState state, Level worldIn, BlockPos pos, Player player, BlockHitResult hit, CallbackInfoReturnable cir) { boolean flag = state.getValue(POWERED); Block block = CraftBlock.at(worldIn, pos); int old = (flag) ? 15 : 0; @@ -37,7 +37,7 @@ public class LeverBlockMixin { Bukkit.getPluginManager().callEvent(eventRedstone); if ((eventRedstone.getNewCurrent() > 0) == flag) { - cir.setReturnValue(true); + cir.setReturnValue(InteractionResult.SUCCESS); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LightningRodBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LightningRodBlockMixin.java index a6b1d0cb1..a736718e3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LightningRodBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/LightningRodBlockMixin.java @@ -1,21 +1,15 @@ package io.izzel.arclight.common.mixin.core.world.level.block; -import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; -import io.izzel.arclight.common.mod.util.DistValidate; import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LightningBolt; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.LightningRodBlock; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.event.block.BlockRedstoneEvent; -import org.bukkit.event.weather.LightningStrikeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LightningRodBlock.class) @@ -34,11 +28,4 @@ public class LightningRodBlockMixin { ci.cancel(); } } - - @Redirect(method = "onProjectileHit", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private boolean arclight$strikeReason(Level level, Entity entity) { - if (!DistValidate.isValid(level)) return level.addFreshEntity(entity); - ((ServerWorldBridge) level).bridge$strikeLightning((LightningBolt) entity, LightningStrikeEvent.Cause.TRIDENT); - return true; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/NetherPortalBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/NetherPortalBlockMixin.java index 4af82c02e..71ccdbb76 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/NetherPortalBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/NetherPortalBlockMixin.java @@ -1,7 +1,14 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.EntityTypeBridge; +import io.izzel.arclight.common.bridge.core.world.TeleporterBridge; +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.BlockUtil; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -9,15 +16,22 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.NetherPortalBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.border.WorldBorder; +import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.craftbukkit.v.CraftWorld; +import org.bukkit.craftbukkit.v.util.CraftLocation; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(NetherPortalBlock.class) public class NetherPortalBlockMixin { @@ -27,10 +41,35 @@ public class NetherPortalBlockMixin { return ((EntityTypeBridge) instance).bridge$spawnCreature(p_262634_, p_262707_, p_262597_, CreatureSpawnEvent.SpawnReason.NETHER_PORTAL); } - @Inject(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleInsidePortal(Lnet/minecraft/core/BlockPos;)V")) + @Inject(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setAsInsidePortal(Lnet/minecraft/world/level/block/Portal;Lnet/minecraft/core/BlockPos;)V")) public void arclight$portalEnter(BlockState state, Level worldIn, BlockPos pos, Entity entityIn, CallbackInfo ci) { EntityPortalEnterEvent event = new EntityPortalEnterEvent(entityIn.bridge$getBukkitEntity(), new Location(worldIn.bridge$getWorld(), pos.getX(), pos.getY(), pos.getZ())); Bukkit.getPluginManager().callEvent(event); } + + @Decorate(method = "getPortalDestination", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/NetherPortalBlock;getExitPortal(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/BlockPos;ZLnet/minecraft/world/level/border/WorldBorder;)Lnet/minecraft/world/level/portal/DimensionTransition;")) + private DimensionTransition arclight$createPortalEvent(NetherPortalBlock instance, ServerLevel serverLevel, Entity entity, BlockPos blockPos, BlockPos blockPos2, boolean bl, WorldBorder worldBorder) throws Throwable { + var event = ((EntityBridge) entity).bridge$callPortalEvent(entity, CraftLocation.toBukkit(blockPos2, serverLevel.bridge$getWorld()), PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, bl ? 16 : 128, 16); + if (event == null) { + return null; + } + serverLevel = ((CraftWorld) event.getTo().getWorld()).getHandle(); + worldBorder = serverLevel.getWorldBorder(); + blockPos2 = worldBorder.clampToBounds(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + ((TeleporterBridge) serverLevel.getPortalForcer()).bridge$pushSearchRadius(event.getSearchRadius()); + ((TeleporterBridge) serverLevel.getPortalForcer()).bridge$pushPortalCreate(entity, event.getCreationRadius()); + var result = (DimensionTransition) DecorationOps.callsite().invoke(instance, serverLevel, entity, blockPos, blockPos2, bl, worldBorder); + ((TeleporterBridge) serverLevel.getPortalForcer()).bridge$pushSearchRadius(-1); + ((TeleporterBridge) serverLevel.getPortalForcer()).bridge$pushPortalCreate(null, -1); + return result; + } + + @Inject(method = "createDimensionTransition", at = @At("RETURN")) + private static void arclight$setCause(ServerLevel serverLevel, BlockUtil.FoundRectangle foundRectangle, Direction.Axis axis, Vec3 vec3, Entity entity, Vec3 vec32, float f, float g, DimensionTransition.PostDimensionTransition postDimensionTransition, CallbackInfoReturnable cir) { + var dimensionTransition = cir.getReturnValue(); + if (dimensionTransition != null) { + ((DimensionTransitionBridge) (Object) dimensionTransition).bridge$setTeleportCause(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalInfoMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalInfoMixin.java deleted file mode 100644 index a0aed0f0d..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalInfoMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.block; - -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.portal.PortalInfo; -import org.bukkit.craftbukkit.v.event.CraftPortalEvent; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(PortalInfo.class) -public class PortalInfoMixin implements PortalInfoBridge { - - public ServerLevel world; - public CraftPortalEvent portalEventInfo; - - @Override - public void bridge$setPortalEventInfo(CraftPortalEvent event) { - this.portalEventInfo = event; - } - - @Override - public CraftPortalEvent bridge$getPortalEventInfo() { - return this.portalEventInfo; - } - - @Override - public void bridge$setWorld(ServerLevel world) { - this.world = world; - } - - @Override - public ServerLevel bridge$getWorld() { - return this.world; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalShapeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalShapeMixin.java index 85d809dd7..06116b2ad 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalShapeMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/PortalShapeMixin.java @@ -1,30 +1,22 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.world.IWorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; import io.izzel.arclight.common.bridge.core.world.level.block.PortalSizeBridge; import io.izzel.arclight.common.mod.mixins.annotation.RenameInto; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.BlockUtil; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.NetherPortalBlock; import net.minecraft.world.level.block.state.BlockBehaviour; -import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.level.portal.PortalShape; -import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.World; -import org.bukkit.block.BlockState; -import org.bukkit.craftbukkit.v.block.CraftBlock; -import org.bukkit.craftbukkit.v.block.CraftBlockState; -import org.bukkit.craftbukkit.v.block.CraftBlockStates; -import org.bukkit.craftbukkit.v.event.CraftPortalEvent; +import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; import org.bukkit.event.world.PortalCreateEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -35,8 +27,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; @Mixin(PortalShape.class) public abstract class PortalShapeMixin implements PortalSizeBridge { @@ -49,16 +39,41 @@ public abstract class PortalShapeMixin implements PortalSizeBridge { @Shadow private int height; @Shadow @Final private Direction rightDir; @Shadow @Final private int width; - @Shadow public static PortalInfo createPortalInfo(ServerLevel p_259301_, BlockUtil.FoundRectangle p_259931_, Direction.Axis p_259901_, Vec3 p_259630_, Entity p_259166_, Vec3 p_260043_, float p_259853_, float p_259667_) { return null; } // @formatter:on - List blocks = new ArrayList<>(); + BlockStateListPopulator blocks; - @Redirect(method = "getDistanceUntilEdgeAboveFrame", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z")) + @Decorate(method = "", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/portal/PortalShape;calculateBottomLeft(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/core/BlockPos;")) + private void arclight$init(LevelAccessor levelAccessor) { + this.blocks = new BlockStateListPopulator(levelAccessor); + } + + @Redirect(method = "getDistanceUntilEdgeAboveFrame", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z")) private boolean arclight$captureBlock(BlockBehaviour.StatePredicate predicate, net.minecraft.world.level.block.state.BlockState p_test_1_, BlockGetter p_test_2_, BlockPos pos) { boolean test = predicate.test(p_test_1_, p_test_2_, pos); if (test) { - blocks.add(CraftBlock.at(this.level, pos).getState()); + blocks.setBlock(pos, this.level.getBlockState(pos), 18); + } + return test; + } + + @Redirect(method = "hasTopFrame", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$captureBlock2(BlockBehaviour.StatePredicate predicate, net.minecraft.world.level.block.state.BlockState p_test_1_, BlockGetter p_test_2_, BlockPos pos) { + boolean test = predicate.test(p_test_1_, p_test_2_, pos); + if (test) { + blocks.setBlock(pos, this.level.getBlockState(pos), 18); + } + return test; + } + + @Decorate(method = "getDistanceUntilTop", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$StatePredicate;test(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$captureBlock3(BlockBehaviour.StatePredicate predicate, net.minecraft.world.level.block.state.BlockState p_test_1_, BlockGetter p_test_2_, BlockPos pos, + @Local(ordinal = 0) int i) throws Throwable { + boolean test = (boolean) DecorationOps.callsite().invoke(predicate, p_test_1_, p_test_2_, pos); + if (test) { + var mutablePos = pos.mutable(); + blocks.setBlock(mutablePos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, -1), this.level.getBlockState(mutablePos), 18); + blocks.setBlock(mutablePos.set(this.bottomLeft).move(Direction.UP, i).move(this.rightDir, this.width), this.level.getBlockState(mutablePos), 18); } return test; } @@ -67,12 +82,10 @@ public abstract class PortalShapeMixin implements PortalSizeBridge { private void arclight$buildPortal(CallbackInfo ci) { World world = ((IWorldBridge) this.level).bridge$getMinecraftWorld().bridge$getWorld(); net.minecraft.world.level.block.state.BlockState blockState = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis); - BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach(pos -> { - CraftBlockState state = CraftBlockStates.getBlockState(((IWorldBridge) this.level).bridge$getMinecraftWorld(), pos, 18); - state.setData(blockState); - this.blocks.add(state); + BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1)).forEach((blockPos) -> { + blocks.setBlock(blockPos, blockState, 18); }); - PortalCreateEvent event = new PortalCreateEvent(this.blocks, world, null, PortalCreateEvent.CreateReason.FIRE); + PortalCreateEvent event = new PortalCreateEvent((java.util.List) (java.util.List) this.blocks.getList(), world, null, PortalCreateEvent.CreateReason.FIRE); Bukkit.getPluginManager().callEvent(event); arclight$ret = !event.isCancelled(); if (event.isCancelled()) { @@ -92,18 +105,4 @@ public abstract class PortalShapeMixin implements PortalSizeBridge { public boolean bridge$createPortal() { return bukkit$createPortalBlocks(); } - - @SuppressWarnings("ConstantConditions") - @Redirect(method = "createPortalInfo", at = @At(value = "NEW", target = "(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;FF)Lnet/minecraft/world/level/portal/PortalInfo;")) - private static PortalInfo arclight$setPortalInfo(Vec3 pos, Vec3 motion, float rotationYaw, float rotationPitch, ServerLevel world) { - PortalInfo portalInfo = new PortalInfo(pos, motion, rotationYaw, rotationPitch); - ((PortalInfoBridge) portalInfo).bridge$setWorld(world); - ((PortalInfoBridge) portalInfo).bridge$setPortalEventInfo(ArclightCaptures.getCraftPortalEvent()); - return portalInfo; - } - - private static PortalInfo createPortalInfo(ServerLevel world, BlockUtil.FoundRectangle result, Direction.Axis axis, Vec3 offsetVector, Entity entity, Vec3 motion, float rotationYaw, float rotationPitch, CraftPortalEvent event) { - ArclightCaptures.captureCraftPortalEvent(event); - return createPortalInfo(world, result, axis, offsetVector, entity, motion, rotationYaw, rotationPitch); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RedstoneOreBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RedstoneOreBlockMixin.java index a71281e34..a9e37254c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RedstoneOreBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RedstoneOreBlockMixin.java @@ -1,12 +1,13 @@ package io.izzel.arclight.common.mixin.core.world.level.block; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.RedStoneOreBlock; import net.minecraft.world.level.block.state.BlockState; @@ -47,7 +48,7 @@ public abstract class RedstoneOreBlockMixin { return; } } else { - EntityInteractEvent event = new EntityInteractEvent(((EntityBridge) entityIn).bridge$getBukkitEntity(), CraftBlock.at(worldIn, pos)); + EntityInteractEvent event = new EntityInteractEvent(entityIn.bridge$getBukkitEntity(), CraftBlock.at(worldIn, pos)); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { ci.cancel(); @@ -57,8 +58,8 @@ public abstract class RedstoneOreBlockMixin { arclight$entity = entityIn; } - @Inject(method = "use", at = @At(value = "HEAD")) - public void arclight$interact3(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit, CallbackInfoReturnable cir) { + @Inject(method = "useItemOn", at = @At(value = "HEAD")) + public void arclight$interact3(ItemStack itemStack, BlockState blockState, Level level, BlockPos blockPos, Player player, InteractionHand interactionHand, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { arclight$entity = player; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java index 4c883019d..c0c985e31 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java @@ -2,7 +2,6 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -18,8 +17,8 @@ @Mixin(RespawnAnchorBlock.class) public class RespawnAnchorBlockMixin { - @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) - private void arclight$cause(BlockState p_55874_, Level p_55875_, BlockPos p_55876_, Player player, InteractionHand p_55878_, BlockHitResult p_55879_, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) + private void arclight$cause(BlockState blockState, Level level, BlockPos blockPos, Player player, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { ((ServerPlayerEntityBridge) player).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SculkSensorBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SculkSensorBlockMixin.java index 1a9a93238..23ec8bb9a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SculkSensorBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SculkSensorBlockMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; @@ -12,10 +14,8 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.BlockRedstoneEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(SculkSensorBlock.class) @@ -46,20 +46,15 @@ public class SculkSensorBlockMixin { } } - @Unique private int newCurrent; - - @Inject(method = "activate", cancellable = true, at = @At("HEAD")) - private void arclight$activate(Entity p_222126_, Level level, BlockPos pos, BlockState state, int i, int j, CallbackInfo ci) { + @Decorate(method = "activate", inject = true, at = @At("HEAD")) + private void arclight$activate(Entity p_222126_, Level level, BlockPos pos, BlockState state, int i, int j) throws Throwable { BlockRedstoneEvent eventRedstone = new BlockRedstoneEvent(CraftBlock.at(level, pos), state.getValue(SculkSensorBlock.POWER), i); Bukkit.getPluginManager().callEvent(eventRedstone); if (eventRedstone.getNewCurrent() <= 0) { - ci.cancel(); + DecorationOps.cancel().invoke(); + return; } - newCurrent = eventRedstone.getNewCurrent(); - } - - @ModifyVariable(method = "activate", ordinal = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z"), argsOnly = true) - private int arclight$updateCurrent(int old) { - return newCurrent; + i = eventRedstone.getNewCurrent(); + DecorationOps.blackhole().invoke(i); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SignBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SignBlockMixin.java index 51f79bc65..75b60cf02 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SignBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SignBlockMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -27,13 +26,13 @@ public abstract class SignBlockMixin { private transient PlayerSignOpenEvent.Cause arclight$edit; - @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/SignBlock;openTextEdit(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/block/entity/SignBlockEntity;Z)V")) - private void arclight$beforeEdit(BlockState p_56278_, Level p_56279_, BlockPos p_56280_, Player p_56281_, InteractionHand p_56282_, BlockHitResult p_56283_, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/SignBlock;openTextEdit(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/block/entity/SignBlockEntity;Z)V")) + private void arclight$beforeEdit(BlockState blockState, Level level, BlockPos blockPos, Player player, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { arclight$edit = PlayerSignOpenEvent.Cause.INTERACT; } - @Inject(method = "use", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/SignBlock;openTextEdit(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/block/entity/SignBlockEntity;Z)V")) - private void arclight$afterEdit(BlockState p_56278_, Level p_56279_, BlockPos p_56280_, Player p_56281_, InteractionHand p_56282_, BlockHitResult p_56283_, CallbackInfoReturnable cir) { + @Inject(method = "useWithoutItem", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/block/SignBlock;openTextEdit(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/level/block/entity/SignBlockEntity;Z)V")) + private void arclight$afterEdit(BlockState blockState, Level level, BlockPos blockPos, Player player, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { arclight$edit = null; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java index 0b9850d51..18b305078 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/SweetBerryBushBlockMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.block; import io.izzel.arclight.common.bridge.core.util.DamageSourceBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import io.izzel.arclight.mixin.Eject; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; @@ -8,11 +10,9 @@ import net.minecraft.world.InteractionResult; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.damagesource.DamageSources; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SweetBerryBushBlock; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.craftbukkit.v.block.CraftBlock; @@ -21,10 +21,8 @@ import org.bukkit.event.player.PlayerHarvestBlockEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Collections; @@ -44,16 +42,18 @@ public class SweetBerryBushBlockMixin { return ((DamageSourceBridge) instance.sweetBerryBush()).bridge$directBlock(CraftBlock.at(level, blockPos)); } - @Eject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/SweetBerryBushBlock;popResource(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;)V")) - private void arclight$playerHarvest(Level worldIn, BlockPos pos, ItemStack stack, CallbackInfoReturnable cir, - BlockState state, Level worldIn1, BlockPos pos1, Player player, InteractionHand hand) { - PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(worldIn, pos, player, hand, Collections.singletonList(stack)); + @Decorate(method = "useWithoutItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/SweetBerryBushBlock;popResource(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;)V")) + private void arclight$playerHarvest(Level worldIn, BlockPos pos, ItemStack stack, + BlockState state, Level worldIn1, BlockPos pos1, Player player) throws Throwable { + PlayerHarvestBlockEvent event = CraftEventFactory.callPlayerHarvestBlockEvent(worldIn, pos, player, InteractionHand.MAIN_HAND, Collections.singletonList(stack)); if (!event.isCancelled()) { for (org.bukkit.inventory.ItemStack itemStack : event.getItemsHarvested()) { - Block.popResource(worldIn, pos, CraftItemStack.asNMSCopy(itemStack)); + DecorationOps.callsite().invoke(worldIn, pos, CraftItemStack.asNMSCopy(itemStack)); } } else { - cir.setReturnValue(InteractionResult.SUCCESS); + DecorationOps.cancel().invoke(InteractionResult.SUCCESS); + return; } + DecorationOps.blackhole().invoke(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java index cd76615a3..399489b4b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java @@ -3,10 +3,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; @@ -49,10 +50,10 @@ public abstract class TntBlockMixin extends BlockMixin { } } - @Inject(method = "use", require = 0, cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/TntBlock;explode(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$player(BlockState p_57450_, Level level, BlockPos pos, Player player, InteractionHand p_57454_, BlockHitResult p_57455_, CallbackInfoReturnable cir) { - if (!CraftEventFactory.callTNTPrimeEvent(level, pos, TNTPrimeEvent.PrimeCause.PLAYER, player, null)) { - cir.setReturnValue(InteractionResult.CONSUME); + @Inject(method = "useItemOn", require = 0, cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/TntBlock;explode(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$player(ItemStack itemStack, BlockState blockState, Level level, BlockPos blockPos, Player player, InteractionHand interactionHand, BlockHitResult blockHitResult, CallbackInfoReturnable cir) { + if (!CraftEventFactory.callTNTPrimeEvent(level, blockPos, TNTPrimeEvent.PrimeCause.PLAYER, player, null)) { + cir.setReturnValue(ItemInteractionResult.CONSUME); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/WitherSkullBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/WitherSkullBlockMixin.java index 3ee5c82d7..b3e573c92 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/WitherSkullBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/WitherSkullBlockMixin.java @@ -1,66 +1,34 @@ package io.izzel.arclight.common.mixin.core.world.level.block; -import io.izzel.arclight.api.ArclightPlatform; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.mod.mixins.annotation.OnlyInPlatform; -import net.minecraft.core.BlockPos; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.boss.wither.WitherBoss; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.CarvedPumpkinBlock; import net.minecraft.world.level.block.WitherSkullBlock; -import net.minecraft.world.level.block.entity.SkullBlockEntity; -import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.pattern.BlockPattern; import org.bukkit.event.entity.CreatureSpawnEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(WitherSkullBlock.class) public class WitherSkullBlockMixin { - @Redirect(method = "checkSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/CarvedPumpkinBlock;clearPatternBlocks(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;)V")) + @Redirect(method = "checkSpawn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/SkullBlockEntity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/CarvedPumpkinBlock;clearPatternBlocks(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/pattern/BlockPattern$BlockPatternMatch;)V")) private static void arclight$clearLater(Level p_249604_, BlockPattern.BlockPatternMatch p_251190_) { } - @Mixin(WitherSkullBlock.class) - @OnlyInPlatform({ArclightPlatform.FORGE, ArclightPlatform.NEOFORGE}) - public static class ForgeLike { - - @Inject(method = "checkSpawn", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;makeInvulnerable()V")) - private static void arclight$addEntity(Level level, BlockPos pos, SkullBlockEntity p_58258_, CallbackInfo ci, - BlockState state, boolean flag, BlockPattern.BlockPatternMatch patternMatch, WitherBoss witherBoss) { - ((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); - if (!level.addFreshEntity(witherBoss)) { - ci.cancel(); - } else { - CarvedPumpkinBlock.clearPatternBlocks(level, patternMatch); - } + @Decorate(method = "checkSpawn(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/SkullBlockEntity;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) + private static boolean arclight$muteSpawn(Level instance, Entity entity, @Local(ordinal = -1) BlockPattern.BlockPatternMatch patternMatch) throws Throwable { + ((WorldBridge) instance).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); + if (!(boolean) DecorationOps.callsite().invoke(instance, entity)) { + return (boolean) DecorationOps.cancel().invoke(); + } else { + CarvedPumpkinBlock.clearPatternBlocks(instance, patternMatch); } - } - - @Mixin(WitherSkullBlock.class) - @OnlyInPlatform({ArclightPlatform.VANILLA, ArclightPlatform.FABRIC}) - public static class VanillaLike { - - @Inject(method = "checkSpawn", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/entity/boss/wither/WitherBoss;makeInvulnerable()V")) - private static void arclight$addEntity(Level level, BlockPos pos, SkullBlockEntity p_58258_, CallbackInfo ci, - boolean flag, BlockPattern.BlockPatternMatch patternMatch, WitherBoss witherBoss) { - ((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); - if (!level.addFreshEntity(witherBoss)) { - ci.cancel(); - } else { - CarvedPumpkinBlock.clearPatternBlocks(level, patternMatch); - } - } - } - - @Redirect(method = "checkSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private static boolean arclight$muteSpawn(Level instance, Entity entity) { return true; } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java index 077531d35..bef527cf0 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin.java @@ -3,7 +3,10 @@ import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.tileentity.AbstractFurnaceTileEntityBridge; import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeHolderBridge; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; @@ -26,6 +29,7 @@ import org.bukkit.entity.HumanEntity; import org.bukkit.event.inventory.FurnaceBurnEvent; import org.bukkit.event.inventory.FurnaceExtractEvent; +import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.bukkit.event.inventory.FurnaceStartSmeltEvent; import org.bukkit.inventory.CookingRecipe; import org.bukkit.inventory.InventoryHolder; @@ -33,11 +37,8 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.ArrayList; import java.util.List; @@ -56,24 +57,48 @@ public abstract class AbstractFurnaceBlockEntityMixin extends LockableBlockEntit public List transaction = new ArrayList<>(); private int maxStack = MAX_STACK; - @Eject(method = "serverTick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;isLit()Z"), + @SuppressWarnings("unchecked") + @Decorate(method = "burn", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/core/NonNullList;get(I)Ljava/lang/Object;")) + private static E arclight$furnaceSmelt(NonNullList instance, int i, @Local(ordinal = -1) ItemStack itemStack2, @Local(ordinal = -2) ItemStack itemStack1) throws Throwable { + var blockEntity = ArclightCaptures.getTickingBlockEntity(); + if (blockEntity != null) { + CraftItemStack source = CraftItemStack.asCraftMirror(itemStack1); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemStack2); + + FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()), source, result); + Bukkit.getPluginManager().callEvent(furnaceSmeltEvent); + + if (furnaceSmeltEvent.isCancelled()) { + return (E) DecorationOps.cancel().invoke(false); + } + + result = furnaceSmeltEvent.getResult(); + itemStack2 = CraftItemStack.asNMSCopy(result); + if (itemStack2.isEmpty()) { + itemStack1.shrink(1); + return (E) DecorationOps.cancel().invoke(true); + } + } + return (E) DecorationOps.callsite().invoke(instance, i); + } + + @Decorate(method = "serverTick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;isLit()Z"), slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;litDuration:I"))) - private static boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace, CallbackInfo ci) { + private static boolean arclight$setBurnTime(AbstractFurnaceBlockEntity furnace) throws Throwable { ItemStack itemStack = furnace.getItem(1); CraftItemStack fuel = CraftItemStack.asCraftMirror(itemStack); - FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(furnace.level, furnace.getBlockPos()), fuel, ((AbstractFurnaceTileEntityBridge) furnace).bridge$getBurnDuration(itemStack)); + FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(furnace.level, furnace.getBlockPos()), fuel, furnace.litTime); Bukkit.getPluginManager().callEvent(furnaceBurnEvent); - if (furnaceBurnEvent.isCancelled()) { - ci.cancel(); - return false; + return (boolean) DecorationOps.cancel().invoke(); } - return ((AbstractFurnaceTileEntityBridge) furnace).bridge$isLit() && furnaceBurnEvent.isBurning(); + furnace.litTime = furnaceBurnEvent.getBurnTime(); + return (boolean) DecorationOps.callsite().invoke(furnace) && furnaceBurnEvent.isBurning(); } - @Inject(method = "serverTick", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingProgress:I")) - private static void arclight$startSmelt(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity furnace, CallbackInfo ci, - boolean flag, boolean flag1, ItemStack stack, boolean flag2, boolean flag3, RecipeHolder recipe) { + @Decorate(method = "serverTick", inject = true, at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;cookingProgress:I")) + private static void arclight$startSmelt(Level level, BlockPos pos, BlockState state, AbstractFurnaceBlockEntity furnace, + @Local(ordinal = -1) RecipeHolder recipe) { if (recipe != null && furnace.cookingProgress == 0) { CraftItemStack source = CraftItemStack.asCraftMirror(furnace.getItem(0)); if (((RecipeHolderBridge) (Object) recipe).bridge$toBukkitRecipe() instanceof CookingRecipe cookingRecipe) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeaconTileEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeaconTileEntityMixin.java index eab27e461..f58a56dd9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeaconTileEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeaconTileEntityMixin.java @@ -1,32 +1,33 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; import io.izzel.arclight.common.bridge.core.tileentity.BeaconTileEntityBridge; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.level.block.entity.BeaconBlockEntity; import org.bukkit.craftbukkit.v.potion.CraftPotionUtil; import org.bukkit.potion.PotionEffect; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import javax.annotation.Nullable; - @Mixin(BeaconBlockEntity.class) public abstract class BeaconTileEntityMixin implements BeaconTileEntityBridge { // @formatter:off - @Shadow @Nullable public MobEffect primaryPower; @Shadow public int levels; - @Shadow @Nullable public MobEffect secondaryPower; + @Shadow @Nullable public Holder primaryPower; + @Shadow @Nullable public Holder secondaryPower; // @formatter:on - @Inject(method = "load", at = @At("RETURN")) - public void arclight$level(CompoundTag compound, CallbackInfo ci) { - this.levels = compound.getInt("Levels"); + @Inject(method = "loadAdditional", at = @At("RETURN")) + public void arclight$level(CompoundTag compoundTag, HolderLookup.Provider provider, CallbackInfo ci) { + this.levels = compoundTag.getInt("Levels"); } public PotionEffect getPrimaryEffect() { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeehiveBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeehiveBlockEntityMixin.java index 98009a57c..908f544d6 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeehiveBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BeehiveBlockEntityMixin.java @@ -1,14 +1,11 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; import com.google.common.collect.Lists; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; -import net.minecraft.tags.EntityTypeTags; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.animal.Bee; import net.minecraft.world.level.Level; @@ -16,7 +13,6 @@ import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityEnterBlockEvent; import org.bukkit.event.entity.EntityRemoveEvent; import org.bukkit.event.entity.EntityTargetEvent; @@ -38,7 +34,7 @@ public abstract class BeehiveBlockEntityMixin extends BlockEntityMixin { // @formatter:off @Shadow @Final private List stored; @Shadow @Nullable public BlockPos savedFlowerPos; - @Shadow private static boolean releaseOccupant(Level p_155137_, BlockPos p_155138_, BlockState p_155139_, BeehiveBlockEntity.BeeData p_155140_, @org.jetbrains.annotations.Nullable List p_155141_, BeehiveBlockEntity.BeeReleaseStatus p_155142_, @org.jetbrains.annotations.Nullable BlockPos p_155143_) { return false; } + @Shadow protected static boolean releaseOccupant(Level arg, BlockPos arg2, BlockState arg3, BeehiveBlockEntity.Occupant arg4, @org.jetbrains.annotations.Nullable List list, BeehiveBlockEntity.BeeReleaseStatus arg5, @org.jetbrains.annotations.Nullable BlockPos arg6) { return false; } // @formatter:on public int maxBees = 3; @@ -64,15 +60,15 @@ public List releaseBees(BlockState blockState, BeehiveBlockEntity.BeeRel return list; } - @Redirect(method = "addOccupantWithPresetTicks", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;size()I")) + @Redirect(method = "addOccupant", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/List;size()I")) private int arclight$maxBee(List list) { return list.size() < this.maxBees ? 1 : 3; } - @Inject(method = "addOccupantWithPresetTicks(Lnet/minecraft/world/entity/Entity;ZI)V", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;stopRiding()V")) - private void arclight$beeEnterBlock(Entity entity, boolean p_226962_2_, int p_226962_3_, CallbackInfo ci) { + @Inject(method = "addOccupant", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;stopRiding()V")) + private void arclight$beeEnterBlock(Entity entity, CallbackInfo ci) { if (this.level != null) { - EntityEnterBlockEvent event = new EntityEnterBlockEvent(((EntityBridge) entity).bridge$getBukkitEntity(), CraftBlock.at(this.level, this.worldPosition)); + EntityEnterBlockEvent event = new EntityEnterBlockEvent(entity.bridge$getBukkitEntity(), CraftBlock.at(this.level, this.worldPosition)); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { if (entity instanceof Bee) { @@ -83,15 +79,15 @@ public List releaseBees(BlockState blockState, BeehiveBlockEntity.BeeRel } } - @Inject(method = "addOccupantWithPresetTicks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;discard()V")) - private void arclight$enterBlockCause(Entity entity, boolean bl, int i, CallbackInfo ci) { + @Inject(method = "addOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;discard()V")) + private void arclight$enterBlockCause(Entity entity, CallbackInfo ci) { entity.bridge().bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.ENTER_BLOCK); } private static boolean releaseBee(Level world, BlockPos pos, BlockState state, BeehiveBlockEntity.BeeData beeData, @Nullable List list, BeehiveBlockEntity.BeeReleaseStatus status, @Nullable BlockPos pos1, boolean force) { arclight$force = force; try { - return releaseOccupant(world, pos, state, beeData, list, status, pos1); + return releaseOccupant(world, pos, state, beeData.toOccupant(), list, status, pos1); } finally { arclight$force = false; } @@ -104,34 +100,15 @@ private static boolean releaseBee(Level world, BlockPos pos, BlockState state, B return !arclight$force && world.isNight(); } - @Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getType()Lnet/minecraft/world/entity/EntityType;")) - private static EntityType arclight$spawnFirst(Entity entity, Level level) { - EntityType type = entity.getType(); - if (type.is(EntityTypeTags.BEEHIVE_INHABITORS)) { - ((WorldBridge) level).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BEEHIVE); - if (!level.addFreshEntity(entity)) { - return EntityType.ITEM_FRAME; - } else { - return type; - } - } - return type; - } - - @Redirect(method = "releaseOccupant", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;addFreshEntity(Lnet/minecraft/world/entity/Entity;)Z")) - private static boolean arclight$addedBefore(Level world, Entity entityIn) { - return true; - } - - @Inject(method = "load", at = @At("RETURN")) - private void arclight$readMax(CompoundTag compound, CallbackInfo ci) { + @Inject(method = "loadAdditional", at = @At("RETURN")) + private void arclight$readMax(CompoundTag compound, HolderLookup.Provider provider, CallbackInfo ci) { if (compound.contains("Bukkit.MaxEntities")) { this.maxBees = compound.getInt("Bukkit.MaxEntities"); } } @Inject(method = "saveAdditional", at = @At("RETURN")) - private void arclight$writeMax(CompoundTag compound, CallbackInfo ci) { + private void arclight$writeMax(CompoundTag compound, HolderLookup.Provider provider, CallbackInfo ci) { compound.putInt("Bukkit.MaxEntities", this.maxBees); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BellBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BellBlockEntityMixin.java index 41bc0e034..0adc8f704 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BellBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BellBlockEntityMixin.java @@ -18,7 +18,7 @@ public class BellBlockEntityMixin { @Redirect(method = "makeRaidersGlow", at = @At(value = "INVOKE", remap = false, target = "Ljava/util/stream/Stream;forEach(Ljava/util/function/Consumer;)V")) private static void arclight$bellResonate(Stream instance, Consumer consumer, Level level, BlockPos pos) { - var list = instance.map(it -> (org.bukkit.entity.LivingEntity) ((EntityBridge) it).bridge$getBukkitEntity()).toList(); + var list = instance.map(it -> (org.bukkit.entity.LivingEntity) it.bridge$getBukkitEntity()).toList(); CraftEventFactory.handleBellResonateEvent(level, pos, list).forEach(consumer); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BlockEntityMixin.java index 864bac1d1..b818ca64a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BlockEntityMixin.java @@ -2,6 +2,11 @@ import io.izzel.arclight.common.bridge.core.tileentity.TileEntityBridge; import net.minecraft.core.BlockPos; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponentMap; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -18,8 +23,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; +import java.util.Set; @Mixin(BlockEntity.class) public abstract class BlockEntityMixin implements TileEntityBridge { @@ -31,17 +38,17 @@ public abstract class BlockEntityMixin implements TileEntityBridge { @Shadow @Nullable public Level level; @Shadow @Final protected BlockPos worldPosition; @Shadow public abstract BlockState getBlockState(); - @Shadow public abstract void setChanged(); @Shadow public BlockPos getBlockPos() { return null; } - @Shadow public abstract boolean onlyOpCanSetNbt(); @Shadow protected static void setChanged(Level p_155233_, BlockPos p_155234_, BlockState p_155235_) { } @Shadow public abstract BlockEntityType getType(); - @Shadow public void load(CompoundTag p_155245_) {} @Shadow public void setLevel(Level p_155231_) {} // @formatter:on - @Inject(method = "load", at = @At("RETURN")) - public void arclight$loadPersistent(CompoundTag compound, CallbackInfo ci) { + @Shadow + public abstract void applyComponents(DataComponentMap dataComponentMap, DataComponentPatch dataComponentPatch); + + @Inject(method = "loadAdditional", at = @At("RETURN")) + public void arclight$loadPersistent(CompoundTag compound, HolderLookup.Provider provider, CallbackInfo ci) { this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); CompoundTag persistentDataTag = compound.getCompound("PublicBukkitValues"); @@ -57,6 +64,23 @@ public abstract class BlockEntityMixin implements TileEntityBridge { } } + private transient Set> arclight$appliedSet; + + public final Set> applyComponentsSet(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) { + try { + this.applyComponents(datacomponentmap, datacomponentpatch); + return arclight$appliedSet; + } finally { + arclight$appliedSet = null; + } + } + + @Inject(method = "applyComponents", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) + private void arclight$captureSet(DataComponentMap dataComponentMap, DataComponentPatch dataComponentPatch, CallbackInfo ci, Set> set) { + set.remove(DataComponents.ENTITY_DATA); + arclight$appliedSet = set; + } + public InventoryHolder getOwner() { if (this.level == null) return null; org.bukkit.block.Block block = CraftBlock.at(this.level, this.worldPosition); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin.java index f7c69bb66..fda5cf333 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin.java @@ -1,14 +1,14 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; import io.izzel.arclight.common.bridge.core.tileentity.TileEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; -import net.minecraft.world.Containers; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.alchemy.PotionBrewing; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BrewingStandBlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -20,11 +20,9 @@ import org.bukkit.event.block.BrewingStartEvent; import org.bukkit.event.inventory.BrewEvent; import org.bukkit.event.inventory.BrewingStandFuelEvent; -import org.bukkit.inventory.BrewerInventory; import org.bukkit.inventory.InventoryHolder; import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -43,19 +41,21 @@ public abstract class BrewingStandBlockEntityMixin extends LockableBlockEntityMi public List transaction = new ArrayList<>(); private int maxStack = MAX_STACK; - @Eject(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) - private static void arclight$brewFuel(ItemStack stack, int count, CallbackInfo ci, Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity entity) { + @Decorate(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) + private static void arclight$brewFuel(ItemStack stack, int count, Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity entity) throws Throwable { BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(level, pos), CraftItemStack.asCraftMirror(stack), 20); Bukkit.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { - ci.cancel(); + DecorationOps.cancel().invoke(); + return; } else { entity.fuel = event.getFuelPower(); if (entity.fuel > 0 && event.isConsuming()) { - stack.shrink(count); + DecorationOps.callsite().invoke(stack, count); } } + DecorationOps.blackhole().invoke(); } @Inject(method = "serverTick", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/level/block/entity/BrewingStandBlockEntity;ingredient:Lnet/minecraft/world/item/Item;")) @@ -65,52 +65,38 @@ public abstract class BrewingStandBlockEntityMixin extends LockableBlockEntityMi entity.brewTime = event.getTotalBrewTime(); } - /** - * @author Izzel_Aliz - * @reason - */ - @Overwrite - private static void doBrew(Level level, BlockPos pos, NonNullList stacks) { + @Decorate(method = "doBrew", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;potionBrewing()Lnet/minecraft/world/item/alchemy/PotionBrewing;")) + private static PotionBrewing arclight$brewEvent(Level instance, Level level, BlockPos pos, NonNullList stacks, + @Local(allocate = "brewResults") List brewResults) throws Throwable { + var potionBrewing = (PotionBrewing) DecorationOps.callsite().invoke(instance); + BrewingStandBlockEntity entity = ArclightCaptures.getTickingBlockEntity(); + InventoryHolder owner = entity == null ? null : ((TileEntityBridge) entity).bridge$getOwner(); ItemStack ing = stacks.get(3); - - List brewResults = new ArrayList<>(3); + brewResults = new ArrayList<>(3); for (int i = 0; i < 3; ++i) { - var input = stacks.get(i); - var output = ((WorldBridge) level).bridge$forge$potionBrewMix(input, ing); - brewResults.add(i, CraftItemStack.asCraftMirror(output.isEmpty() ? input : output)); + brewResults.add(i, CraftItemStack.asCraftMirror(potionBrewing.mix(ing, stacks.get(i)))); } - BrewingStandBlockEntity entity = ArclightCaptures.getTickingBlockEntity(); - InventoryHolder owner = entity == null ? null : ((TileEntityBridge) entity).bridge$getOwner(); + if (owner != null) { - BrewEvent event = new BrewEvent(CraftBlock.at(level, pos), (BrewerInventory) owner.getInventory(), brewResults, entity.fuel); - Bukkit.getPluginManager().callEvent(event); + BrewEvent event = new BrewEvent(CraftBlock.at(level, pos), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, entity.fuel); + org.bukkit.Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - return; - } else { - for (int i = 0; i < 3; ++i) { - if (i < brewResults.size()) { - stacks.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); - } else { - stacks.set(i, ItemStack.EMPTY); - } - } + return (PotionBrewing) DecorationOps.cancel().invoke(); } } + return potionBrewing; + } - // BrewingRecipeRegistry.brewPotions(stacks, ing, SLOTS_FOR_SIDES); - ((WorldBridge) level).bridge$forge$onPotionBrewed(stacks); - if (((ItemStackBridge) (Object) ing).bridge$forge$hasCraftingRemainingItem()) { - ItemStack containerItem = ((ItemStackBridge) (Object) ing).bridge$forge$getCraftingRemainingItem(); - ing.shrink(1); - if (ing.isEmpty()) { - ing = containerItem; - } else { - Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), containerItem); - } - } else ing.shrink(1); - - stacks.set(3, ing); - level.levelEvent(1035, pos, 0); + @SuppressWarnings("unchecked") + @Decorate(method = "doBrew", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/core/NonNullList;set(ILjava/lang/Object;)Ljava/lang/Object;")) + private static E arclight$applyResults(NonNullList instance, int i, E object, + @Local(allocate = "brewResults") List brewResults) throws Throwable { + if (i < brewResults.size()) { + object = (E) CraftItemStack.asNMSCopy(brewResults.get(i)); + } else { + object = (E) ItemStack.EMPTY; + } + return (E) DecorationOps.callsite().invoke(instance, i, object); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrushableBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrushableBlockEntityMixin.java index 1d7308854..d084db694 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrushableBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/BrushableBlockEntityMixin.java @@ -1,6 +1,5 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; @@ -11,9 +10,7 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Collections; @@ -26,9 +23,4 @@ public abstract class BrushableBlockEntityMixin extends BlockEntityMixin { CraftEventFactory.handleBlockDropItemEvent(block, block.getState(), (ServerPlayer) player, Collections.singletonList((ItemEntity) entity)); return true; } - - @Inject(method = "load", at = @At("HEAD")) - private void arclight$load(CompoundTag p_277597_, CallbackInfo ci) { - super.load(p_277597_); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java index 4dbdd408d..38a0fdf85 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CampfireBlockEntityMixin.java @@ -1,19 +1,17 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeHolderBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.world.Container; -import net.minecraft.world.Containers; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CampfireCookingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.CampfireBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEvent; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.inventory.CraftItemStack; @@ -22,7 +20,6 @@ import org.bukkit.inventory.CampfireRecipe; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -35,61 +32,32 @@ public abstract class CampfireBlockEntityMixin extends BlockEntityMixin { // @formatter:off - @Shadow @Final private RecipeManager.CachedCheck quickCheck; @Shadow public abstract Optional> getCookableRecipe(ItemStack p_59052_); @Shadow @Final public int[] cookingTime; // @formatter:on - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public static void cookTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity entity) { - boolean flag = false; + @Decorate(method = "cookTick", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/Containers;dropItemStack(Lnet/minecraft/world/level/Level;DDDLnet/minecraft/world/item/ItemStack;)V")) + private static void arclight$cookEvent(Level level, BlockPos blockPos, BlockState blockState, CampfireBlockEntity campfireBlockEntity, + @Local(ordinal = 0) ItemStack sourceStack, @Local(ordinal = -1) ItemStack resultStack) throws Throwable { + CraftItemStack source = CraftItemStack.asCraftMirror(sourceStack); + org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(resultStack); - for (int i = 0; i < entity.getItems().size(); ++i) { - ItemStack itemstack = entity.getItems().get(i); - if (!itemstack.isEmpty()) { - flag = true; - entity.cookingProgress[i]++; - if (entity.cookingProgress[i] >= entity.cookingTime[i]) { - Container container = new SimpleContainer(itemstack); - ItemStack itemstack1 = ((CampfireBlockEntityMixin) (Object) entity).quickCheck.getRecipeFor(container, level).map((p_155305_) -> { - return p_155305_.value().assemble(container, level.registryAccess()); - }).orElse(itemstack); + BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, blockPos), source, result); + Bukkit.getPluginManager().callEvent(blockCookEvent); - if (!itemstack1.isItemEnabled(level.enabledFeatures())) continue; - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - - BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(level, pos), source, result); - Bukkit.getPluginManager().callEvent(blockCookEvent); - - if (blockCookEvent.isCancelled()) { - return; - } - - result = blockCookEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - - Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemstack1); - entity.getItems().set(i, ItemStack.EMPTY); - level.sendBlockUpdated(pos, state, state, 3); - level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state)); - } - } - } - - if (flag) { - setChanged(level, pos, state); + if (blockCookEvent.isCancelled()) { + DecorationOps.cancel().invoke(); + return; } + result = blockCookEvent.getResult(); + resultStack = CraftItemStack.asNMSCopy(result); + DecorationOps.blackhole().invoke(resultStack); } @Inject(method = "placeFood", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/entity/CampfireBlockEntity;cookingProgress:[I")) - private void arclight$cookStart(Entity p_238285_, ItemStack stack, int p_238287_, CallbackInfoReturnable cir, int i) { + private void arclight$cookStart(LivingEntity p_238285_, ItemStack stack, int p_238287_, CallbackInfoReturnable cir, int i) { var event = new CampfireStartEvent(CraftBlock.at(this.level, this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) ((RecipeHolderBridge) (Object) getCookableRecipe(stack).get()).bridge$toBukkitRecipe()); Bukkit.getPluginManager().callEvent(event); this.cookingTime[i] = event.getTotalCookTime(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/ChiseledBookShelfBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/ChiseledBookShelfBlockEntityMixin.java index 1be1a5605..ddb2c9297 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/ChiseledBookShelfBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/ChiseledBookShelfBlockEntityMixin.java @@ -4,7 +4,6 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mod.util.DistValidate; import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.ChiseledBookShelfBlockEntity; @@ -76,9 +75,4 @@ public Location getLocation() { ci.cancel(); } } - - @Inject(method = "load", at = @At("HEAD")) - private void arclight$load(CompoundTag p_277597_, CallbackInfo ci) { - super.load(p_277597_); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CommandBlockLogicMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CommandBlockLogicMixin.java index 571604f1f..ea0b7646f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CommandBlockLogicMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/CommandBlockLogicMixin.java @@ -4,25 +4,17 @@ import io.izzel.arclight.common.bridge.core.command.CommandSourceBridge; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.network.chat.Component; import net.minecraft.world.level.BaseCommandBlock; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.event.server.ServerCommandEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(BaseCommandBlock.class) public class CommandBlockLogicMixin { - // @formatter:off - @Shadow private Component name; - // @formatter:on - @Redirect(method = "performCommand", at = @At(value = "INVOKE", target = "Lnet/minecraft/commands/Commands;performPrefixedCommand(Lnet/minecraft/commands/CommandSourceStack;Ljava/lang/String;)V")) private void arclight$serverCommand(Commands commands, CommandSourceStack sender, String command) { Joiner joiner = Joiner.on(" "); @@ -55,11 +47,4 @@ public class CommandBlockLogicMixin { commands.performPrefixedCommand(sender, joiner.join(args)); } - - @Inject(method = "setName", at = @At("RETURN")) - public void arclight$setName(Component nameIn, CallbackInfo ci) { - if (this.name == null) { - this.name = Component.literal("@"); - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/EndGatewayBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/EndGatewayBlockEntityMixin.java index e1636bb28..4b1e28174 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/EndGatewayBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/EndGatewayBlockEntityMixin.java @@ -1,84 +1,10 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; -import io.izzel.arclight.api.ArclightPlatform; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; import io.izzel.arclight.common.bridge.core.tileentity.EndGatewayBlockEntityBridge; -import io.izzel.arclight.common.mod.mixins.annotation.OnlyInPlatform; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v.entity.CraftPlayer; -import org.bukkit.event.entity.EntityRemoveEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(TheEndGatewayBlockEntity.class) public abstract class EndGatewayBlockEntityMixin extends BlockEntityMixin implements EndGatewayBlockEntityBridge { - // @formatter:off - @Shadow private static void triggerCooldown(Level p_155850_, BlockPos p_155851_, BlockState p_155852_, TheEndGatewayBlockEntity p_155853_) { } - // @formatter:on - - @Inject(method = "teleportEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPortalCooldown()V")) - private static void arclight$teleportCause(Level level, BlockPos pos, BlockState state, Entity entityIn, TheEndGatewayBlockEntity entity, CallbackInfo ci) { - entityIn.bridge().bridge$pushEntityRemoveCause(EntityRemoveEvent.Cause.HIT); - } - - @Override - public void bridge$playerTeleportEvent(Level level, BlockPos pos, BlockState state, Entity entityIn, BlockPos dest) { - CraftPlayer player = ((ServerPlayerEntityBridge) entityIn).bridge$getBukkitEntity(); - Location location = new Location(level.bridge$getWorld(), dest.getX() + 0.5D, dest.getY() + 0.5D, dest.getZ() + 0.5D); - location.setPitch(player.getLocation().getPitch()); - location.setYaw(player.getLocation().getYaw()); - - PlayerTeleportEvent event = new PlayerTeleportEvent(player, player.getLocation(), location, PlayerTeleportEvent.TeleportCause.END_GATEWAY); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - - entityIn.setPortalCooldown(); - ((ServerPlayNetHandlerBridge) (((ServerPlayer) entityIn)).connection).bridge$teleport(event.getTo()); - triggerCooldown(level, pos, state, (TheEndGatewayBlockEntity) (Object) this); - } - - @Mixin(TheEndGatewayBlockEntity.class) - @OnlyInPlatform({ArclightPlatform.FABRIC, ArclightPlatform.VANILLA}) - public static class VanillaLike { - - @Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPortalCooldown()V")) - private static void arclight$portal(Level level, BlockPos pos, BlockState state, Entity entityIn, TheEndGatewayBlockEntity entity, CallbackInfo ci, - BlockPos dest) { - if (entityIn instanceof ServerPlayer) { - ((EndGatewayBlockEntityBridge) entity).bridge$playerTeleportEvent(level, pos, state, entityIn, dest); - ci.cancel(); - } - } - } - - @Mixin(TheEndGatewayBlockEntity.class) - @OnlyInPlatform({ArclightPlatform.FORGE, ArclightPlatform.NEOFORGE}) - public static class ForgeLike { - - @Inject(method = "teleportEntity", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;setPortalCooldown()V")) - private static void arclight$portal(Level level, BlockPos pos, BlockState state, Entity entityIn, TheEndGatewayBlockEntity entity, CallbackInfo ci, - ServerLevel serverLevel, BlockPos dest) { - if (entityIn instanceof ServerPlayer) { - ((EndGatewayBlockEntityBridge) entity).bridge$playerTeleportEvent(level, pos, state, entityIn, dest); - ci.cancel(); - } - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java index 48fb5b476..4ff53ed7a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/HopperBlockEntityMixin.java @@ -138,16 +138,16 @@ private static Container runHopperInventorySearchEvent(Container inventory, Craf return (craftInventory != null) ? craftInventory.getInventory() : null; } - @Inject(method = "getAttachedContainer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) - private static void arclight$searchTo(Level level, BlockPos pos, BlockState p_155595_, CallbackInfoReturnable cir, Direction direction) { + @Inject(method = "getAttachedContainer", cancellable = true, at = @At("RETURN")) + private static void arclight$searchTo(Level level, BlockPos pos, HopperBlockEntity hopperBlockEntity, CallbackInfoReturnable cir) { var container = cir.getReturnValue(); var hopper = CraftBlock.at(level, pos); - var searchBlock = CraftBlock.at(level, pos.relative(direction)); + var searchBlock = CraftBlock.at(level, pos.relative(hopperBlockEntity.facing)); cir.setReturnValue(runHopperInventorySearchEvent(container, hopper, searchBlock, HopperInventorySearchEvent.ContainerType.DESTINATION)); } - @Inject(method = "getSourceContainer", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) - private static void arclight$searchFrom(Level level, Hopper hopper, CallbackInfoReturnable cir) { + @Inject(method = "getSourceContainer", cancellable = true, at = @At("RETURN")) + private static void arclight$searchFrom(Level level, Hopper hopper, BlockPos blockposition, BlockState iblockdata, CallbackInfoReturnable cir) { var container = cir.getReturnValue(); var blockPos = BlockPos.containing(hopper.getLevelX(), hopper.getLevelY(), hopper.getLevelZ()); var hopperBlock = CraftBlock.at(level, blockPos); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/JukeboxBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/JukeboxBlockEntityMixin.java index 5823c9695..9afc7a624 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/JukeboxBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/JukeboxBlockEntityMixin.java @@ -1,17 +1,18 @@ package io.izzel.arclight.common.mixin.core.world.level.block.entity; import io.izzel.arclight.common.bridge.core.inventory.IInventoryBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mod.util.DistValidate; import net.minecraft.core.BlockPos; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.JukeboxSongPlayer; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.JukeboxBlockEntity; import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.entity.HumanEntity; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -24,7 +25,11 @@ @Mixin(JukeboxBlockEntity.class) public abstract class JukeboxBlockEntityMixin extends BlockEntityMixin implements IInventoryBridge, Container { + // @formatter:off @Shadow private ItemStack item; + @Shadow @Final private JukeboxSongPlayer jukeboxSongPlayer; + @Shadow public abstract void setSongItemWithoutPlaying(ItemStack arg); + // @formatter:on public List transaction = new ArrayList<>(); private int maxStack = MAX_STACK; @@ -63,13 +68,21 @@ public void setMaxStackSize(int size) { @Override public Location getLocation() { if (!DistValidate.isValid(level)) return null; - return new Location(((WorldBridge) level).bridge$getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); + return new Location(level.bridge$getWorld(), worldPosition.getX(), worldPosition.getY(), worldPosition.getZ()); } - @Redirect(method = "setRecordWithoutPlaying", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V")) + @Redirect(method = "setSongItemWithoutPlaying", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;updateNeighborsAt(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;)V")) private void arclight$levelNullCheck(Level instance, BlockPos p_46673_, Block p_46674_) { if (instance != null) { instance.updateNeighborsAt(p_46673_, p_46674_); } } + + public void setSongItemWithoutPlaying(ItemStack itemstack, long ticksSinceSongStarted) { + this.jukeboxSongPlayer.song = null; // CraftBukkit - reset + this.setSongItemWithoutPlaying(itemstack); + if (this.jukeboxSongPlayer.song != null) { + this.jukeboxSongPlayer.ticksSinceSongStarted = ticksSinceSongStarted; + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/SculkCatalystBlockEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/SculkCatalystBlockEntityMixin.java index 1431b74a8..6eb4e2466 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/SculkCatalystBlockEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/SculkCatalystBlockEntityMixin.java @@ -34,9 +34,4 @@ public void setLevel(Level p_155231_) { private static void arclight$resetSource(Level p_222780_, BlockPos p_222781_, BlockState p_222782_, SculkCatalystBlockEntity blockEntity, CallbackInfo ci) { CraftEventFactory.sourceBlockOverride = null; } - - @Inject(method = "load", at = @At("HEAD")) - private void arclight$load(CompoundTag p_277597_, CallbackInfo ci) { - super.load(p_277597_); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/trailspawner/TrialSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/trailspawner/TrialSpawnerMixin.java new file mode 100644 index 000000000..e6f50e655 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/entity/trailspawner/TrialSpawnerMixin.java @@ -0,0 +1,23 @@ +package io.izzel.arclight.common.mixin.core.world.level.block.entity.trailspawner; + +import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Optional; +import java.util.UUID; + +@Mixin(TrialSpawner.class) +public class TrialSpawnerMixin { + + @Inject(method = "spawnMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tryAddFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)Z")) + private void arclight$cause(ServerLevel serverLevel, BlockPos blockPos, CallbackInfoReturnable> cir) { + ((WorldBridge) serverLevel).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.TRIAL_SPAWNER); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/state/BlockBehaviourMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/state/BlockBehaviourMixin.java index 5cc66bc77..87cecd0c9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/state/BlockBehaviourMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/state/BlockBehaviourMixin.java @@ -2,24 +2,21 @@ import io.izzel.arclight.common.bridge.core.world.ExplosionBridge; import io.izzel.arclight.common.bridge.core.world.level.block.state.BlockBehaviourBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Explosion; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.storage.loot.LootParams; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; import java.util.function.BiConsumer; @@ -27,33 +24,14 @@ public abstract class BlockBehaviourMixin implements BlockBehaviourBridge { // @formatter:off - @Shadow public BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { return null; } + @Shadow protected BlockState updateShape(BlockState stateIn, Direction facing, BlockState facingState, LevelAccessor worldIn, BlockPos currentPos, BlockPos facingPos) { return null; } // @formatter:on - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @Deprecated - public void onExplosionHit(BlockState p_310712_, Level p_311693_, BlockPos p_311490_, Explosion p_312709_, BiConsumer p_311277_) { - if (!p_310712_.isAir() && p_312709_.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) { - Block block = p_310712_.getBlock(); - boolean flag = p_312709_.getIndirectSourceEntity() instanceof Player; - if (this.bridge$forge$canDropFromExplosion(p_310712_, p_311693_, p_311490_, p_312709_) && p_311693_ instanceof ServerLevel) { - ServerLevel serverlevel = (ServerLevel) p_311693_; - BlockEntity blockentity = p_310712_.hasBlockEntity() ? p_311693_.getBlockEntity(p_311490_) : null; - LootParams.Builder lootparams$builder = (new LootParams.Builder(serverlevel)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(p_311490_)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, blockentity).withOptionalParameter(LootContextParams.THIS_ENTITY, p_312709_.getDirectSourceEntity()); - if (((ExplosionBridge) p_312709_).bridge$getYield() < 1.0F) { - lootparams$builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / ((ExplosionBridge) p_312709_).bridge$getYield()); - } - - p_310712_.spawnAfterBreak(serverlevel, p_311490_, ItemStack.EMPTY, flag); - p_310712_.getDrops(lootparams$builder).forEach((p_309419_) -> { - p_311277_.accept(p_309419_, p_311490_); - }); - } - this.bridge$forge$onBlockExploded(p_310712_, p_311693_, p_311490_, p_312709_); + @Decorate(method = "onExplosionHit", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;spawnAfterBreak(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/item/ItemStack;Z)V")) + private void arclight$setRadius(BlockState blockState, Level level, BlockPos blockPos, Explosion explosion, BiConsumer biConsumer, + @Local(ordinal = -1) LootParams.Builder builder) { + if (((ExplosionBridge) explosion).bridge$getYield() < 1.0F) { + builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / ((ExplosionBridge) explosion).bridge$getYield()); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java index 5c1a0534e..a53c7e8b4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/ChunkGeneratorMixin.java @@ -3,24 +3,19 @@ import io.izzel.arclight.common.bridge.core.world.IWorldBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.bridge.core.world.level.levelgen.ChunkGeneratorBridge; -import net.minecraft.core.Holder; -import net.minecraft.core.HolderSet; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.SectionPos; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.levelgen.LegacyRandomSource; -import net.minecraft.world.level.levelgen.RandomState; import net.minecraft.world.level.levelgen.WorldgenRandom; import net.minecraft.world.level.levelgen.structure.Structure; -import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureStart; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.generator.CraftLimitedRegion; import org.bukkit.craftbukkit.v.generator.structure.CraftStructure; @@ -33,10 +28,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.util.function.Predicate; @Mixin(ChunkGenerator.class) public abstract class ChunkGeneratorMixin implements ChunkGeneratorBridge { @@ -51,15 +42,16 @@ public abstract class ChunkGeneratorMixin implements ChunkGeneratorBridge { this.addDecorations(level, chunkAccess, manager); } - @Inject(method = "tryGenerateStructure", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/StructureManager;setStartForStructure(Lnet/minecraft/core/SectionPos;Lnet/minecraft/world/level/levelgen/structure/Structure;Lnet/minecraft/world/level/levelgen/structure/StructureStart;Lnet/minecraft/world/level/chunk/StructureAccess;)V")) - private void arclight$structureSpawn(StructureSet.StructureSelectionEntry p_223105_, StructureManager manager, RegistryAccess registryAccess, RandomState p_223108_, StructureTemplateManager p_223109_, long p_223110_, ChunkAccess p_223111_, ChunkPos chunkPos, SectionPos p_223113_, CallbackInfoReturnable cir, - Structure structure, int i, HolderSet holderset, Predicate> predicate, StructureStart structurestart) { + @Decorate(method = "tryGenerateStructure", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/StructureManager;setStartForStructure(Lnet/minecraft/core/SectionPos;Lnet/minecraft/world/level/levelgen/structure/Structure;Lnet/minecraft/world/level/levelgen/structure/StructureStart;Lnet/minecraft/world/level/chunk/StructureAccess;)V")) + private void arclight$structureSpawn(@Local(ordinal = -1) StructureManager manager, @Local(ordinal = -1) ChunkPos chunkPos, @Local(ordinal = -1) Structure structure, @Local(ordinal = -1) StructureStart structurestart) throws Throwable { var box = structurestart.getBoundingBox(); - var event = new org.bukkit.event.world.AsyncStructureSpawnEvent(((WorldBridge) ((IWorldBridge) manager.level).bridge$getMinecraftWorld()).bridge$getWorld(), CraftStructure.minecraftToBukkit(structure), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunkPos.x, chunkPos.z); + var event = new org.bukkit.event.world.AsyncStructureSpawnEvent(((IWorldBridge) manager.level).bridge$getMinecraftWorld().bridge$getWorld(), CraftStructure.minecraftToBukkit(structure), new org.bukkit.util.BoundingBox(box.minX(), box.minY(), box.minZ(), box.maxX(), box.maxY(), box.maxZ()), chunkPos.x, chunkPos.z); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - cir.setReturnValue(true); + DecorationOps.cancel().invoke(true); + return; } + DecorationOps.blackhole().invoke(); } public void applyBiomeDecoration(WorldGenLevel level, ChunkAccess chunkAccess, StructureManager structureFeatureManager, boolean vanilla) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/ChunkSerializerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/ChunkSerializerMixin.java index 52d04e491..1341e8ecc 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/ChunkSerializerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/ChunkSerializerMixin.java @@ -7,6 +7,7 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.storage.ChunkSerializer; +import net.minecraft.world.level.chunk.storage.RegionStorageInfo; import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -18,7 +19,7 @@ public class ChunkSerializerMixin { @Redirect(method = "read", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/ChunkAccess;setLightCorrect(Z)V")) - private static void arclight$loadPersistent(ChunkAccess instance, boolean correct, ServerLevel level, PoiManager poiManager, ChunkPos pos, CompoundTag tag) { + private static void arclight$loadPersistent(ChunkAccess instance, boolean correct, ServerLevel serverLevel, PoiManager poiManager, RegionStorageInfo regionStorageInfo, ChunkPos chunkPos, CompoundTag tag) { net.minecraft.nbt.Tag persistentBase = tag.get("ChunkBukkitValues"); if (persistentBase instanceof CompoundTag) { ((CraftPersistentDataContainer) ((ChunkAccessBridge) instance).bridge$getPersistentDataContainer()).putAll((CompoundTag) persistentBase); @@ -26,7 +27,6 @@ public class ChunkSerializerMixin { instance.setLightCorrect(correct); } - @Inject(method = "write", at = @At("RETURN")) private static void arclight$savePersistent(ServerLevel level, ChunkAccess chunkAccess, CallbackInfoReturnable cir) { var container = (CraftPersistentDataContainer) ((ChunkAccessBridge) chunkAccess).bridge$getPersistentDataContainer(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileCacheMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileCacheMixin.java index af72268c3..aac400fcb 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileCacheMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileCacheMixin.java @@ -33,7 +33,7 @@ private RegionFile loadFile(ChunkPos pos, boolean existsOnly) throws IOException private transient boolean arclight$existOnly; @Inject(method = "getRegionFile", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "NEW", target = "(Ljava/nio/file/Path;Ljava/nio/file/Path;Z)Lnet/minecraft/world/level/chunk/storage/RegionFile;")) + at = @At(value = "NEW", target = "(Lnet/minecraft/world/level/chunk/storage/RegionStorageInfo;Ljava/nio/file/Path;Ljava/nio/file/Path;Z)Lnet/minecraft/world/level/chunk/storage/RegionFile;")) private void arclight$retIfSearch(ChunkPos pos, CallbackInfoReturnable cir, long l, RegionFile rf, Path path) { if (arclight$existOnly && !Files.exists(path)) cir.setReturnValue(null); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileMixin.java new file mode 100644 index 000000000..790f22954 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/chunk/storage/RegionFileMixin.java @@ -0,0 +1,47 @@ +package io.izzel.arclight.common.mixin.core.world.level.chunk.storage; + +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.world.level.chunk.storage.RegionFile; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; + +@Mixin(RegionFile.class) +public abstract class RegionFileMixin { + + // @formatter:off + @Shadow private static int getSectorNumber(int i) { return 0; } + @Shadow @Final private FileChannel file; + // @formatter:on + + @Decorate(method = "(Lnet/minecraft/world/level/chunk/storage/RegionStorageInfo;Ljava/nio/file/Path;Ljava/nio/file/Path;Lnet/minecraft/world/level/chunk/storage/RegionFileVersion;Z)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/storage/RegionFile;getNumSectors(I)I")) + private int arclight$extendMaxLen(int i) throws Throwable { + int len = (int) DecorationOps.callsite().invoke(i); + if (len == 255) { + // We're maxed out, so we need to read the proper length from the section + ByteBuffer realLen = ByteBuffer.allocate(4); + this.file.read(realLen, getSectorNumber(i) * 4096L); + len = (realLen.getInt(0) + 4) / 4096 + 1; + } + return len; + } + + @Decorate(method = "getChunkDataInputStream", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/storage/RegionFile;getNumSectors(I)I")) + private int arclight$extendMaxLen2(int i) throws Throwable { + int len = (int) DecorationOps.callsite().invoke(i); + if (len == 255) { + // We're maxed out, so we need to read the proper length from the section + ByteBuffer realLen = ByteBuffer.allocate(4); + this.file.read(realLen, getSectorNumber(i) * 4096L); + len = (realLen.getInt(0) + 4) / 4096 + 1; + } + return len; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java index bce0cdde1..877210bfc 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/entity/PersistentEntitySectionManagerMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.entity; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.Local; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.ChunkPos; @@ -18,7 +20,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Coerce; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -58,9 +59,9 @@ public boolean isPending(long cord) { @Unique private boolean arclight$fireEvent = false; - @Inject(method = "storeChunkSections", locals = LocalCapture.CAPTURE_FAILHARD, + @Decorate(method = "storeChunkSections", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/EntityPersistentStorage;storeEntities(Lnet/minecraft/world/level/entity/ChunkEntities;)V")) - private void arclight$fireUnload(long pos, Consumer consumer, CallbackInfoReturnable cir, @Coerce Object status, List list) { + private void arclight$fireUnload(long pos, @Local(ordinal = -1) List list) { if (arclight$fireEvent) { CraftEventFactory.callEntitiesUnloadEvent(((EntityStorage) permanentStorage).level, new ChunkPos(pos), list.stream().map(entity -> (Entity) entity).collect(Collectors.toList())); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/GameEventDispatcherMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/GameEventDispatcherMixin.java index 52903e2ab..817917e76 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/GameEventDispatcherMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/GameEventDispatcherMixin.java @@ -1,7 +1,9 @@ package io.izzel.arclight.common.mixin.core.world.level.gameevent; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.gameevent.GameEventDispatcher; @@ -14,33 +16,23 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GameEventDispatcher.class) public class GameEventDispatcherMixin { @Shadow @Final private ServerLevel level; - private transient int arclight$newRadius; - - @Inject(method = "post", cancellable = true, at = @At("HEAD")) - private void arclight$gameEvent(GameEvent gameEvent, Vec3 vec3, GameEvent.Context context, CallbackInfo ci) { + @Decorate(method = "post", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;containing(Lnet/minecraft/core/Position;)Lnet/minecraft/core/BlockPos;")) + private void arclight$gameEvent(Holder holder, Vec3 vec3, GameEvent.Context context, @Local(ordinal = 0) int i) throws Throwable { var entity = context.sourceEntity(); - var i = gameEvent.getNotificationRadius(); - GenericGameEvent event = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(gameEvent), - new Location(((WorldBridge) this.level).bridge$getWorld(), vec3.x(), vec3.y(), vec3.z()), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread()); + GenericGameEvent event = new GenericGameEvent(CraftGameEvent.minecraftToBukkit(holder.value()), + new Location(this.level.bridge$getWorld(), vec3.x(), vec3.y(), vec3.z()), (entity == null) ? null : entity.bridge$getBukkitEntity(), i, !Bukkit.isPrimaryThread()); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { - ci.cancel(); - } else { - arclight$newRadius = event.getRadius(); + DecorationOps.cancel().invoke(); + return; } - } - - @Redirect(method = "post", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/gameevent/GameEvent;getNotificationRadius()I")) - private int arclight$applyRadius(GameEvent instance) { - return arclight$newRadius; + i = event.getRadius(); + DecorationOps.blackhole().invoke(i); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/vibrations/VibrationListenerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/vibrations/VibrationListenerMixin.java index d9c352acc..49120abaf 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/vibrations/VibrationListenerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/gameevent/vibrations/VibrationListenerMixin.java @@ -1,69 +1,30 @@ package io.izzel.arclight.common.mixin.core.world.level.gameevent.vibrations; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.gameevent.vibrations.VibrationSystem; -import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftGameEvent; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.event.block.BlockReceiveGameEvent; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Optional; +import org.spongepowered.asm.mixin.injection.At; @Mixin(VibrationSystem.Listener.class) public abstract class VibrationListenerMixin { - // @formatter:off - @Shadow private static boolean isOccluded(Level p_223776_, Vec3 p_223777_, Vec3 p_223778_) { return false; } - @Shadow @Final private VibrationSystem system; - @Shadow protected abstract void scheduleVibration(ServerLevel p_282037_, VibrationSystem.Data p_283229_, GameEvent p_281778_, GameEvent.Context p_283344_, Vec3 p_281758_, Vec3 p_282990_); - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean handleGameEvent(ServerLevel worldserver, GameEvent gameevent, GameEvent.Context gameevent_a, Vec3 vec3d) { - VibrationSystem.Data vibrationsystem_a = this.system.getVibrationData(); - VibrationSystem.User vibrationsystem_d = this.system.getVibrationUser(); - - if (vibrationsystem_a.getCurrentVibration() != null) { - return false; - } else if (!vibrationsystem_d.isValidVibration(gameevent, gameevent_a)) { - return false; - } else { - Optional optional = vibrationsystem_d.getPositionSource().getPosition(worldserver); - - if (optional.isEmpty()) { - return false; - } else { - Vec3 vec3d1 = optional.get(); - // CraftBukkit start - boolean defaultCancel = !vibrationsystem_d.canReceiveVibration(worldserver, BlockPos.containing(vec3d), gameevent, gameevent_a); - Entity entity = gameevent_a.sourceEntity(); - BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameevent), CraftBlock.at(worldserver, BlockPos.containing(vec3d1)), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity()); - event.setCancelled(defaultCancel); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - // CraftBukkit end - return false; - } else if (isOccluded(worldserver, vec3d, vec3d1)) { - return false; - } else { - this.scheduleVibration(worldserver, vibrationsystem_a, gameevent, gameevent_a, vec3d, vec3d1); - return true; - } - } - } + @Decorate(method = "handleGameEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/gameevent/vibrations/VibrationSystem$User;canReceiveVibration(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Holder;Lnet/minecraft/world/level/gameevent/GameEvent$Context;)Z")) + private boolean arclight$gameEvent(VibrationSystem.User instance, ServerLevel serverLevel, BlockPos pos, Holder gameEventHolder, GameEvent.Context context) throws Throwable { + var defaultCancel = !(boolean) DecorationOps.callsite().invoke(instance, serverLevel, pos, gameEventHolder, context); + Entity entity = context.sourceEntity(); + BlockReceiveGameEvent event = new BlockReceiveGameEvent(CraftGameEvent.minecraftToBukkit(gameEventHolder.value()), CraftBlock.at(serverLevel, pos), (entity == null) ? null : entity.bridge$getBukkitEntity()); + event.setCancelled(defaultCancel); + Bukkit.getPluginManager().callEvent(event); + return !event.isCancelled(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/feature/EndPlatformFeatureMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/feature/EndPlatformFeatureMixin.java new file mode 100644 index 000000000..6f2d61a2f --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/feature/EndPlatformFeatureMixin.java @@ -0,0 +1,70 @@ +package io.izzel.arclight.common.mixin.core.world.level.levelgen.feature; + +import io.izzel.arclight.common.mod.util.ArclightCaptures; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.ServerLevelAccessor; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.feature.EndPlatformFeature; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; +import org.bukkit.event.world.PortalCreateEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; + +@Mixin(EndPlatformFeature.class) +public class EndPlatformFeatureMixin { + + @Decorate(method = "createEndPlatform", inject = true, at = @At("HEAD")) + private static void arclight$blockList(ServerLevelAccessor serverLevelAccessor, + @Local(allocate = "blockList") BlockStateListPopulator blockList, + @Local(allocate = "entity") Entity entity) throws Throwable { + entity = ArclightCaptures.getEndPortalEntity(); + blockList = entity != null ? new BlockStateListPopulator(serverLevelAccessor) : null; + DecorationOps.blackhole().invoke(blockList, entity); + } + + @Decorate(method = "createEndPlatform", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) + private static BlockState arclight$useBlockList1(ServerLevelAccessor instance, BlockPos pos, @Local(allocate = "blockList") BlockStateListPopulator blockList) throws Throwable { + if (blockList != null) { + instance = blockList; + } + return (BlockState) DecorationOps.callsite().invoke(instance, pos); + } + + @Decorate(method = "createEndPlatform", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;destroyBlock(Lnet/minecraft/core/BlockPos;ZLnet/minecraft/world/entity/Entity;)Z")) + private static boolean arclight$useBlockList2(ServerLevelAccessor instance, BlockPos pos, boolean b, Entity entity, @Local(allocate = "blockList") BlockStateListPopulator blockList) throws Throwable { + if (blockList != null) { + instance = blockList; + } + return (boolean) DecorationOps.callsite().invoke(instance, pos, b, entity); + } + + @Decorate(method = "createEndPlatform", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/ServerLevelAccessor;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) + private static boolean arclight$useBlockList3(ServerLevelAccessor instance, BlockPos pos, BlockState blockState, int i, @Local(allocate = "blockList") BlockStateListPopulator blockList) throws Throwable { + if (blockList != null) { + instance = blockList; + } + return (boolean) DecorationOps.callsite().invoke(instance, pos, blockState, i); + } + + @Decorate(method = "createEndPlatform", inject = true, at = @At("RETURN")) + private static void arclight$portalCreate(ServerLevelAccessor serverLevelAccessor, + @Local(allocate = "blockList") BlockStateListPopulator blockList, + @Local(allocate = "entity") Entity entity) { + if (blockList != null) { + var bworld = serverLevelAccessor.getLevel().bridge$getWorld(); + PortalCreateEvent portalEvent = new PortalCreateEvent((List) (List) blockList.getList(), bworld, entity.bridge$getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.END_PLATFORM); + + Bukkit.getPluginManager().callEvent(portalEvent); + if (!portalEvent.isCancelled()) { + blockList.updateList(); + } + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/StructurePieceMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/StructurePieceMixin.java index af005d79b..b5e5bbc8d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/StructurePieceMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/StructurePieceMixin.java @@ -1,7 +1,7 @@ package io.izzel.arclight.common.mixin.core.world.level.levelgen.structure; import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.resources.ResourceKey; import net.minecraft.util.RandomSource; import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.WorldGenLevel; @@ -10,6 +10,7 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.StructurePiece; +import net.minecraft.world.level.storage.loot.LootTable; import org.bukkit.craftbukkit.v.block.CraftBlockEntityState; import org.bukkit.craftbukkit.v.block.CraftBlockState; import org.bukkit.craftbukkit.v.block.CraftBlockStates; @@ -28,7 +29,7 @@ public class StructurePieceMixin { @Inject(method = "placeBlock", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/WorldGenLevel;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) private void arclight$useTransformer(WorldGenLevel level, BlockState p_73436_, int p_73437_, int p_73438_, int p_73439_, BoundingBox p_73440_, CallbackInfo ci, BlockPos pos) { if (level instanceof TransformerGeneratorAccess transformerGeneratorAccess) { - transformerGeneratorAccess.setCraftBlock(pos, (CraftBlockState) CraftBlockStates.getBlockState(pos, p_73436_, null), 2); + transformerGeneratorAccess.setCraftBlock(pos, (CraftBlockState) CraftBlockStates.getBlockState(level, pos, p_73436_, null), 2); ci.cancel(); } } @@ -41,7 +42,7 @@ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPo boolean result = worldAccess.setBlock(position, craftBlockEntityState.getHandle(), i); var tileEntity = worldAccess.getBlockEntity(position); if (tileEntity != null) { - tileEntity.load(craftBlockEntityState.getSnapshotNBT()); + tileEntity.loadWithComponents(craftBlockEntityState.getSnapshotNBT(), worldAccess.registryAccess()); } return result; } @@ -49,19 +50,19 @@ protected boolean placeCraftBlockEntity(ServerLevelAccessor worldAccess, BlockPo @Unique protected void placeCraftSpawner(ServerLevelAccessor worldAccess, BlockPos position, org.bukkit.entity.EntityType entityType, int i) { // This method is used in structures that are generated by code and place spawners as they set the entity after the block was placed making it impossible for plugins to access that information - var spawner = (CraftCreatureSpawner) CraftBlockStates.getBlockState(position, Blocks.SPAWNER.defaultBlockState(), null); + var spawner = (CraftCreatureSpawner) CraftBlockStates.getBlockState(worldAccess, position, Blocks.SPAWNER.defaultBlockState(), null); spawner.setSpawnedType(entityType); placeCraftBlockEntity(worldAccess, position, spawner, i); } @Unique - protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, ResourceLocation loottableKey) { + protected void setCraftLootTable(ServerLevelAccessor worldAccess, BlockPos position, RandomSource randomSource, ResourceKey loottableKey) { // This method is used in structures that use data markers to a loot table to loot containers as otherwise plugins won't have access to that information. var tileEntity = worldAccess.getBlockEntity(position); if (tileEntity instanceof RandomizableContainerBlockEntity tileEntityLootable) { tileEntityLootable.setLootTable(loottableKey, randomSource.nextLong()); if (worldAccess instanceof TransformerGeneratorAccess transformerAccess) { - transformerAccess.setCraftBlock(position, (CraftBlockState) CraftBlockStates.getBlockState(position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata()), 3); + transformerAccess.setCraftBlock(position, (CraftBlockState) CraftBlockStates.getBlockState(worldAccess, position, tileEntity.getBlockState(), tileEntityLootable.saveWithFullMetadata(worldAccess.registryAccess())), 3); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin.java index 0152d93d9..2a216c586 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin.java @@ -1,29 +1,18 @@ package io.izzel.arclight.common.mixin.core.world.level.levelgen.structure.templatesystem; -import com.google.common.collect.Lists; -import com.mojang.datafixers.util.Pair; import io.izzel.arclight.common.bridge.core.world.level.levelgen.structure.templatesystem.StructureTemplateBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.core.HolderGetter; -import net.minecraft.core.Vec3i; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.RandomSource; -import net.minecraft.world.Clearable; -import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.BoundingBox; import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; -import net.minecraft.world.phys.shapes.DiscreteVoxelShape; import org.bukkit.craftbukkit.v.block.CraftBlockEntityState; import org.bukkit.craftbukkit.v.block.CraftBlockState; import org.bukkit.craftbukkit.v.block.CraftBlockStates; @@ -32,29 +21,15 @@ import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry; import org.bukkit.craftbukkit.v.util.CraftStructureTransformer; import org.bukkit.craftbukkit.v.util.TransformerGeneratorAccess; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import java.util.Iterator; -import java.util.List; - @Mixin(StructureTemplate.class) public abstract class StructureTemplateMixin implements StructureTemplateBridge { - // @formatter:off - @Shadow @Final public List palettes; - @Shadow @Final public List entityInfoList; - @Shadow private Vec3i size; - @Shadow public static void updateShapeAtEdge(LevelAccessor p_74511_, int p_74512_, DiscreteVoxelShape p_74513_, int p_74514_, int p_74515_, int p_74516_) { } - // @formatter:on - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); public CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); @@ -73,179 +48,50 @@ public abstract class StructureTemplateMixin implements StructureTemplateBridge } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean placeInWorld(ServerLevelAccessor p_230329_, BlockPos pos, BlockPos p_230331_, StructurePlaceSettings placeSettings, RandomSource p_230333_, int p_230334_) { - if (this.palettes.isEmpty()) { - return false; - } else { - // CraftBukkit start - // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed - var wrappedAccess = p_230329_; - CraftStructureTransformer structureTransformer = null; - if (wrappedAccess instanceof TransformerGeneratorAccess transformerAccess) { - p_230329_ = transformerAccess.getHandle(); - structureTransformer = transformerAccess.getStructureTransformer(); - // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this - if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { - structureTransformer = null; - } + @Decorate(method = "placeInWorld", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings;getRandomPalette(Ljava/util/List;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate$Palette;")) + private void arclight$unwrap(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, BlockPos blockPos2, StructurePlaceSettings structurePlaceSettings, RandomSource randomSource, int i, + @Local(allocate = "wrappedAccess") ServerLevelAccessor wrappedAccess, + @Local(allocate = "structureTransformer") CraftStructureTransformer structureTransformer) throws Throwable { + wrappedAccess = serverLevelAccessor; + structureTransformer = null; + if (wrappedAccess instanceof TransformerGeneratorAccess transformerAccess) { + serverLevelAccessor = transformerAccess.getHandle(); + structureTransformer = transformerAccess.getStructureTransformer(); + // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this + if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { + structureTransformer = null; } - // CraftBukkit end - List list = placeSettings.getRandomPalette(this.palettes, pos).blocks(); - if ((!list.isEmpty() || !placeSettings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { - BoundingBox boundingbox = placeSettings.getBoundingBox(); - List list1 = Lists.newArrayListWithCapacity(placeSettings.shouldKeepLiquids() ? list.size() : 0); - List list2 = Lists.newArrayListWithCapacity(placeSettings.shouldKeepLiquids() ? list.size() : 0); - List> list3 = Lists.newArrayListWithCapacity(list.size()); - int i = Integer.MAX_VALUE; - int j = Integer.MAX_VALUE; - int k = Integer.MAX_VALUE; - int l = Integer.MIN_VALUE; - int i1 = Integer.MIN_VALUE; - int j1 = Integer.MIN_VALUE; - - for (StructureTemplate.StructureBlockInfo structuretemplate$structureblockinfo : this.bridge$platform$processBlockInfos(p_230329_, pos, p_230331_, placeSettings, list, (StructureTemplate) (Object) this)) { - BlockPos blockpos = structuretemplate$structureblockinfo.pos(); - if (boundingbox == null || boundingbox.isInside(blockpos)) { - FluidState fluidstate = placeSettings.shouldKeepLiquids() ? p_230329_.getFluidState(blockpos) : null; - BlockState blockstate = structuretemplate$structureblockinfo.state().mirror(placeSettings.getMirror()).rotate(placeSettings.getRotation()); - if (structuretemplate$structureblockinfo.nbt() != null) { - BlockEntity blockentity = p_230329_.getBlockEntity(blockpos); - Clearable.tryClear(blockentity); - p_230329_.setBlock(blockpos, Blocks.BARRIER.defaultBlockState(), 20); - } - // CraftBukkit start - if (structureTransformer != null) { - var craftBlockState = (CraftBlockState) CraftBlockStates.getBlockState(blockpos, blockstate, null); - if (structuretemplate$structureblockinfo.nbt() != null && craftBlockState instanceof CraftBlockEntityState entityState) { - entityState.loadData(structuretemplate$structureblockinfo.nbt()); - if (craftBlockState instanceof CraftLootable craftLootable) { - craftLootable.setSeed(p_230333_.nextLong()); - } - } - craftBlockState = structureTransformer.transformCraftState(craftBlockState); - blockstate = craftBlockState.getHandle(); - structuretemplate$structureblockinfo = new StructureTemplate.StructureBlockInfo(blockpos, blockstate, (craftBlockState instanceof CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); - } - // CraftBukkit end - - if (p_230329_.setBlock(blockpos, blockstate, p_230334_)) { - i = Math.min(i, blockpos.getX()); - j = Math.min(j, blockpos.getY()); - k = Math.min(k, blockpos.getZ()); - l = Math.max(l, blockpos.getX()); - i1 = Math.max(i1, blockpos.getY()); - j1 = Math.max(j1, blockpos.getZ()); - list3.add(Pair.of(blockpos, structuretemplate$structureblockinfo.nbt())); - if (structuretemplate$structureblockinfo.nbt() != null) { - BlockEntity blockentity1 = p_230329_.getBlockEntity(blockpos); - if (blockentity1 != null) { - if (structureTransformer == null && blockentity1 instanceof RandomizableContainerBlockEntity) { - structuretemplate$structureblockinfo.nbt().putLong("LootTableSeed", p_230333_.nextLong()); - } - - blockentity1.load(structuretemplate$structureblockinfo.nbt()); - } - } - - if (fluidstate != null) { - if (blockstate.getFluidState().isSource()) { - list2.add(blockpos); - } else if (blockstate.getBlock() instanceof LiquidBlockContainer) { - ((LiquidBlockContainer) blockstate.getBlock()).placeLiquid(p_230329_, blockpos, blockstate, fluidstate); - if (!fluidstate.isSource()) { - list1.add(blockpos); - } - } - } - } - } - } - - boolean flag = true; - Direction[] adirection = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; - - while (flag && !list1.isEmpty()) { - flag = false; - Iterator iterator = list1.iterator(); - - while (iterator.hasNext()) { - BlockPos blockpos3 = iterator.next(); - FluidState fluidstate2 = p_230329_.getFluidState(blockpos3); - - for (int i2 = 0; i2 < adirection.length && !fluidstate2.isSource(); ++i2) { - BlockPos blockpos1 = blockpos3.relative(adirection[i2]); - FluidState fluidstate1 = p_230329_.getFluidState(blockpos1); - if (fluidstate1.isSource() && !list2.contains(blockpos1)) { - fluidstate2 = fluidstate1; - } - } - - if (fluidstate2.isSource()) { - BlockState blockstate1 = p_230329_.getBlockState(blockpos3); - Block block = blockstate1.getBlock(); - if (block instanceof LiquidBlockContainer) { - ((LiquidBlockContainer) block).placeLiquid(p_230329_, blockpos3, blockstate1, fluidstate2); - flag = true; - iterator.remove(); - } - } - } - } - - if (i <= l) { - if (!placeSettings.getKnownShape()) { - DiscreteVoxelShape discretevoxelshape = new BitSetDiscreteVoxelShape(l - i + 1, i1 - j + 1, j1 - k + 1); - int k1 = i; - int l1 = j; - int j2 = k; - - for (Pair pair1 : list3) { - BlockPos blockpos2 = pair1.getFirst(); - discretevoxelshape.fill(blockpos2.getX() - k1, blockpos2.getY() - l1, blockpos2.getZ() - j2); - } - - updateShapeAtEdge(p_230329_, p_230334_, discretevoxelshape, k1, l1, j2); - } - - for (Pair pair : list3) { - BlockPos blockpos4 = pair.getFirst(); - if (!placeSettings.getKnownShape()) { - BlockState blockstate2 = p_230329_.getBlockState(blockpos4); - BlockState blockstate3 = Block.updateFromNeighbourShapes(blockstate2, p_230329_, blockpos4); - if (blockstate2 != blockstate3) { - p_230329_.setBlock(blockpos4, blockstate3, p_230334_ & -2 | 16); - } - - p_230329_.blockUpdated(blockpos4, blockstate3.getBlock()); - } - - if (pair.getSecond() != null) { - BlockEntity blockentity2 = p_230329_.getBlockEntity(blockpos4); - if (blockentity2 != null) { - blockentity2.setChanged(); - } - } - } - } + } + DecorationOps.blackhole().invoke(serverLevelAccessor, wrappedAccess, structureTransformer); + } - if (!placeSettings.isIgnoreEntities()) { - this.bridge$platform$placeEntities(wrappedAccess, pos, placeSettings.getMirror(), placeSettings.getRotation(), placeSettings.getRotationPivot(), placeSettings.getBoundingBox(), placeSettings.shouldFinalizeEntities(), placeSettings); + @Decorate(method = "placeInWorld", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/ServerLevelAccessor;setBlock(Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;I)Z")) + private boolean arclight$useTransformer(ServerLevelAccessor instance, BlockPos pos, BlockState blockState, int i, + @Local(ordinal = -1) RandomSource randomSource, + @Local(ordinal = -1) StructureTemplate.StructureBlockInfo structureBlockInfo, + @Local(ordinal = -1) BlockState blockstate, + @Local(allocate = "structureTransformer") CraftStructureTransformer structureTransformer) throws Throwable { + if (structureTransformer != null) { + var craftBlockState = (CraftBlockState) CraftBlockStates.getBlockState(instance, pos, blockstate, null); + if (structureBlockInfo.nbt() != null && craftBlockState instanceof CraftBlockEntityState entityState) { + entityState.loadData(structureBlockInfo.nbt()); + if (craftBlockState instanceof CraftLootable craftLootable) { + craftLootable.setSeed(randomSource.nextLong()); } - - return true; - } else { - return false; } + craftBlockState = structureTransformer.transformCraftState(craftBlockState); + blockState = craftBlockState.getHandle(); + blockstate = blockState; + structureBlockInfo = new StructureTemplate.StructureBlockInfo(pos, blockState, (craftBlockState instanceof CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); } + DecorationOps.blackhole().invoke(structureBlockInfo, blockstate); + return (boolean) DecorationOps.callsite().invoke(instance, pos, blockState, i); } - @Override - public List bridge$platform$processBlockInfos(ServerLevelAccessor arg, BlockPos arg2, BlockPos arg3, StructurePlaceSettings arg4, List list2, @Nullable StructureTemplate template) { - return StructureTemplate.processBlockInfos(arg, arg2, arg3, arg4, list2); + @Decorate(method = "placeInWorld", inject = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings;isIgnoreEntities()Z")) + private void arclight$resetWrap(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, BlockPos blockPos2, StructurePlaceSettings structurePlaceSettings, RandomSource randomSource, int i, + @Local(allocate = "wrappedAccess") ServerLevelAccessor wrappedAccess) throws Throwable { + serverLevelAccessor = wrappedAccess; + DecorationOps.blackhole().invoke(serverLevelAccessor); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/DimensionTransitionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/DimensionTransitionMixin.java new file mode 100644 index 000000000..0426086d8 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/DimensionTransitionMixin.java @@ -0,0 +1,49 @@ +package io.izzel.arclight.common.mixin.core.world.level.portal; + +import io.izzel.arclight.common.bridge.core.world.level.portal.DimensionTransitionBridge; +import io.izzel.arclight.common.mod.mixins.annotation.CreateConstructor; +import io.izzel.arclight.common.mod.mixins.annotation.ShadowConstructor; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.phys.Vec3; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(DimensionTransition.class) +public class DimensionTransitionMixin implements DimensionTransitionBridge { + + @ShadowConstructor + public void arclight$constructor(ServerLevel newLevel, Vec3 pos, Vec3 speed, float yRot, float xRot, boolean missingRespawnBlock, DimensionTransition.PostDimensionTransition postDimensionTransition) { + throw new RuntimeException(); + } + + @CreateConstructor + public void arclight$constructor(ServerLevel newLevel, Vec3 pos, Vec3 speed, float yRot, float xRot, boolean missingRespawnBlock, DimensionTransition.PostDimensionTransition postDimensionTransition, PlayerTeleportEvent.TeleportCause cause) { + arclight$constructor(newLevel, pos, speed, yRot, xRot, missingRespawnBlock, postDimensionTransition); + this.arclight$cause = cause; + } + + @ShadowConstructor + public void arclight$constructor(ServerLevel serverLevel, Vec3 vec3, Vec3 vec32, float f, float g, DimensionTransition.PostDimensionTransition postDimensionTransition) { + throw new RuntimeException(); + } + + @CreateConstructor + public void arclight$constructor(ServerLevel serverLevel, Vec3 vec3, Vec3 vec32, float f, float g, DimensionTransition.PostDimensionTransition postDimensionTransition, PlayerTeleportEvent.TeleportCause cause) { + arclight$constructor(serverLevel, vec3, vec32, f, g, postDimensionTransition); + this.arclight$cause = cause; + } + + @Unique private PlayerTeleportEvent.TeleportCause arclight$cause; + + @Override + public void bridge$setTeleportCause(PlayerTeleportEvent.TeleportCause cause) { + arclight$cause = cause; + } + + @Override + public PlayerTeleportEvent.TeleportCause bridge$getTeleportCause() { + return arclight$cause; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/PortalForcerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/PortalForcerMixin.java index 2f3d05746..9556da4ad 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/PortalForcerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/portal/PortalForcerMixin.java @@ -1,15 +1,12 @@ package io.izzel.arclight.common.mixin.core.world.level.portal; -import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.world.TeleporterBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; import net.minecraft.BlockUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.portal.PortalForcer; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftWorld; @@ -21,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; -import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @@ -35,28 +31,23 @@ public abstract class PortalForcerMixin implements TeleporterBridge { // @formatter:off @Shadow public abstract Optional createPortal(BlockPos pos, Direction.Axis axis); @Shadow @Final protected ServerLevel level; - @Shadow public abstract Optional findPortalAround(BlockPos p_192986_, boolean p_192987_, WorldBorder p_192988_); // @formatter:on - @ModifyVariable(method = "findPortalAround", ordinal = 0, at = @At(value = "STORE", ordinal = 0)) - private int arclight$useSearchRadius(int i) { - return this.arclight$searchRadius == -1 ? i : this.arclight$searchRadius; - } - private transient int arclight$searchRadius = -1; - public Optional findPortalAround(BlockPos pos, WorldBorder worldBorder, int searchRadius) { + @Override + public void bridge$pushSearchRadius(int searchRadius) { this.arclight$searchRadius = searchRadius; - try { - return this.findPortalAround(pos, false, worldBorder); - } finally { - this.arclight$searchRadius = -1; - } } - @Override - public Optional bridge$findPortal(BlockPos pos, WorldBorder worldborder, int searchRadius) { - return findPortalAround(pos, worldborder, searchRadius); + @ModifyArg(method = "findClosestPortalPosition", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;ensureLoadedAndValid(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;I)V")) + private int arclight$useSearchRadius1(int i) { + return this.arclight$searchRadius > 0 ? this.arclight$searchRadius : i; + } + + @ModifyArg(method = "findClosestPortalPosition", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/village/poi/PoiManager;getInSquare(Ljava/util/function/Predicate;Lnet/minecraft/core/BlockPos;ILnet/minecraft/world/entity/ai/village/poi/PoiManager$Occupancy;)Ljava/util/stream/Stream;")) + private int arclight$useSearchRadius2(int i) { + return this.arclight$searchRadius > 0 ? this.arclight$searchRadius : i; } @ModifyArg(method = "createPortal", index = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;spiralAround(Lnet/minecraft/core/BlockPos;ILnet/minecraft/core/Direction;Lnet/minecraft/core/Direction;)Ljava/lang/Iterable;")) @@ -83,14 +74,14 @@ public Optional findPortalAround(BlockPos pos, WorldBo @SuppressWarnings({"unchecked", "rawtypes"}) @Inject(method = "createPortal", cancellable = true, at = @At("RETURN")) private void arclight$portalCreate(BlockPos pos, Direction.Axis axis, CallbackInfoReturnable> cir) { - CraftWorld craftWorld = ((WorldBridge) this.level).bridge$getWorld(); + CraftWorld craftWorld = this.level.bridge$getWorld(); List blockStates; if (this.arclight$populator == null) { blockStates = new ArrayList<>(); } else { blockStates = (List) this.arclight$populator.getList(); } - PortalCreateEvent event = new PortalCreateEvent(blockStates, craftWorld, (this.arclight$entity == null) ? null : ((EntityBridge) this.arclight$entity).bridge$getBukkitEntity(), PortalCreateEvent.CreateReason.NETHER_PAIR); + PortalCreateEvent event = new PortalCreateEvent(blockStates, craftWorld, (this.arclight$entity == null) ? null : this.arclight$entity.bridge$getBukkitEntity(), PortalCreateEvent.CreateReason.NETHER_PAIR); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { @@ -106,19 +97,9 @@ public Optional findPortalAround(BlockPos pos, WorldBo private transient Entity arclight$entity; private transient int arclight$createRadius = -1; - public Optional createPortal(BlockPos pos, Direction.Axis axis, Entity entity, int createRadius) { + @Override + public void bridge$pushPortalCreate(Entity entity, int createRadius) { this.arclight$entity = entity; this.arclight$createRadius = createRadius; - try { - return this.createPortal(pos, axis); - } finally { - this.arclight$entity = null; - this.arclight$createRadius = -1; - } - } - - @Override - public Optional bridge$createPortal(BlockPos pos, Direction.Axis axis, Entity entity, int createRadius) { - return createPortal(pos, axis, entity, createRadius); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/redstone/NeighborUpdaterMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/redstone/NeighborUpdaterMixin.java index 6b96a78ff..d4a1ea882 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/redstone/NeighborUpdaterMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/redstone/NeighborUpdaterMixin.java @@ -1,11 +1,10 @@ package io.izzel.arclight.common.mixin.core.world.level.redstone; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import net.minecraft.CrashReport; -import net.minecraft.CrashReportCategory; -import net.minecraft.ReportedException; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; @@ -15,45 +14,30 @@ import org.bukkit.craftbukkit.v.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.util.Locale; +import org.spongepowered.asm.mixin.injection.At; @Mixin(NeighborUpdater.class) public interface NeighborUpdaterMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - static void executeUpdate(Level level, BlockState state, BlockPos pos, Block block, BlockPos source, boolean p_230769_) { - try { - var cworld = ((WorldBridge) level).bridge$getWorld(); - if (cworld != null) { - BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(state), CraftBlock.at(level, source)); - Bukkit.getPluginManager().callEvent(event); + @Decorate(method = "executeUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/state/BlockState;handleNeighborChanged(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/Block;Lnet/minecraft/core/BlockPos;Z)V")) + private static void arclight$blockPhysicsEvent(BlockState instance, Level level, BlockPos pos, Block block, BlockPos source, boolean b) throws Throwable { + var cworld = level.bridge$getWorld(); + if (cworld != null) { + BlockPhysicsEvent event = new BlockPhysicsEvent(CraftBlock.at(level, pos), CraftBlockData.fromData(instance), CraftBlock.at(level, source)); + Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } + if (event.isCancelled()) { + DecorationOps.cancel().invoke(); + return; } - state.neighborChanged(level, pos, block, source, p_230769_); - } catch (StackOverflowError ex) { + } + DecorationOps.callsite().invoke(instance, level, pos, block, source, b); + } + + @Decorate(method = "executeUpdate", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/CrashReport;forThrowable(Ljava/lang/Throwable;Ljava/lang/String;)Lnet/minecraft/CrashReport;")) + private static void arclight$setLastPhysicsProblem(BlockState instance, Level level, BlockPos pos, @Local(ordinal = -1) Throwable t) { + if (t instanceof StackOverflowError) { ((WorldBridge) level).bridge$setLastPhysicsProblem(pos.immutable()); - // Spigot End - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); - CrashReportCategory crashreportcategory = crashreport.addCategory("Block being updated"); - crashreportcategory.setDetail("Source block type", () -> { - try { - return String.format(Locale.ROOT, "ID #%s (%s // %s)", BuiltInRegistries.BLOCK.getKey(block), block.getDescriptionId(), block.getClass().getCanonicalName()); - } catch (Throwable throwable1) { - return "ID #" + BuiltInRegistries.BLOCK.getKey(block); - } - }); - CrashReportCategory.populateBlockDetails(crashreportcategory, level, pos, state); - throw new ReportedException(crashreport); } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapDataMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapDataMixin.java index 40eb173f8..a6fd6740a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapDataMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapDataMixin.java @@ -1,9 +1,11 @@ package io.izzel.arclight.common.mixin.core.world.level.saveddata.maps; import io.izzel.arclight.common.bridge.core.world.storage.MapDataBridge; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftServer; @@ -34,7 +36,7 @@ public abstract class MapDataMixin implements MapDataBridge { public CraftMapView mapView; private CraftServer server; public UUID uniqueId; - public String id; + public MapId id; @Inject(method = "", at = @At("RETURN")) public void arclight$init(int p_164768_, int p_164769_, byte p_164770_, boolean p_164771_, boolean p_164772_, boolean p_164773_, ResourceKey p_164774_, CallbackInfo ci) { @@ -60,7 +62,7 @@ public abstract class MapDataMixin implements MapDataBridge { } @Inject(method = "save", at = @At("HEAD")) - public void arclight$storeDimension(CompoundTag compound, CallbackInfoReturnable cir) { + public void arclight$storeDimension(CompoundTag compound, HolderLookup.Provider provider, CallbackInfoReturnable cir) { if (this.uniqueId == null) { for (org.bukkit.World world : this.server.getWorlds()) { CraftWorld cWorld = (CraftWorld) world; @@ -76,7 +78,7 @@ public abstract class MapDataMixin implements MapDataBridge { } @Override - public void bridge$setId(String id) { + public void bridge$setId(MapId id) { this.id = id; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapItemSavedData_HoldingPlayerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapItemSavedData_HoldingPlayerMixin.java index e30918634..e39238b85 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapItemSavedData_HoldingPlayerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/saveddata/maps/MapItemSavedData_HoldingPlayerMixin.java @@ -6,7 +6,9 @@ import net.minecraft.network.protocol.game.ClientboundMapItemDataPacket; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.saveddata.maps.MapDecoration; +import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; +import org.bukkit.craftbukkit.v.map.CraftMapCursor; import org.bukkit.craftbukkit.v.map.RenderData; import org.bukkit.craftbukkit.v.util.CraftChatMessage; import org.bukkit.map.MapCursor; @@ -41,7 +43,7 @@ public abstract class MapItemSavedData_HoldingPlayerMixin { */ @Overwrite @Nullable - public Packet nextUpdatePacket(int i) { + public Packet nextUpdatePacket(MapId id) { RenderData render = ((MapDataBridge) outerThis).bridge$getMapView().render(((ServerPlayerEntityBridge) this.player).bridge$getBukkitEntity()); MapItemSavedData.MapPatch patch; if (this.dirtyData) { @@ -59,12 +61,12 @@ public Packet nextUpdatePacket(int i) { icons = new ArrayList<>(); for (MapCursor cursor : render.cursors) { if (cursor.isVisible()) { - icons.add(new MapDecoration(MapDecoration.Type.byIcon(cursor.getRawType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrNull(cursor.getCaption()))); + icons.add(new MapDecoration(CraftMapCursor.CraftType.bukkitToMinecraftHolder(cursor.getType()), cursor.getX(), cursor.getY(), cursor.getDirection(), CraftChatMessage.fromStringOrOptional(cursor.getCaption()))); } } } else { icons = null; } - return icons == null && patch == null ? null : new ClientboundMapItemDataPacket(i, outerThis.scale, outerThis.locked, icons, patch); + return icons == null && patch == null ? null : new ClientboundMapItemDataPacket(id, outerThis.scale, outerThis.locked, icons, patch); } } \ No newline at end of file diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataManagerMixin.java deleted file mode 100644 index 2c137d998..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataManagerMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.storage.loot; - -import io.izzel.arclight.common.bridge.core.world.storage.loot.LootTableBridge; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.storage.loot.LootDataId; -import net.minecraft.world.level.storage.loot.LootDataManager; -import net.minecraft.world.level.storage.loot.LootDataType; -import net.minecraft.world.level.storage.loot.LootTable; -import org.bukkit.craftbukkit.v.CraftLootTable; -import org.bukkit.craftbukkit.v.util.CraftNamespacedKey; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.Map; - -@Mixin(LootDataManager.class) -public class LootDataManagerMixin { - - // @formatter:off - @Shadow private Map, ?> elements; - // @formatter:on - - @Inject(method = "apply", at = @At("RETURN")) - private void arclight$buildRev(Map, Map> p_279426_, CallbackInfo ci) { - this.elements.forEach((key, value) -> { - if (value instanceof LootTable lootTable) { - ((LootTableBridge) lootTable).bridge$setCraftLootTable(new CraftLootTable(CraftNamespacedKey.fromMinecraft(key.location()), lootTable)); - } - }); - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataTypeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataTypeMixin.java new file mode 100644 index 000000000..689337f08 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootDataTypeMixin.java @@ -0,0 +1,24 @@ +package io.izzel.arclight.common.mixin.core.world.level.storage.loot; + +import io.izzel.arclight.common.bridge.core.world.storage.loot.LootTableBridge; +import net.minecraft.world.level.storage.loot.LootDataType; +import net.minecraft.world.level.storage.loot.LootTable; +import org.bukkit.craftbukkit.v.CraftLootTable; +import org.bukkit.craftbukkit.v.util.CraftNamespacedKey; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(LootDataType.class) +public class LootDataTypeMixin { + + @Inject(method = "createLootTableValidator", cancellable = true, at = @At("RETURN")) + private static void arclight$setHandle(CallbackInfoReturnable> cir) { + var validator = cir.getReturnValue(); + cir.setReturnValue((validationContext, resourceKey, object) -> { + validator.run(validationContext, resourceKey, object); + ((LootTableBridge) object).bridge$setCraftLootTable(new CraftLootTable(CraftNamespacedKey.fromMinecraft(resourceKey.location()), object)); + }); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootTableMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootTableMixin.java index cacb9da9c..bd687058b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootTableMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/LootTableMixin.java @@ -1,7 +1,8 @@ package io.izzel.arclight.common.mixin.core.world.level.storage.loot; import io.izzel.arclight.common.bridge.core.world.storage.loot.LootTableBridge; -import io.izzel.arclight.mixin.Eject; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; @@ -21,7 +22,6 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; import java.util.List; @@ -50,9 +50,10 @@ public abstract class LootTableMixin implements LootTableBridge { return this.craftLootTable; } - @Eject(method = "fill", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/loot/LootTable;getRandomItems(Lnet/minecraft/world/level/storage/loot/LootContext;)Lit/unimi/dsi/fastutil/objects/ObjectArrayList;")) - private ObjectArrayList arclight$nonPluginEvent(LootTable lootTable, LootContext context, CallbackInfo ci, Container inv) { - ObjectArrayList list = this.getRandomItems(context); + @SuppressWarnings("unchecked") + @Decorate(method = "fill", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/loot/LootTable;getRandomItems(Lnet/minecraft/world/level/storage/loot/LootContext;)Lit/unimi/dsi/fastutil/objects/ObjectArrayList;")) + private ObjectArrayList arclight$nonPluginEvent(LootTable lootTable, LootContext context, Container inv) throws Throwable { + ObjectArrayList list = (ObjectArrayList) DecorationOps.callsite().invoke(lootTable, context); if (!context.hasParam(LootContextParams.ORIGIN) && !context.hasParam(LootContextParams.THIS_ENTITY)) { return list; } @@ -61,8 +62,7 @@ public abstract class LootTableMixin implements LootTableBridge { } LootGenerateEvent event = CraftEventFactory.callLootGenerateEvent(inv, (LootTable) (Object) this, context, list, false); if (event.isCancelled()) { - ci.cancel(); - return null; + return (ObjectArrayList) DecorationOps.cancel().invoke(); } else { return event.getLoot().stream().map(CraftItemStack::asNMSCopy).collect(ObjectArrayList.toList()); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/functions/LootingEnchantBonusMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/functions/LootingEnchantBonusMixin.java deleted file mode 100644 index b5b5f7d0f..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/functions/LootingEnchantBonusMixin.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.storage.loot.functions; - -import io.izzel.arclight.common.bridge.core.world.storage.loot.LootContextBridge; -import io.izzel.arclight.common.mod.ArclightConstants; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.functions.LootingEnchantFunction; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.level.storage.loot.providers.number.NumberProvider; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(LootingEnchantFunction.class) -public abstract class LootingEnchantBonusMixin { - - // @formatter:off - @Shadow @Final private NumberProvider value; - @Shadow @Final private int limit; - @Shadow protected abstract boolean hasLimit(); - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public ItemStack run(ItemStack stack, LootContext context) { - Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); - if (entity instanceof LivingEntity) { - int i = ((LootContextBridge) context).bridge$forge$getLootingModifier(entity); - if (context.hasParam(ArclightConstants.LOOTING_MOD)) { - i = context.getParamOrNull(ArclightConstants.LOOTING_MOD); - } - if (i <= 0) { - return stack; - } - - float f = (float) i * this.value.getFloat(context); - stack.grow(Math.round(f)); - if (this.hasLimit() && stack.getCount() > this.limit) { - stack.setCount(this.limit); - } - } - - return stack; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/parameters/LootParametersMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/parameters/LootParametersMixin.java deleted file mode 100644 index 4c9933c28..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/parameters/LootParametersMixin.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.storage.loot.parameters; - -import io.izzel.arclight.common.mod.mixins.annotation.TransformAccess; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.storage.loot.parameters.LootContextParam; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import org.objectweb.asm.Opcodes; -import org.spongepowered.asm.mixin.Mixin; - -@Mixin(LootContextParams.class) -public class LootParametersMixin { - - @TransformAccess(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL) - private static final LootContextParam LOOTING_MOD = new LootContextParam<>(new ResourceLocation("bukkit:looting_mod")); -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/predicates/RandomChanceWithLootingMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/predicates/RandomChanceWithLootingMixin.java deleted file mode 100644 index c60101ab1..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/storage/loot/predicates/RandomChanceWithLootingMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.izzel.arclight.common.mixin.core.world.level.storage.loot.predicates; - -import io.izzel.arclight.common.bridge.core.world.storage.loot.LootContextBridge; -import io.izzel.arclight.common.mod.ArclightConstants; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.level.storage.loot.predicates.LootItemRandomChanceWithLootingCondition; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -@Mixin(LootItemRandomChanceWithLootingCondition.class) -public class RandomChanceWithLootingMixin { - - @Shadow @Final private float percent; - @Shadow @Final private float lootingMultiplier; - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean test(LootContext context) { - Entity entity = context.getParamOrNull(LootContextParams.KILLER_ENTITY); - int i = ((LootContextBridge) context).bridge$forge$getLootingModifier(entity); - if (context.hasParam(ArclightConstants.LOOTING_MOD)) { - i = context.getParamOrNull(ArclightConstants.LOOTING_MOD); - } - return context.getRandom().nextFloat() < this.percent + (float) i * this.lootingMultiplier; - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/BaseSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/BaseSpawnerMixin.java index e3fa81874..1ef2f4bd1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/BaseSpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/BaseSpawnerMixin.java @@ -2,55 +2,31 @@ import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.bridge.core.world.spawner.BaseSpawnerBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; import net.minecraft.server.level.ServerLevel; -import net.minecraft.util.RandomSource; import net.minecraft.util.random.SimpleWeightedRandomList; -import net.minecraft.world.Difficulty; -import net.minecraft.world.DifficultyInstance; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntitySelector; -import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.MobSpawnType; -import net.minecraft.world.entity.SpawnGroupData; -import net.minecraft.world.entity.SpawnPlacements; import net.minecraft.world.level.BaseSpawner; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LightLayer; -import net.minecraft.world.level.ServerLevelAccessor; import net.minecraft.world.level.SpawnData; -import net.minecraft.world.level.entity.EntityTypeTest; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.AABB; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.CreatureSpawnEvent; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Optional; - @Mixin(BaseSpawner.class) public abstract class BaseSpawnerMixin implements BaseSpawnerBridge { // @formatter:off @Shadow public SimpleWeightedRandomList spawnPotentials; - @Shadow public int spawnDelay; - @Shadow public int spawnCount; - @Shadow public int spawnRange; - @Shadow public int maxNearbyEntities; - @Shadow protected abstract boolean isNearPlayer(Level p_151344_, BlockPos p_151345_); - @Shadow protected abstract void delay(Level p_151351_, BlockPos p_151352_); - @Shadow protected abstract SpawnData getOrCreateNextSpawnData(@Nullable Level p_254503_, RandomSource p_253892_, BlockPos p_254487_); // @formatter:on @Inject(method = "setEntityId", at = @At("RETURN")) @@ -58,123 +34,19 @@ public abstract class BaseSpawnerMixin implements BaseSpawnerBridge { this.spawnPotentials = SimpleWeightedRandomList.empty(); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void serverTick(ServerLevel level, BlockPos pos) { - if (this.isNearPlayer(level, pos)) { - if (this.spawnDelay == -1) { - this.delay(level, pos); - } - - if (this.spawnDelay > 0) { - --this.spawnDelay; - } else { - boolean flag = false; - RandomSource randomsource = level.getRandom(); - SpawnData spawnData = this.getOrCreateNextSpawnData(level, randomsource, pos); - - for (int i = 0; i < this.spawnCount; ++i) { - CompoundTag compoundtag = spawnData.getEntityToSpawn(); - Optional> optional = EntityType.by(compoundtag); - if (optional.isEmpty()) { - this.delay(level, pos); - return; - } - - ListTag listtag = compoundtag.getList("Pos", 6); - int j = listtag.size(); - double d0 = j >= 1 ? listtag.getDouble(0) : (double) pos.getX() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D; - double d1 = j >= 2 ? listtag.getDouble(1) : (double) (pos.getY() + level.random.nextInt(3) - 1); - double d2 = j >= 3 ? listtag.getDouble(2) : (double) pos.getZ() + (level.random.nextDouble() - level.random.nextDouble()) * (double) this.spawnRange + 0.5D; - if (level.noCollision(optional.get().getAABB(d0, d1, d2))) { - BlockPos blockpos = BlockPos.containing(d0, d1, d2); - if (spawnData.getCustomSpawnRules().isPresent()) { - if (!optional.get().getCategory().isFriendly() && level.getDifficulty() == Difficulty.PEACEFUL) { - continue; - } - - SpawnData.CustomSpawnRules spawndata$customspawnrules = spawnData.getCustomSpawnRules().get(); - if (!spawndata$customspawnrules.blockLightLimit().isValueInRange(level.getBrightness(LightLayer.BLOCK, blockpos)) || !spawndata$customspawnrules.skyLightLimit().isValueInRange(level.getBrightness(LightLayer.SKY, blockpos))) { - continue; - } - } else if (!SpawnPlacements.checkSpawnRules(optional.get(), level, MobSpawnType.SPAWNER, blockpos, level.getRandom())) { - continue; - } - - Entity entity = EntityType.loadEntityRecursive(compoundtag, level, (p_151310_) -> { - p_151310_.moveTo(d0, d1, d2, p_151310_.getYRot(), p_151310_.getXRot()); - return p_151310_; - }); - if (entity == null) { - this.delay(level, pos); - return; - } - - int k = level.getEntities(EntityTypeTest.forExactClass(entity.getClass()), (new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)).inflate(this.spawnRange), EntitySelector.NO_SPECTATORS).size(); - if (k >= this.maxNearbyEntities) { - this.delay(level, pos); - return; - } - - entity.moveTo(entity.getX(), entity.getY(), entity.getZ(), level.random.nextFloat() * 360.0F, 0.0F); - if (entity instanceof Mob mob) { - if (this.bridge$forge$checkSpawnRules(mob, level, MobSpawnType.SPAWNER, spawnData, spawnData.getCustomSpawnRules().isEmpty() && !mob.checkSpawnRules(level, MobSpawnType.SPAWNER) || !mob.checkSpawnObstruction(level))) { - continue; - } - - if (spawnData.getEntityToSpawn().size() == 1 && spawnData.getEntityToSpawn().contains("id", 8)) { - this.bridge$forge$finalizeSpawnerSpawn(mob, level, level.getCurrentDifficultyAt(entity.blockPosition()), null, compoundtag); - } - if (((WorldBridge) mob.level()).bridge$spigotConfig().nerfSpawnerMobs) { - ((MobEntityBridge) mob).bridge$setAware(false); - } - } - - if (CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { - Entity vehicle = entity.getVehicle(); - if (vehicle != null) { - vehicle.discard(); - } - for (Entity passenger : entity.getIndirectPassengers()) { - passenger.discard(); - } - continue; - } - if (CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { - continue; - } - if (!((ServerWorldBridge) level).bridge$addAllEntitiesSafely(entity, CreatureSpawnEvent.SpawnReason.SPAWNER)) { - this.delay(level, pos); - return; - } - - level.levelEvent(2004, pos, 0); - level.gameEvent(entity, GameEvent.ENTITY_PLACE, blockpos); - if (entity instanceof Mob) { - ((Mob) entity).spawnAnim(); - } - - flag = true; - } - } - - if (flag) { - this.delay(level, pos); - } - } + @Decorate(method = "serverTick", inject = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/SpawnData;getEquipment()Ljava/util/Optional;")) + private void arclight$nerf(@Local(ordinal = -1) Mob mob) { + if (((WorldBridge) mob.level()).bridge$spigotConfig().nerfSpawnerMobs) { + ((MobEntityBridge) mob).bridge$setAware(false); } } - @Override - public boolean bridge$forge$checkSpawnRules(Mob mob, ServerLevelAccessor level, MobSpawnType spawnType, SpawnData spawnData, boolean result) { - return result; - } - - @Override - public void bridge$forge$finalizeSpawnerSpawn(Mob mob, ServerLevelAccessor level, DifficultyInstance difficulty, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag spawnTag) { - mob.finalizeSpawn(level, difficulty, MobSpawnType.SPAWNER, spawnData, spawnTag); + @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;tryAddFreshEntityWithPassengers(Lnet/minecraft/world/entity/Entity;)Z")) + private boolean arclight$spawnerSpawn(ServerLevel instance, Entity entity, ServerLevel level, BlockPos pos) throws Throwable { + if (CraftEventFactory.callSpawnerSpawnEvent(entity, pos).isCancelled()) { + throw DecorationOps.jumpToLoopStart(); + } + ((WorldBridge) instance).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.SPAWNER); + return (boolean) DecorationOps.callsite().invoke(instance, entity); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/NaturalSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/NaturalSpawnerMixin.java index ec2bc057d..549f32ee9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/NaturalSpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/NaturalSpawnerMixin.java @@ -51,7 +51,7 @@ public static void spawnForChunk(ServerLevel world, LevelChunk chunk, NaturalSpa SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(classification); if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { spawnThisTick = ((WorldBridge) world).bridge$ticksPerSpawnCategory().getLong(spawnCategory) != 0 && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerSpawnCategory().getLong(spawnCategory) == 0; - limit = ((WorldBridge) world).bridge$getWorld().getSpawnLimit(spawnCategory); + limit = world.bridge$getWorld().getSpawnLimit(spawnCategory); } if (spawnThisTick) { if (limit != 0) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/PlayerDataMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/PlayerDataMixin.java index f9f1ce48d..a7ca731f7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/PlayerDataMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/storage/PlayerDataMixin.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.FileInputStream; +import java.util.Optional; @Mixin(PlayerDataStorage.class) public class PlayerDataMixin implements PlayerDataBridge { @@ -28,16 +29,18 @@ public class PlayerDataMixin implements PlayerDataBridge { @Shadow @Final private static Logger LOGGER; // @formatter:on - @Inject(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtUtils;getDataVersion(Lnet/minecraft/nbt/CompoundTag;I)I")) - private void arclight$lastSeenTime(Player player, CallbackInfoReturnable cir) { - if (player instanceof ServerPlayer) { - CraftPlayer craftPlayer = ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(); - // Only update first played if it is older than the one we have - long modified = new File(this.playerDir, player.getUUID() + ".dat").lastModified(); - if (modified < craftPlayer.getFirstPlayed()) { - craftPlayer.setFirstPlayed(modified); + @Inject(method = "load(Lnet/minecraft/world/entity/player/Player;Ljava/lang/String;)Ljava/util/Optional;", at = @At("RETURN")) + private void arclight$lastSeenTime(Player player, String string, CallbackInfoReturnable> cir) { + cir.getReturnValue().ifPresent((tag) -> { + if (player instanceof ServerPlayer) { + CraftPlayer craftPlayer = ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity(); + // Only update first played if it is older than the one we have + long modified = new File(this.playerDir, player.getUUID() + ".dat").lastModified(); + if (modified < craftPlayer.getFirstPlayed()) { + craftPlayer.setFirstPlayed(modified); + } } - } + }); } public File getPlayerDir() { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/optimization/general/EntityDataManagerMixin_Optimize.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/optimization/general/EntityDataManagerMixin_Optimize.java deleted file mode 100644 index f1ec7c7e2..000000000 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/optimization/general/EntityDataManagerMixin_Optimize.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.izzel.arclight.common.mixin.optimization.general; - -import io.izzel.arclight.common.mod.util.optimization.NoopReadWriteLock; -import net.minecraft.network.syncher.SynchedEntityData; -import net.minecraft.world.entity.Entity; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.concurrent.locks.ReadWriteLock; - -@Mixin(SynchedEntityData.class) -public class EntityDataManagerMixin_Optimize { - - @Shadow @Final @Mutable private ReadWriteLock lock; - - @Inject(method = "", at = @At("RETURN")) - private void optimize$dropLock(Entity entityIn, CallbackInfo ci) { - this.lock = NoopReadWriteLock.instance(); - } -} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/server/Main_ServerShutdownThreadMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/server/Main_ServerShutdownThreadMixin_Vanilla.java index 2490e311d..aed6cb4c8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/server/Main_ServerShutdownThreadMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/server/Main_ServerShutdownThreadMixin_Vanilla.java @@ -1,6 +1,6 @@ package io.izzel.arclight.common.mixin.vanilla.server; -import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.MinecraftServer; import org.spigotmc.AsyncCatcher; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; @@ -9,8 +9,8 @@ @Mixin(targets = "net/minecraft/server/Main$1") public class Main_ServerShutdownThreadMixin_Vanilla { - @Redirect(method = "run", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/dedicated/DedicatedServer;halt(Z)V")) - private void arclight$shutdown(DedicatedServer instance, boolean b) { + @Redirect(method = "run", require = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;halt(Z)V")) + private void arclight$shutdown(MinecraftServer instance, boolean b) { AsyncCatcher.enabled = false; instance.close(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/animal/frog/TadpoleMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/animal/frog/TadpoleMixin_Vanilla.java index 8ba1fce7a..d055d3f66 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/animal/frog/TadpoleMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/animal/frog/TadpoleMixin_Vanilla.java @@ -1,32 +1,9 @@ package io.izzel.arclight.common.mixin.vanilla.world.entity.animal.frog; -import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.animal.frog.Frog; import net.minecraft.world.entity.animal.frog.Tadpole; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Tadpole.class) public abstract class TadpoleMixin_Vanilla { - // @formatter:off - @Shadow protected abstract void setAge(int p_218711_); - // @formatter:on - - @Inject(method = "ageUp()V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void arclight$transform(CallbackInfo ci, ServerLevel serverLevel, Frog frog) { - if (CraftEventFactory.callEntityTransformEvent((Tadpole) (Object) this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { - this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled - ci.cancel(); - } else { - ((ServerWorldBridge) serverLevel).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); - } - } } \ No newline at end of file diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/monster/ZombieMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/monster/ZombieMixin_Vanilla.java index e22cfa486..8f2283b10 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/monster/ZombieMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/monster/ZombieMixin_Vanilla.java @@ -1,27 +1,8 @@ package io.izzel.arclight.common.mixin.vanilla.world.entity.monster; -import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.monster.Zombie; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityTargetEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Zombie.class) public class ZombieMixin_Vanilla { - - @Inject(method = "hurt", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Zombie;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$spawnWithReason(DamageSource source, float amount, CallbackInfoReturnable cir, ServerLevel world, LivingEntity livingEntity, int i, int j, int k, net.minecraft.world.entity.monster.Zombie zombieEntity) { - ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); - if (livingEntity != null) { - ((MobEntityBridge) zombieEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/player/ServerPlayerMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/player/ServerPlayerMixin_Vanilla.java index d7e1b9890..18acc77ac 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/player/ServerPlayerMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/entity/player/ServerPlayerMixin_Vanilla.java @@ -1,37 +1,14 @@ package io.izzel.arclight.common.mixin.vanilla.world.entity.player; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import net.minecraft.core.BlockPos; -import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; -import net.minecraft.network.protocol.game.ClientboundGameEventPacket; -import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; -import net.minecraft.network.protocol.game.ClientboundRespawnPacket; -import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; -import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.Vec3; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v.CraftWorld; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import javax.annotation.Nullable; @@ -45,9 +22,7 @@ public abstract class ServerPlayerMixin_Vanilla extends PlayerMixin_Vanilla impl @Shadow public boolean wonGame; @Shadow public ServerGamePacketListenerImpl connection; @Shadow private boolean seenCredits; - @Shadow @Nullable protected abstract PortalInfo findDimensionEntryPoint(ServerLevel arg); @Shadow @Nullable private Vec3 enteredNetherPosition; - @Shadow protected abstract void createEndPlatform(ServerLevel arg, BlockPos arg2); @Shadow public abstract CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel arg); @Shadow @Final public MinecraftServer server; @Shadow public abstract void setServerLevel(ServerLevel arg); @@ -56,91 +31,4 @@ public abstract class ServerPlayerMixin_Vanilla extends PlayerMixin_Vanilla impl @Shadow private float lastSentHealth; @Shadow private int lastSentFood; // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @Nullable - public Entity changeDimension(ServerLevel server) { - PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN); - if (this.isSleeping()) { - return (ServerPlayer) (Object) this; - } - ServerLevel serverworld = this.serverLevel(); - ResourceKey resourcekey = ((WorldBridge) serverworld).bridge$getTypeKey(); - - if (resourcekey == LevelStem.END && Level.END != null /* fabric dimensions v1 */ && server != null && ((WorldBridge) server).bridge$getTypeKey() == LevelStem.OVERWORLD) { - this.isChangingDimension = true; - this.unRide(); - this.serverLevel().removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - if (!this.wonGame) { - this.wonGame = true; - this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); - this.seenCredits = true; - } - - return (ServerPlayer) (Object) this; - } else { - PortalInfo portalinfo = this.findDimensionEntryPoint(server); - if (portalinfo != null) { - serverworld.getProfiler().push("moving"); - if (((PortalInfoBridge) portalinfo).bridge$getWorld() != null) { - server = ((PortalInfoBridge) portalinfo).bridge$getWorld(); - } - if (resourcekey == LevelStem.OVERWORLD && ((WorldBridge) server).bridge$getTypeKey() == LevelStem.NETHER) { - this.enteredNetherPosition = this.position(); - } else if (((WorldBridge) server).bridge$getTypeKey() == LevelStem.END && (((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo() == null || ((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo().getCanCreatePortal())) { // CraftBukkit - this.createEndPlatform(server, BlockPos.containing(portalinfo.pos)); - } - - Location enter = this.bridge$getBukkitEntity().getLocation(); - Location exit = (server == null) ? null : new Location(server.bridge$getWorld(), portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, portalinfo.xRot); - PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.bridge$getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); - if (tpEvent.isCancelled() || tpEvent.getTo() == null) { - return null; - } - exit = tpEvent.getTo(); - server = ((CraftWorld) exit.getWorld()).getHandle(); - serverworld.getProfiler().pop(); - serverworld.getProfiler().push("placing"); - - this.isChangingDimension = true; - - this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(server), (byte) 3)); - this.connection.send(new ClientboundChangeDifficultyPacket(this.level().getDifficulty(), this.level().getLevelData().isDifficultyLocked())); - PlayerList playerlist = this.server.getPlayerList(); - - playerlist.sendPlayerPermissionLevel((ServerPlayer) (Object) this); - serverworld.removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - this.bridge$revive(); - - this.setServerLevel(server); - ((ServerPlayNetHandlerBridge) this.connection).bridge$teleport(exit); - this.connection.resetPosition(); - server.addDuringPortalTeleport((ServerPlayer) (Object) this); - serverworld.getProfiler().pop(); - this.triggerDimensionChangeTriggers(serverworld); - this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); - playerlist.sendLevelInfo((ServerPlayer) (Object) this, server); - playerlist.sendAllPlayerInfo((ServerPlayer) (Object) this); - - for (MobEffectInstance effectinstance : this.getActiveEffects()) { - this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectinstance)); - } - - this.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); - this.lastSentExp = -1; - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.bridge$getBukkitEntity(), serverworld.bridge$getWorld()); - Bukkit.getPluginManager().callEvent(changeEvent); - } - - return (ServerPlayer) (Object) this; - } - } - } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/item/ItemStackMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/item/ItemStackMixin_Vanilla.java index f2eef0da5..05ccd0472 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/item/ItemStackMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/item/ItemStackMixin_Vanilla.java @@ -3,8 +3,6 @@ import io.izzel.arclight.common.bridge.core.world.WorldBridge; import io.izzel.arclight.common.mod.server.event.ArclightEventFactory; import net.minecraft.core.BlockPos; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; import net.minecraft.stats.Stats; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; @@ -13,7 +11,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.SolidBucketItem; import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.pattern.BlockInWorld; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; @@ -23,7 +20,7 @@ public abstract class ItemStackMixin_Vanilla { // @formatter:off - @Shadow public abstract boolean hasAdventureModePlaceTagForBlock(Registry registry, BlockInWorld blockInWorld); + @Shadow public abstract boolean canPlaceOnBlockInAdventureMode(BlockInWorld blockInWorld); @Shadow public abstract Item getItem(); @Shadow public abstract ItemStack copy(); // @formatter:on @@ -36,8 +33,7 @@ public abstract class ItemStackMixin_Vanilla { public InteractionResult useOn(UseOnContext useOnContext) { Player player = useOnContext.getPlayer(); BlockPos blockPos = useOnContext.getClickedPos(); - BlockInWorld blockInWorld = new BlockInWorld(useOnContext.getLevel(), blockPos, false); - if (player != null && !player.getAbilities().mayBuild && !this.hasAdventureModePlaceTagForBlock(useOnContext.getLevel().registryAccess().registryOrThrow(Registries.BLOCK), blockInWorld)) { + if (player != null && !player.getAbilities().mayBuild && !this.canPlaceOnBlockInAdventureMode(new BlockInWorld(useOnContext.getLevel(), blockPos, false))) { return InteractionResult.PASS; } else { Item item = this.getItem(); @@ -48,7 +44,7 @@ public InteractionResult useOn(UseOnContext useOnContext) { } interactionResult = item.useOn(useOnContext); ((WorldBridge) useOnContext.getLevel()).bridge$platform$endCaptureBlockBreak(); - if (player != null && interactionResult.shouldAwardStats()) { + if (player != null && interactionResult.indicateItemUse()) { interactionResult = ArclightEventFactory.onBlockPlace(useOnContext, player, oldStack, (ItemStack) (Object) this, interactionResult); if (interactionResult != InteractionResult.FAIL) { player.awardStat(Stats.ITEM_USED.get(item)); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/RedstoneOreBlockMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/RedstoneOreBlockMixin_Vanilla.java index f4fa61b1e..b2a1146dd 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/RedstoneOreBlockMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/RedstoneOreBlockMixin_Vanilla.java @@ -1,22 +1,8 @@ package io.izzel.arclight.common.mixin.vanilla.world.level.block; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.block.RedStoneOreBlock; -import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; @Mixin(RedStoneOreBlock.class) public abstract class RedstoneOreBlockMixin_Vanilla extends BlockMixin_Vanilla { - - @Override - public int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) { - if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, itemStack) == 0) { - return 1 + world.random.nextInt(5); - } - return 0; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java index 2eafcaa93..7be8d7ccf 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Vanilla.java @@ -1,75 +1,9 @@ package io.izzel.arclight.common.mixin.vanilla.world.level.block.entity; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v.block.CraftBlock; -import org.bukkit.craftbukkit.v.inventory.CraftItemStack; -import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import javax.annotation.Nullable; @Mixin(AbstractFurnaceBlockEntity.class) public abstract class AbstractFurnaceBlockEntityMixin_Vanilla { - // @formatter:off - @Shadow private static boolean canBurn(RegistryAccess p_266924_, @org.jetbrains.annotations.Nullable RecipeHolder p_155006_, NonNullList p_155007_, int p_155008_) { return false; } - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private static boolean burn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, NonNullList items, int i) { - if (recipe != null && canBurn(registryAccess, recipe, items, i)) { - ItemStack itemstack = items.get(0); - ItemStack itemstack1 = recipe.value().getResultItem(registryAccess); - ItemStack itemstack2 = items.get(2); - - if (ArclightCaptures.getTickingBlockEntity() != null) { - var blockEntity = ArclightCaptures.getTickingBlockEntity(); - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - - FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()), source, result); - Bukkit.getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { - return false; - } - - result = furnaceSmeltEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - } - - if (!itemstack1.isEmpty()) { - if (itemstack2.isEmpty()) { - items.set(2, itemstack1.copy()); - } else if (ItemStack.isSameItemSameTags(itemstack2, itemstack1)) { - itemstack2.grow(itemstack1.getCount()); - } else { - return false; - } - } - - if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) { - items.set(1, new ItemStack(Items.WATER_BUCKET)); - } - - itemstack.shrink(1); - return true; - } else { - return false; - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Vanilla.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Vanilla.java index 819d15bc9..5aec4c95a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Vanilla.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/vanilla/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Vanilla.java @@ -1,224 +1,10 @@ package io.izzel.arclight.common.mixin.vanilla.world.level.levelgen.structure.templatesystem; -import com.google.common.collect.Lists; -import com.mojang.datafixers.util.Pair; import io.izzel.arclight.common.bridge.core.world.level.levelgen.structure.templatesystem.StructureTemplateBridge; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.Vec3i; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.util.RandomSource; -import net.minecraft.world.Clearable; -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.level.ServerLevelAccessor; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlockContainer; -import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.Rotation; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.structure.BoundingBox; -import net.minecraft.world.level.levelgen.structure.templatesystem.StructurePlaceSettings; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; -import net.minecraft.world.phys.shapes.DiscreteVoxelShape; -import org.bukkit.craftbukkit.v.block.CraftBlockEntityState; -import org.bukkit.craftbukkit.v.block.CraftBlockState; -import org.bukkit.craftbukkit.v.block.CraftBlockStates; -import org.bukkit.craftbukkit.v.block.CraftLootable; -import org.bukkit.craftbukkit.v.util.CraftStructureTransformer; -import org.bukkit.craftbukkit.v.util.TransformerGeneratorAccess; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Iterator; -import java.util.List; @Mixin(value = StructureTemplate.class) public abstract class StructureTemplateMixin_Vanilla implements StructureTemplateBridge { - // @formatter:off - @Shadow protected abstract void placeEntities(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, Mirror mirror, Rotation rotation, BlockPos blockPos2, @Nullable BoundingBox boundingBox, boolean bl); - @Shadow @Final public List palettes; - @Shadow @Final public List entityInfoList; - @Shadow private Vec3i size; - @Shadow public static void updateShapeAtEdge(LevelAccessor p_74511_, int p_74512_, DiscreteVoxelShape p_74513_, int p_74514_, int p_74515_, int p_74516_) { } - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean placeInWorld(ServerLevelAccessor p_230329_, BlockPos pos, BlockPos p_230331_, StructurePlaceSettings placeSettings, RandomSource p_230333_, int p_230334_) { - if (this.palettes.isEmpty()) { - return false; - } else { - // CraftBukkit start - // We only want the TransformerGeneratorAccess at certain locations because in here are many "block update" calls that shouldn't be transformed - var wrappedAccess = p_230329_; - CraftStructureTransformer structureTransformer = null; - if (wrappedAccess instanceof TransformerGeneratorAccess transformerAccess) { - p_230329_ = transformerAccess.getHandle(); - structureTransformer = transformerAccess.getStructureTransformer(); - // The structureTransformer is not needed if we can not transform blocks therefore we can save a little bit of performance doing this - if (structureTransformer != null && !structureTransformer.canTransformBlocks()) { - structureTransformer = null; - } - } - // CraftBukkit end - List list = placeSettings.getRandomPalette(this.palettes, pos).blocks(); - if ((!list.isEmpty() || !placeSettings.isIgnoreEntities() && !this.entityInfoList.isEmpty()) && this.size.getX() >= 1 && this.size.getY() >= 1 && this.size.getZ() >= 1) { - BoundingBox boundingbox = placeSettings.getBoundingBox(); - List list1 = Lists.newArrayListWithCapacity(placeSettings.shouldKeepLiquids() ? list.size() : 0); - List list2 = Lists.newArrayListWithCapacity(placeSettings.shouldKeepLiquids() ? list.size() : 0); - List> list3 = Lists.newArrayListWithCapacity(list.size()); - int i = Integer.MAX_VALUE; - int j = Integer.MAX_VALUE; - int k = Integer.MAX_VALUE; - int l = Integer.MIN_VALUE; - int i1 = Integer.MIN_VALUE; - int j1 = Integer.MIN_VALUE; - - for (StructureTemplate.StructureBlockInfo structuretemplate$structureblockinfo : StructureTemplate.processBlockInfos(p_230329_, pos, p_230331_, placeSettings, list)) { - BlockPos blockpos = structuretemplate$structureblockinfo.pos(); - if (boundingbox == null || boundingbox.isInside(blockpos)) { - FluidState fluidstate = placeSettings.shouldKeepLiquids() ? p_230329_.getFluidState(blockpos) : null; - BlockState blockstate = structuretemplate$structureblockinfo.state().mirror(placeSettings.getMirror()).rotate(placeSettings.getRotation()); - if (structuretemplate$structureblockinfo.nbt() != null) { - BlockEntity blockentity = p_230329_.getBlockEntity(blockpos); - Clearable.tryClear(blockentity); - p_230329_.setBlock(blockpos, Blocks.BARRIER.defaultBlockState(), 20); - } - // CraftBukkit start - if (structureTransformer != null) { - var craftBlockState = (CraftBlockState) CraftBlockStates.getBlockState(blockpos, blockstate, null); - if (structuretemplate$structureblockinfo.nbt() != null && craftBlockState instanceof CraftBlockEntityState entityState) { - entityState.loadData(structuretemplate$structureblockinfo.nbt()); - if (craftBlockState instanceof CraftLootable craftLootable) { - craftLootable.setSeed(p_230333_.nextLong()); - } - } - craftBlockState = structureTransformer.transformCraftState(craftBlockState); - blockstate = craftBlockState.getHandle(); - structuretemplate$structureblockinfo = new StructureTemplate.StructureBlockInfo(blockpos, blockstate, (craftBlockState instanceof CraftBlockEntityState craftBlockEntityState ? craftBlockEntityState.getSnapshotNBT() : null)); - } - // CraftBukkit end - - if (p_230329_.setBlock(blockpos, blockstate, p_230334_)) { - i = Math.min(i, blockpos.getX()); - j = Math.min(j, blockpos.getY()); - k = Math.min(k, blockpos.getZ()); - l = Math.max(l, blockpos.getX()); - i1 = Math.max(i1, blockpos.getY()); - j1 = Math.max(j1, blockpos.getZ()); - list3.add(Pair.of(blockpos, structuretemplate$structureblockinfo.nbt())); - if (structuretemplate$structureblockinfo.nbt() != null) { - BlockEntity blockentity1 = p_230329_.getBlockEntity(blockpos); - if (blockentity1 != null) { - if (structureTransformer == null && blockentity1 instanceof RandomizableContainerBlockEntity) { - structuretemplate$structureblockinfo.nbt().putLong("LootTableSeed", p_230333_.nextLong()); - } - - blockentity1.load(structuretemplate$structureblockinfo.nbt()); - } - } - - if (fluidstate != null) { - if (blockstate.getFluidState().isSource()) { - list2.add(blockpos); - } else if (blockstate.getBlock() instanceof LiquidBlockContainer) { - ((LiquidBlockContainer) blockstate.getBlock()).placeLiquid(p_230329_, blockpos, blockstate, fluidstate); - if (!fluidstate.isSource()) { - list1.add(blockpos); - } - } - } - } - } - } - - boolean flag = true; - Direction[] adirection = new Direction[]{Direction.UP, Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; - - while (flag && !list1.isEmpty()) { - flag = false; - Iterator iterator = list1.iterator(); - - while (iterator.hasNext()) { - BlockPos blockpos3 = iterator.next(); - FluidState fluidstate2 = p_230329_.getFluidState(blockpos3); - - for (int i2 = 0; i2 < adirection.length && !fluidstate2.isSource(); ++i2) { - BlockPos blockpos1 = blockpos3.relative(adirection[i2]); - FluidState fluidstate1 = p_230329_.getFluidState(blockpos1); - if (fluidstate1.isSource() && !list2.contains(blockpos1)) { - fluidstate2 = fluidstate1; - } - } - - if (fluidstate2.isSource()) { - BlockState blockstate1 = p_230329_.getBlockState(blockpos3); - Block block = blockstate1.getBlock(); - if (block instanceof LiquidBlockContainer) { - ((LiquidBlockContainer) block).placeLiquid(p_230329_, blockpos3, blockstate1, fluidstate2); - flag = true; - iterator.remove(); - } - } - } - } - - if (i <= l) { - if (!placeSettings.getKnownShape()) { - DiscreteVoxelShape discretevoxelshape = new BitSetDiscreteVoxelShape(l - i + 1, i1 - j + 1, j1 - k + 1); - int k1 = i; - int l1 = j; - int j2 = k; - - for (Pair pair1 : list3) { - BlockPos blockpos2 = pair1.getFirst(); - discretevoxelshape.fill(blockpos2.getX() - k1, blockpos2.getY() - l1, blockpos2.getZ() - j2); - } - - updateShapeAtEdge(p_230329_, p_230334_, discretevoxelshape, k1, l1, j2); - } - - for (Pair pair : list3) { - BlockPos blockpos4 = pair.getFirst(); - if (!placeSettings.getKnownShape()) { - BlockState blockstate2 = p_230329_.getBlockState(blockpos4); - BlockState blockstate3 = Block.updateFromNeighbourShapes(blockstate2, p_230329_, blockpos4); - if (blockstate2 != blockstate3) { - p_230329_.setBlock(blockpos4, blockstate3, p_230334_ & -2 | 16); - } - - p_230329_.blockUpdated(blockpos4, blockstate3.getBlock()); - } - - if (pair.getSecond() != null) { - BlockEntity blockentity2 = p_230329_.getBlockEntity(blockpos4); - if (blockentity2 != null) { - blockentity2.setChanged(); - } - } - } - } - - if (!placeSettings.isIgnoreEntities()) { - this.placeEntities(wrappedAccess, pos, placeSettings.getMirror(), placeSettings.getRotation(), placeSettings.getRotationPivot(), placeSettings.getBoundingBox(), placeSettings.shouldFinalizeEntities()); - } - - return true; - } else { - return false; - } - } - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConstants.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConstants.java index 349057168..0b3f4b352 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConstants.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightConstants.java @@ -6,8 +6,6 @@ import io.izzel.arclight.api.Unsafe; import net.minecraft.util.datafix.DataFixTypes; import net.minecraft.world.level.Level; -import net.minecraft.world.level.storage.loot.parameters.LootContextParam; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import org.bukkit.TreeType; import java.util.List; @@ -17,7 +15,6 @@ public class ArclightConstants { public static final TreeType MOD = EnumHelper.addEnum(TreeType.class, "MOD", ImmutableList.of(), ImmutableList.of()); public static final Level.ExplosionInteraction STANDARD = Unsafe.getStatic(Level.ExplosionInteraction.class, "STANDARD"); - public static final LootContextParam LOOTING_MOD = Unsafe.getStatic(LootContextParams.class, "LOOTING_MOD"); private static final DSL.TypeReference PDC_TYPE = () -> "bukkit_pdc"; public static final DataFixTypes BUKKIT_PDC = EnumHelper.makeEnum(DataFixTypes.class, "BUKKIT_PDC", 0, List.of(DSL.TypeReference.class), List.of(PDC_TYPE)); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java index 04724c6eb..0e261ce59 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/ArclightMixinPlugin.java @@ -7,6 +7,7 @@ import io.izzel.arclight.common.mod.mixins.RenameIntoProcessor; import io.izzel.arclight.common.mod.mixins.ShouldApplyProcessor; import io.izzel.arclight.common.mod.mixins.TransformAccessProcessor; +import io.izzel.arclight.mixin.MixinTools; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -63,5 +64,6 @@ public void postApply(String targetClassName, ClassNode targetClass, String mixi for (var processor : this.postProcessors) { processor.accept(targetClassName, targetClass, mixinInfo); } + MixinTools.onPostMixin(targetClass); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java index 215eb453e..7eae3a80e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java @@ -28,7 +28,6 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.CookingBookCategory; -import net.minecraft.world.item.enchantment.EnchantmentCategory; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.dimension.LevelStem; @@ -90,7 +89,7 @@ public static void registerAll(DedicatedServer console) { loadEntities(); loadVillagerProfessions(); loadBiomes(console); - loadArts(); + loadArts(console); loadStats(); loadSpawnCategory(); loadEndDragonPhase(); @@ -215,18 +214,19 @@ private static void loadStats() { putStatic(CraftStatistic.class, "statistics", STATS); } - private static void loadArts() { + private static void loadArts(DedicatedServer console) { int i = Art.values().length; List newTypes = new ArrayList<>(); Field key = Arrays.stream(Art.class.getDeclaredFields()).filter(it -> it.getName().equals("key")).findAny().orElse(null); long keyOffset = Unsafe.objectFieldOffset(key); - for (var paintingType : BuiltInRegistries.PAINTING_VARIANT) { - var location = BuiltInRegistries.PAINTING_VARIANT.getKey(paintingType); + var reg = console.registryAccess().registryOrThrow(Registries.PAINTING_VARIANT); + for (var paintingType : reg) { + var location = reg.getKey(paintingType); String lookupName = location.getPath().toLowerCase(Locale.ROOT); Art bukkit = Art.getByName(lookupName); if (bukkit == null) { String standardName = ResourceLocationUtil.standardize(location); - bukkit = EnumHelper.makeEnum(Art.class, standardName, i, ImmutableList.of(int.class, int.class, int.class), ImmutableList.of(i, paintingType.getWidth(), paintingType.getHeight())); + bukkit = EnumHelper.makeEnum(Art.class, standardName, i, ImmutableList.of(int.class, int.class, int.class), ImmutableList.of(i, paintingType.width(), paintingType.height())); newTypes.add(bukkit); Unsafe.putObject(bukkit, keyOffset, CraftNamespacedKey.fromMinecraft(location)); ART_BY_ID.put(i, bukkit); @@ -341,7 +341,6 @@ private static void loadEntities() { private static void loadEnchantmentTargets() { int origin = EnchantmentTarget.values().length; - int size = EnchantmentCategory.values().length; // TODO } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/RunnableInPlace.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/RunnableInPlace.java new file mode 100644 index 000000000..d57d6145c --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/RunnableInPlace.java @@ -0,0 +1,12 @@ +package io.izzel.arclight.common.mod.server; + +public interface RunnableInPlace extends Runnable { + + static RunnableInPlace wrap(Runnable r) { + if (r instanceof RunnableInPlace i) { + return i; + } else { + return r::run; + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/block/DispenserBlockHooks.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/block/DispenserBlockHooks.java new file mode 100644 index 000000000..d594899bc --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/block/DispenserBlockHooks.java @@ -0,0 +1,28 @@ +package io.izzel.arclight.common.mod.server.block; + +import net.minecraft.world.level.block.DispenserBlock; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; + +public class DispenserBlockHooks { + + private static final VarHandle H_EVENT_FIRED; + + static { + try { + var field = DispenserBlock.class.getDeclaredField("eventFired"); + H_EVENT_FIRED = MethodHandles.lookup().unreflectVarHandle(field); + } catch (Throwable t) { + throw new ExceptionInInitializerError(t); + } + } + + public static boolean isEventFired() { + return (boolean) H_EVENT_FIRED.get(); + } + + public static void setEventFired(boolean b) { + H_EVENT_FIRED.set(b); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/ArclightModWindCharge.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/ArclightModWindCharge.java new file mode 100644 index 000000000..ae8019920 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/ArclightModWindCharge.java @@ -0,0 +1,12 @@ +package io.izzel.arclight.common.mod.server.entity; + +import net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge; +import org.bukkit.craftbukkit.v.CraftServer; +import org.bukkit.craftbukkit.v.entity.CraftAbstractWindCharge; + +public class ArclightModWindCharge extends CraftAbstractWindCharge { + + public ArclightModWindCharge(CraftServer server, AbstractWindCharge entity) { + super(server, entity); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/EntityClassLookup.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/EntityClassLookup.java index 35cb31211..1bff752b0 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/EntityClassLookup.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/entity/EntityClassLookup.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mod.server.entity; import io.izzel.arclight.common.bridge.bukkit.EntityTypeBridge; -import io.izzel.arclight.common.bridge.core.entity.projectile.DamagingProjectileEntityBridge; import io.izzel.arclight.common.mod.server.ArclightServer; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; @@ -18,6 +17,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Marker; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.OminousItemSpawner; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.TamableAnimal; import net.minecraft.world.entity.ambient.AmbientCreature; @@ -50,6 +50,7 @@ import net.minecraft.world.entity.animal.WaterAnimal; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.animal.allay.Allay; +import net.minecraft.world.entity.animal.armadillo.Armadillo; import net.minecraft.world.entity.animal.axolotl.Axolotl; import net.minecraft.world.entity.animal.camel.Camel; import net.minecraft.world.entity.animal.frog.Frog; @@ -81,6 +82,7 @@ import net.minecraft.world.entity.monster.AbstractIllager; import net.minecraft.world.entity.monster.AbstractSkeleton; import net.minecraft.world.entity.monster.Blaze; +import net.minecraft.world.entity.monster.Bogged; import net.minecraft.world.entity.monster.CaveSpider; import net.minecraft.world.entity.monster.Creeper; import net.minecraft.world.entity.monster.Drowned; @@ -146,8 +148,10 @@ 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.WindCharge; import net.minecraft.world.entity.projectile.WitherSkull; +import net.minecraft.world.entity.projectile.windcharge.AbstractWindCharge; +import net.minecraft.world.entity.projectile.windcharge.BreezeWindCharge; +import net.minecraft.world.entity.projectile.windcharge.WindCharge; import net.minecraft.world.entity.raid.Raider; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.AbstractMinecartContainer; @@ -161,10 +165,12 @@ import net.minecraft.world.entity.vehicle.MinecartSpawner; import net.minecraft.world.entity.vehicle.MinecartTNT; import net.minecraft.world.entity.vehicle.VehicleEntity; +import net.minecraft.world.phys.Vec3; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.entity.CraftEntity; import org.bukkit.craftbukkit.v.entity.CraftEntityType; import org.bukkit.craftbukkit.v.entity.CraftEntityTypes; +import org.bukkit.util.Vector; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -291,8 +297,8 @@ private static T spawnDynamic(EntityClass entityClass, org return null; } if (entity instanceof AbstractHurtingProjectile) { - var direction = spawnData.location().getDirection().multiply(10); - ((DamagingProjectileEntityBridge) entity).bridge$setDirection(direction.getX(), direction.getY(), direction.getZ()); + Vector direction = spawnData.location().getDirection(); + ((AbstractHurtingProjectile) entity).assignDirectionalMovement(new Vec3(direction.getX(), direction.getY(), direction.getZ()), 1.0); } if (entity instanceof HangingEntity) { createHanging((Class) entityClass.bukkitClass, (a, direction) -> { @@ -341,12 +347,13 @@ private static Class forName(String name) { add(Projectile.class, new EntityClass<>(org.bukkit.entity.Projectile.class, ArclightModProjectile.class, ArclightModProjectile::new)); add(Raider.class, new EntityClass<>(org.bukkit.entity.Raider.class, ArclightModRaider.class, ArclightModRaider::new)); add(VehicleEntity.class, new EntityClass<>(org.bukkit.entity.Vehicle.class, ArclightModVehicle.class, ArclightModVehicle::new)); + add(AbstractWindCharge.class, new EntityClass<>(org.bukkit.entity.AbstractWindCharge.class, ArclightModWindCharge.class, ArclightModWindCharge::new)); add(LivingEntity.class, new EntityClass<>(org.bukkit.entity.LivingEntity.class, org.bukkit.craftbukkit.v.entity.CraftLivingEntity.class, org.bukkit.craftbukkit.v.entity.CraftLivingEntity::new)); add(Monster.class, new EntityClass<>(org.bukkit.entity.Monster.class, org.bukkit.craftbukkit.v.entity.CraftMonster.class, org.bukkit.craftbukkit.v.entity.CraftMonster::new)); add(PathfinderMob.class, new EntityClass<>(org.bukkit.entity.Creature.class, org.bukkit.craftbukkit.v.entity.CraftCreature.class, org.bukkit.craftbukkit.v.entity.CraftCreature::new)); add(AgeableMob.class, new EntityClass<>(org.bukkit.entity.Ageable.class, org.bukkit.craftbukkit.v.entity.CraftAgeable.class, org.bukkit.craftbukkit.v.entity.CraftAgeable::new)); add(AbstractVillager.class, new EntityClass<>(org.bukkit.entity.AbstractVillager.class, org.bukkit.craftbukkit.v.entity.CraftAbstractVillager.class, org.bukkit.craftbukkit.v.entity.CraftAbstractVillager::new)); - add(AbstractArrow.class, new EntityClass<>(org.bukkit.entity.AbstractArrow.class, org.bukkit.craftbukkit.v.entity.CraftArrow.class, org.bukkit.craftbukkit.v.entity.CraftArrow::new)); + add(AbstractArrow.class, new EntityClass<>(org.bukkit.entity.AbstractArrow.class, org.bukkit.craftbukkit.v.entity.CraftAbstractArrow.class, org.bukkit.craftbukkit.v.entity.CraftAbstractArrow::new)); add(Animal.class, new EntityClass<>(org.bukkit.entity.Animals.class, org.bukkit.craftbukkit.v.entity.CraftAnimals.class, org.bukkit.craftbukkit.v.entity.CraftAnimals::new)); add(Fireball.class, new EntityClass<>(org.bukkit.entity.SizedFireball.class, org.bukkit.craftbukkit.v.entity.CraftSizedFireball.class, org.bukkit.craftbukkit.v.entity.CraftSizedFireball::new)); add(AbstractHurtingProjectile.class, new EntityClass<>(org.bukkit.entity.Fireball.class, org.bukkit.craftbukkit.v.entity.CraftFireball.class, org.bukkit.craftbukkit.v.entity.CraftFireball::new)); @@ -455,7 +462,7 @@ private static Class forName(String name) { add(Painting.class, new EntityClass<>(org.bukkit.entity.Painting.class, org.bukkit.craftbukkit.v.entity.CraftPainting.class, org.bukkit.craftbukkit.v.entity.CraftPainting::new)); add(ItemFrame.class, new EntityClass<>(org.bukkit.entity.ItemFrame.class, org.bukkit.craftbukkit.v.entity.CraftItemFrame.class, org.bukkit.craftbukkit.v.entity.CraftItemFrame::new)); add(GlowItemFrame.class, new EntityClass<>(org.bukkit.entity.GlowItemFrame.class, org.bukkit.craftbukkit.v.entity.CraftGlowItemFrame.class, org.bukkit.craftbukkit.v.entity.CraftGlowItemFrame::new)); - add(Arrow.class, new EntityClass<>(org.bukkit.entity.Arrow.class, org.bukkit.craftbukkit.v.entity.CraftTippedArrow.class, org.bukkit.craftbukkit.v.entity.CraftTippedArrow::new)); + add(Arrow.class, new EntityClass<>(org.bukkit.entity.Arrow.class, org.bukkit.craftbukkit.v.entity.CraftArrow.class, org.bukkit.craftbukkit.v.entity.CraftArrow::new)); add(ThrownEnderpearl.class, new EntityClass<>(org.bukkit.entity.EnderPearl.class, org.bukkit.craftbukkit.v.entity.CraftEnderPearl.class, org.bukkit.craftbukkit.v.entity.CraftEnderPearl::new)); add(ThrownExperienceBottle.class, new EntityClass<>(org.bukkit.entity.ThrownExpBottle.class, org.bukkit.craftbukkit.v.entity.CraftThrownExpBottle.class, org.bukkit.craftbukkit.v.entity.CraftThrownExpBottle::new)); add(SpectralArrow.class, new EntityClass<>(org.bukkit.entity.SpectralArrow.class, org.bukkit.craftbukkit.v.entity.CraftSpectralArrow.class, org.bukkit.craftbukkit.v.entity.CraftSpectralArrow::new)); @@ -492,5 +499,9 @@ private static Class forName(String name) { add(MinecartSpawner.class, new EntityClass<>(org.bukkit.entity.minecart.SpawnerMinecart.class, forName("CraftMinecartMobSpawner"), CraftEntityTypes.getEntityTypeData(org.bukkit.entity.minecart.SpawnerMinecart.class).convertFunction()::apply)); add(FishingHook.class, new EntityClass<>(org.bukkit.entity.FishHook.class, org.bukkit.craftbukkit.v.entity.CraftFishHook.class, org.bukkit.craftbukkit.v.entity.CraftFishHook::new)); add(ServerPlayer.class, new EntityClass<>(org.bukkit.entity.Player.class, org.bukkit.craftbukkit.v.entity.CraftPlayer.class, org.bukkit.craftbukkit.v.entity.CraftPlayer::new)); + add(Bogged.class, new EntityClass<>(org.bukkit.entity.Bogged.class, org.bukkit.craftbukkit.v.entity.CraftBogged.class, org.bukkit.craftbukkit.v.entity.CraftBogged::new)); + add(OminousItemSpawner.class, new EntityClass<>(org.bukkit.entity.OminousItemSpawner.class, org.bukkit.craftbukkit.v.entity.CraftOminousItemSpawner.class, org.bukkit.craftbukkit.v.entity.CraftOminousItemSpawner::new)); + add(Armadillo.class, new EntityClass<>(org.bukkit.entity.Armadillo.class, org.bukkit.craftbukkit.v.entity.CraftArmadillo.class, org.bukkit.craftbukkit.v.entity.CraftArmadillo::new)); + add(BreezeWindCharge.class, new EntityClass<>(org.bukkit.entity.BreezeWindCharge.class, org.bukkit.craftbukkit.v.entity.CraftBreezeWindCharge.class, org.bukkit.craftbukkit.v.entity.CraftBreezeWindCharge::new)); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventFactory.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventFactory.java index 3e1857556..0b35f2a8a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventFactory.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventFactory.java @@ -2,16 +2,17 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayerGameMode; import net.minecraft.world.InteractionResult; +import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.BedItem; @@ -22,16 +23,14 @@ import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.block.CraftBlockState; +import org.bukkit.craftbukkit.v.damage.CraftDamageSource; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityDropItemEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.EntityResurrectEvent; import org.bukkit.inventory.ItemStack; import java.util.List; @@ -43,31 +42,14 @@ public static void callEvent(Event event) { Bukkit.getPluginManager().callEvent(event); } - public static EntityRegainHealthEvent callEntityRegainHealthEvent(Entity entity, float amount, EntityRegainHealthEvent.RegainReason regainReason) { - EntityRegainHealthEvent event = new EntityRegainHealthEvent(entity, amount, regainReason); - callEvent(event); - return event; - } - - public static EntityResurrectEvent callEntityResurrectEvent(org.bukkit.entity.LivingEntity livingEntity) { - EntityResurrectEvent event = new EntityResurrectEvent(livingEntity); - callEvent(event); - return event; - } - - public static void callEntityDeathEvent(LivingEntity entity, List drops) { + public static void callEntityDeathEvent(LivingEntity entity, List drops, DamageSource damageSource) { + CraftDamageSource bukkitDamageSource = new CraftDamageSource(damageSource); CraftLivingEntity craftLivingEntity = ((LivingEntityBridge) entity).bridge$getBukkitEntity(); - EntityDeathEvent event = new EntityDeathEvent(craftLivingEntity, drops, ((LivingEntityBridge) entity).bridge$getExpReward()); + EntityDeathEvent event = new EntityDeathEvent(craftLivingEntity, bukkitDamageSource, drops, ((LivingEntityBridge) entity).bridge$getExpReward(entity)); callEvent(event); ((LivingEntityBridge) entity).bridge$setExpToDrop(event.getDroppedExp()); } - public static EntityDeathEvent callEntityDeathEvent(org.bukkit.entity.LivingEntity entity, List drops, int droppedExp) { - EntityDeathEvent event = new EntityDeathEvent(entity, drops, droppedExp); - callEvent(event); - return event; - } - public static EntityDropItemEvent callEntityDropItemEvent(org.bukkit.entity.Entity entity, org.bukkit.entity.Item drop) { EntityDropItemEvent bukkitEvent = new EntityDropItemEvent(entity, drop); callEvent(bukkitEvent); @@ -139,19 +121,13 @@ public static InteractionResult onBlockPlace(UseOnContext context, net.minecraft // save new item data int newSize = currentStack.getCount(); - CompoundTag newNBT = null; - if (currentStack.getTag() != null) { - newNBT = currentStack.getTag().copy(); - } + var newPatch = currentStack.getComponentsPatch(); int size = oldStack.getCount(); - CompoundTag nbt = null; - if (oldStack.getTag() != null) { - nbt = oldStack.getTag().copy(); - } + var oldPatch = oldStack.getComponentsPatch(); currentStack.setCount(size); - currentStack.setTag(nbt); + ((ItemStackBridge) (Object) currentStack).bridge$restorePatch(oldPatch); if (blocks.size() > 1) { placeEvent = CraftEventFactory.callBlockMultiPlaceEvent(world, player, enumhand, blocks, blockposition.getX(), blockposition.getY(), blockposition.getZ()); @@ -178,8 +154,8 @@ public static InteractionResult onBlockPlace(UseOnContext context, net.minecraft // ItemSign.openSign = null; // SPIGOT-6758 - Reset on early return } else { // Change the stack to its new contents if it hasn't been tampered with. - if (currentStack.getCount() == size && Objects.equals(currentStack.getTag(), nbt)) { - currentStack.setTag(newNBT); + if (currentStack.getCount() == size && Objects.equals(currentStack.getComponentsPatch(), oldPatch)) { + ((ItemStackBridge) (Object) currentStack).bridge$restorePatch(newPatch); currentStack.setCount(newSize); } @@ -192,7 +168,7 @@ public static InteractionResult onBlockPlace(UseOnContext context, net.minecraft var oldBlock = ((CraftBlockState) blockstate).getHandle(); var newblockposition = ((CraftBlockState) blockstate).getPosition(); var block = world.getBlockState(newblockposition); - block.getBlock().onPlace(block, world, newblockposition, oldBlock, true); + block.onPlace(world, newblockposition, oldBlock, true); ((WorldBridge) world).bridge$forge$notifyAndUpdatePhysics(newblockposition, null, oldBlock, block, updateFlag, 512); // send null chunk as chunk.k() returns false by this point } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/world/LevelPersistentData.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/world/LevelPersistentData.java index d8c8bee81..f4fd64675 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/world/LevelPersistentData.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/world/LevelPersistentData.java @@ -1,6 +1,7 @@ package io.izzel.arclight.common.mod.server.world; import io.izzel.arclight.common.mod.ArclightConstants; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.saveddata.SavedData; import org.bukkit.craftbukkit.v.CraftWorld; @@ -10,7 +11,7 @@ public class LevelPersistentData extends SavedData { private CompoundTag tag; - public LevelPersistentData(CompoundTag tag) { + public LevelPersistentData(CompoundTag tag, HolderLookup.Provider provider) { this.tag = tag == null ? new CompoundTag() : tag; } @@ -24,11 +25,11 @@ public void save(CraftWorld world) { } @Override - public @NotNull CompoundTag save(@NotNull CompoundTag it) { + public @NotNull CompoundTag save(@NotNull CompoundTag it, @NotNull HolderLookup.Provider provider) { return tag; } public static Factory factory() { - return new SavedData.Factory<>(() -> new LevelPersistentData(null), LevelPersistentData::new, ArclightConstants.BUKKIT_PDC); + return new SavedData.Factory<>(() -> new LevelPersistentData(null, null), LevelPersistentData::new, ArclightConstants.BUKKIT_PDC); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java index c2cba42a3..3976853fb 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java @@ -38,6 +38,16 @@ public static Entity getEntityChangeBlock() { } } + private static boolean lastEntityChangeBlockResult; + + public static boolean getLastEntityChangeBlockResult() { + return lastEntityChangeBlockResult; + } + + public static boolean setLastEntityChangeBlockResult(boolean b) { + return lastEntityChangeBlockResult = b; + } + /** * Indicates that next BlockBreakEvent is fired directly by ServerPlayerGameMode#destroyBlock * and need to be captured as primary event. diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCustomQueryAnswerPayload.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCustomQueryAnswerPayload.java new file mode 100644 index 000000000..9e808ffa3 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCustomQueryAnswerPayload.java @@ -0,0 +1,13 @@ +package io.izzel.arclight.common.mod.util; + +import io.netty.buffer.ByteBuf; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; + +public record ArclightCustomQueryAnswerPayload(ByteBuf buf) implements CustomQueryAnswerPayload { + + @Override + public void write(FriendlyByteBuf friendlyByteBuf) { + friendlyByteBuf.writeBytes(buf.slice()); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/Blackhole.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/Blackhole.java index 2188f2562..2c26a2de8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/Blackhole.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/Blackhole.java @@ -1,7 +1,21 @@ package io.izzel.arclight.common.mod.util; +import org.jetbrains.annotations.Contract; + public class Blackhole { public static void consume(Object o) { } + + @SuppressWarnings("Contract") + @Contract("-> fail") + public static boolean actuallyFalse() { + return false; + } + + @SuppressWarnings("Contract") + @Contract("-> fail") + public static T nonConstant(T value) { + return value; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ClassDump.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ClassDump.java new file mode 100644 index 000000000..9a1292bb9 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ClassDump.java @@ -0,0 +1,13 @@ +package io.izzel.arclight.common.mod.util; + +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.util.TraceClassVisitor; + +import java.io.PrintWriter; + +public class ClassDump { + + public static void print(ClassNode classNode) { + classNode.accept(new TraceClassVisitor(new PrintWriter(System.out))); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DelegateWorldInfo.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DelegateWorldInfo.java index dc0c1c642..7a6cd65f3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DelegateWorldInfo.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DelegateWorldInfo.java @@ -3,11 +3,13 @@ import com.mojang.serialization.Lifecycle; import io.izzel.arclight.common.bridge.core.world.storage.DerivedWorldInfoBridge; import io.izzel.arclight.common.bridge.core.world.storage.WorldInfoBridge; +import net.minecraft.CrashReportCategory; import net.minecraft.core.BlockPos; import net.minecraft.server.MinecraftServer; import net.minecraft.world.Difficulty; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.GameType; +import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelSettings; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.level.levelgen.WorldOptions; @@ -15,6 +17,7 @@ import net.minecraft.world.level.storage.PrimaryLevelData; import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.timers.TimerQueue; +import org.jetbrains.annotations.Nullable; import java.util.UUID; @@ -28,21 +31,6 @@ public DelegateWorldInfo(LevelSettings p_251081_, WorldOptions p_251666_, Specia this.derivedWorldInfo = derivedLevelData; } - @Override - public int getXSpawn() { - return derivedWorldInfo.getXSpawn(); - } - - @Override - public int getYSpawn() { - return derivedWorldInfo.getYSpawn(); - } - - @Override - public int getZSpawn() { - return derivedWorldInfo.getZSpawn(); - } - @Override public float getSpawnAngle() { return derivedWorldInfo.getSpawnAngle(); @@ -98,26 +86,6 @@ public GameType getGameType() { return derivedWorldInfo.getGameType(); } - @Override - public void setXSpawn(int x) { - derivedWorldInfo.setXSpawn(x); - } - - @Override - public void setYSpawn(int y) { - derivedWorldInfo.setYSpawn(y); - } - - @Override - public void setZSpawn(int z) { - derivedWorldInfo.setZSpawn(z); - } - - @Override - public void setSpawnAngle(float angle) { - derivedWorldInfo.setSpawnAngle(angle); - } - @Override public void setGameTime(long time) { derivedWorldInfo.setGameTime(time); @@ -164,8 +132,8 @@ public boolean isHardcore() { } @Override - public boolean getAllowCommands() { - return derivedWorldInfo.getAllowCommands(); + public boolean isAllowCommands() { + return derivedWorldInfo.isAllowCommands(); } @Override @@ -228,11 +196,27 @@ public void setWanderingTraderSpawnChance(int chance) { derivedWorldInfo.setWanderingTraderSpawnChance(chance); } + @Nullable + @Override + public UUID getWanderingTraderId() { + return derivedWorldInfo.getWanderingTraderId(); + } + @Override public void setWanderingTraderId(UUID id) { derivedWorldInfo.setWanderingTraderId(id); } + @Override + public void fillCrashReportCategory(CrashReportCategory crashReportCategory, LevelHeightAccessor levelHeightAccessor) { + derivedWorldInfo.fillCrashReportCategory(crashReportCategory, levelHeightAccessor); + } + + @Override + public BlockPos getSpawnPos() { + return derivedWorldInfo.getSpawnPos(); + } + public static DelegateWorldInfo wrap(DerivedLevelData worldInfo) { return new DelegateWorldInfo(worldSettings(worldInfo), generatorSettings(worldInfo), specialWorldProperty(worldInfo), lifecycle(worldInfo), worldInfo); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DiscardedPayloadCodec.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DiscardedPayloadCodec.java new file mode 100644 index 000000000..666362970 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/DiscardedPayloadCodec.java @@ -0,0 +1,29 @@ +package io.izzel.arclight.common.mod.util; + +import io.izzel.arclight.common.bridge.core.network.common.DiscardedPayloadBridge; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.network.protocol.common.custom.DiscardedPayload; +import net.minecraft.resources.ResourceLocation; + +public class DiscardedPayloadCodec { + + public static StreamCodec codec(ResourceLocation resourceLocation, int i) { + return CustomPacketPayload.codec((discardedPayload, friendlyByteBuf) -> { + var data = ((DiscardedPayloadBridge) (Object) discardedPayload).bridge$getData(); + if (data != null) { + friendlyByteBuf.writeBytes(data); + } + }, (friendlyByteBuf) -> { + int j = friendlyByteBuf.readableBytes(); + if (j >= 0 && j <= i) { + var payload = new DiscardedPayload(resourceLocation); + ((DiscardedPayloadBridge) (Object) payload).bridge$setData(friendlyByteBuf.readBytes(j)); + return payload; + } else { + throw new IllegalArgumentException("Payload may not be larger than " + i + " bytes"); + } + }); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/EntityDamageResult.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/EntityDamageResult.java new file mode 100644 index 000000000..2970fd32b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/EntityDamageResult.java @@ -0,0 +1,14 @@ +package io.izzel.arclight.common.mod.util; + +public record EntityDamageResult( + boolean damageOverride, + float originalDamage, + float finalDamage, + float damageOffset, + float originalArmorDamage, + float armorDamageOffset, + boolean helmetHurtCancelled, + boolean armorHurtCancelled, + boolean blockingCancelled +) { +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/VelocitySupport.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/VelocitySupport.java index fe0066ed5..1b8d5d80a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/VelocitySupport.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/VelocitySupport.java @@ -7,7 +7,6 @@ import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.login.custom.CustomQueryPayload; -import net.minecraft.network.protocol.login.custom.DiscardedQueryPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.ProfilePublicKey; import org.jetbrains.annotations.NotNull; @@ -34,7 +33,7 @@ public static boolean isEnabled() { public static final int MODERN_FORWARDING_WITH_KEY_V2 = 3; public static final int MODERN_LAZY_SESSION = 4; public static final byte MAX_SUPPORTED_FORWARDING_VERSION = MODERN_LAZY_SESSION; - public static final ResourceLocation PLAYER_INFO_CHANNEL = new ResourceLocation("velocity", "player_info"); + public static final ResourceLocation PLAYER_INFO_CHANNEL = ResourceLocation.parse("velocity:player_info"); private record VelocityForwardQuery(FriendlyByteBuf data) implements CustomQueryPayload { diff --git a/arclight-common/src/main/resources/arclight.accesswidener b/arclight-common/src/main/resources/arclight.accesswidener index 4c71db6af..517195cfa 100644 --- a/arclight-common/src/main/resources/arclight.accesswidener +++ b/arclight-common/src/main/resources/arclight.accesswidener @@ -1,4 +1,9 @@ accessWidener v2 named +# Arclight 1.21 +accessible field net/minecraft/core/component/DataComponentPatch map Lit/unimi/dsi/fastutil/objects/Reference2ObjectMap; +accessible field net/minecraft/core/component/DataComponentPatch$Builder map Lit/unimi/dsi/fastutil/objects/Reference2ObjectMap; +accessible field net/minecraft/world/level/block/entity/HopperBlockEntity facing Lnet/minecraft/core/Direction; +accessible field net/minecraft/world/item/JukeboxSongPlayer ticksSinceSongStarted J # Arclight 1.20.4 accessible method net/minecraft/world/level/block/entity/HopperBlockEntity setCooldown (I)V accessible class net/minecraft/world/inventory/MenuType$MenuSupplier @@ -8,7 +13,6 @@ accessible method net/minecraft/world/entity/item/PrimedTnt explode ()V extendable class net/minecraft/world/item/crafting/Ingredient accessible method net/minecraft/world/damagesource/DamageSource (Lnet/minecraft/core/Holder;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V accessible method net/minecraft/server/level/ServerLevel getEntities ()Lnet/minecraft/world/level/entity/LevelEntityGetter; -accessible field net/minecraft/world/entity/animal/MushroomCow stewEffects Ljava/util/List; accessible field net/minecraft/world/entity/LivingEntity useItemRemaining I accessible method net/minecraft/world/level/block/entity/ConduitBlockEntity getDestroyRangeAABB (Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/phys/AABB; accessible field net/minecraft/world/level/block/entity/ConduitBlockEntity effectBlocks Ljava/util/List; @@ -20,8 +24,6 @@ accessible field net/minecraft/world/level/chunk/storage/ChunkSerializer BLOCK_S accessible field net/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase destroySpeed F accessible field net/minecraft/world/entity/raid/Raids raidMap Ljava/util/Map; accessible class net/minecraft/world/level/block/entity/BeehiveBlockEntity$BeeData -accessible field net/minecraft/world/level/block/entity/BeehiveBlockEntity$BeeData entityData Lnet/minecraft/nbt/CompoundTag; -accessible method net/minecraft/world/entity/projectile/Fireball getItemRaw ()Lnet/minecraft/world/item/ItemStack; accessible method net/minecraft/server/WorldLoader loadAndReplaceLayer (Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/LayeredRegistryAccess;Lnet/minecraft/server/RegistryLayer;Ljava/util/List;)Lnet/minecraft/core/LayeredRegistryAccess; accessible field net/minecraft/world/SimpleContainer items Lnet/minecraft/core/NonNullList; accessible field net/minecraft/server/dedicated/Settings properties Ljava/util/Properties; @@ -34,15 +36,11 @@ accessible method net/minecraft/world/entity/animal/allay/Allay canDuplicate ()Z accessible field net/minecraft/world/item/trading/MerchantOffer maxUses I mutable field net/minecraft/world/item/trading/MerchantOffer maxUses I accessible field net/minecraft/world/item/trading/MerchantOffer result Lnet/minecraft/world/item/ItemStack; -accessible field net/minecraft/world/item/trading/MerchantOffer costB Lnet/minecraft/world/item/ItemStack; -mutable field net/minecraft/world/item/trading/MerchantOffer costB Lnet/minecraft/world/item/ItemStack; accessible field net/minecraft/world/item/trading/MerchantOffer xp I accessible field net/minecraft/world/item/trading/MerchantOffer uses I accessible field net/minecraft/world/item/trading/MerchantOffer priceMultiplier F accessible field net/minecraft/world/item/trading/MerchantOffer specialPriceDiff I accessible field net/minecraft/world/item/trading/MerchantOffer demand I -accessible field net/minecraft/world/item/trading/MerchantOffer baseCostA Lnet/minecraft/world/item/ItemStack; -mutable field net/minecraft/world/item/trading/MerchantOffer baseCostA Lnet/minecraft/world/item/ItemStack; accessible field net/minecraft/world/item/trading/MerchantOffer rewardExp Z accessible field net/minecraft/world/food/FoodData saturationLevel F accessible field net/minecraft/world/food/FoodData foodLevel I @@ -74,8 +72,6 @@ accessible method net/minecraft/world/level/saveddata/maps/MapItemSavedData setD accessible field net/minecraft/world/level/levelgen/structure/templatesystem/StructurePlaceSettings palette I accessible field net/minecraft/world/item/ItemCooldowns tickCount I accessible field net/minecraft/world/item/ItemCooldowns cooldowns Ljava/util/Map; -accessible field net/minecraft/world/item/crafting/RecipeManager recipes Ljava/util/Map; -mutable field net/minecraft/world/item/crafting/RecipeManager recipes Ljava/util/Map; accessible class net/minecraft/world/level/biome/Biome$ClimateSettings accessible field net/minecraft/network/protocol/game/ServerboundMovePlayerPacket yRot F accessible field net/minecraft/network/protocol/game/ServerboundMovePlayerPacket xRot F @@ -106,7 +102,6 @@ accessible field net/minecraft/world/entity/player/Abilities walkingSpeed F accessible field net/minecraft/world/entity/animal/frog/Tadpole age I accessible method net/minecraft/world/level/block/entity/SculkCatalystBlockEntity$CatalystListener bloom (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/util/RandomSource;)V # TODO field net/minecraft/world/inventory/CraftingContainer f_39323_ -accessible field net/minecraft/world/level/block/entity/BrushableBlockEntity lootTable Lnet/minecraft/resources/ResourceLocation; accessible field net/minecraft/world/level/block/entity/BrushableBlockEntity item Lnet/minecraft/world/item/ItemStack; accessible field net/minecraft/world/level/block/entity/BrushableBlockEntity lootTableSeed J accessible method net/minecraft/nbt/ListTag (Ljava/util/List;B)V @@ -116,7 +111,6 @@ accessible method net/minecraft/world/level/biome/Biome getTemperature (Lnet/min accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State accessible field net/minecraft/world/level/storage/PrimaryLevelData settings Lnet/minecraft/world/level/LevelSettings; accessible field net/minecraft/world/entity/projectile/AbstractArrow inGround Z -accessible field net/minecraft/world/entity/projectile/AbstractArrow knockback I accessible field net/minecraft/world/entity/projectile/AbstractArrow pickupItemStack Lnet/minecraft/world/item/ItemStack; accessible field net/minecraft/world/entity/projectile/AbstractArrow life I # TODO accessible method net/minecraft/world/entity/monster/MagmaCube m_7839_ (IZ)V @@ -142,7 +136,6 @@ accessible field net/minecraft/world/entity/animal/horse/AbstractHorse inventory accessible method net/minecraft/world/entity/animal/horse/AbstractHorse createInventory ()V accessible field net/minecraft/world/scores/Objective displayName Lnet/minecraft/network/chat/Component; accessible class net/minecraft/world/entity/Interaction$PlayerAction -accessible method net/minecraft/world/entity/projectile/WindCharge explode ()V accessible field net/minecraft/world/level/Level thunderLevel F accessible field net/minecraft/world/level/Level thread Ljava/lang/Thread; accessible field net/minecraft/world/level/Level rainLevel F @@ -170,7 +163,6 @@ accessible method net/minecraft/world/entity/animal/Fox setSleeping (Z)V # TODO accessible method net/minecraft/world/level/GameRules$IntegerValue m_7377_ (Ljava/lang/String;)V accessible field net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager structureRepository Ljava/util/Map; accessible method net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager loadFromGenerated (Lnet/minecraft/resources/ResourceLocation;)Ljava/util/Optional; -accessible method net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager createAndValidatePathToStructure (Ljava/nio/file/Path;Lnet/minecraft/resources/ResourceLocation;Ljava/lang/String;)Ljava/nio/file/Path; accessible method net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager loadFromResource (Lnet/minecraft/resources/ResourceLocation;)Ljava/util/Optional; accessible method net/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplateManager readStructure (Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/world/level/levelgen/structure/templatesystem/StructureTemplate; accessible method net/minecraft/world/entity/animal/horse/Horse setVariantAndMarkings (Lnet/minecraft/world/entity/animal/horse/Variant;Lnet/minecraft/world/entity/animal/horse/Markings;)V @@ -204,7 +196,6 @@ accessible class net/minecraft/server/level/DistanceManager$FixedPlayerDistanceC # TODO field net/minecraft/world/level/chunk/ChunkBiomeContainer f_62111_ accessible field net/minecraft/world/level/block/FireBlock igniteOdds Lit/unimi/dsi/fastutil/objects/Object2IntMap; # TODO field net/minecraft/world/level/block/FireBlock f_53421_ -accessible field net/minecraft/world/entity/decoration/HangingEntity pos Lnet/minecraft/core/BlockPos; accessible method net/minecraft/world/entity/decoration/HangingEntity setDirection (Lnet/minecraft/core/Direction;)V accessible field net/minecraft/world/level/Explosion source Lnet/minecraft/world/entity/Entity; accessible field net/minecraft/world/level/block/entity/SculkSensorBlockEntity lastVibrationFrequency I @@ -219,15 +210,10 @@ accessible field net/minecraft/server/level/Ticket key Ljava/lang/Object; accessible method net/minecraft/server/level/Ticket (Lnet/minecraft/server/level/TicketType;ILjava/lang/Object;)V accessible method net/minecraft/server/level/Ticket setCreatedTick (J)V accessible field net/minecraft/world/level/block/entity/BannerBlockEntity baseColor Lnet/minecraft/world/item/DyeColor; -accessible field net/minecraft/world/level/block/entity/BannerBlockEntity itemPatterns Lnet/minecraft/nbt/ListTag; accessible method net/minecraft/world/level/block/Block popExperience (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;I)V -accessible method net/minecraft/world/level/block/ChiseledBookShelfBlock getHitSlot (Lnet/minecraft/world/phys/Vec2;)I accessible field net/minecraft/world/LockCode key Ljava/lang/String; # TODO field net/minecraft/world/level/material/MaterialColor f_76387_ accessible field net/minecraft/world/level/storage/DimensionDataStorage cache Ljava/util/Map; -accessible field net/minecraft/world/level/block/entity/JukeboxBlockEntity isPlaying Z -accessible field net/minecraft/world/level/block/entity/JukeboxBlockEntity tickCount J -accessible field net/minecraft/world/level/block/entity/JukeboxBlockEntity recordStartedTick J accessible field net/minecraft/world/level/chunk/ChunkAccess blockEntities Ljava/util/Map; accessible field net/minecraft/world/level/chunk/ChunkAccess heightmaps Ljava/util/Map; accessible field net/minecraft/world/entity/LightningBolt visualOnly Z @@ -238,7 +224,6 @@ accessible field net/minecraft/world/entity/item/PrimedTnt owner Lnet/minecraft/ # TODO field net/minecraft/network/protocol/game/ServerboundCustomPayloadPacket f_133981_ # TODO field net/minecraft/network/protocol/game/ServerboundCustomPayloadPacket f_133980_ accessible class net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateNameOperation -accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateNameOperation (Lnet/minecraft/network/FriendlyByteBuf;)V accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateNameOperation (Lnet/minecraft/network/chat/Component;)V accessible field net/minecraft/world/entity/ai/attributes/RangedAttribute maxValue D mutable field net/minecraft/world/entity/ai/attributes/RangedAttribute maxValue D @@ -307,14 +292,9 @@ mutable field net/minecraft/server/dedicated/DedicatedServer settings Lnet/minec accessible field net/minecraft/server/dedicated/DedicatedServer rconConsoleSource Lnet/minecraft/server/rcon/RconConsoleSource; accessible field net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket blockState Lnet/minecraft/world/level/block/state/BlockState; accessible field net/minecraft/server/network/ServerCommonPacketListenerImpl connection Lnet/minecraft/network/Connection; -accessible field net/minecraft/world/entity/projectile/Arrow effects Ljava/util/Set; -accessible field net/minecraft/world/entity/projectile/Arrow potion Lnet/minecraft/world/item/alchemy/Potion; -accessible method net/minecraft/world/entity/projectile/Arrow setFixedColor (I)V accessible method net/minecraft/world/entity/projectile/Arrow updateColor ()V accessible method net/minecraft/world/entity/monster/piglin/PiglinAi isLovedItem (Lnet/minecraft/world/item/ItemStack;)Z accessible class net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateStyleOperation -accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateStyleOperation (Lnet/minecraft/network/FriendlyByteBuf;)V -accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateStyleOperation (Lnet/minecraft/world/BossEvent$BossBarColor;Lnet/minecraft/world/BossEvent$BossBarOverlay;)V accessible method net/minecraft/world/entity/npc/Villager increaseMerchantCareer ()V accessible method net/minecraft/world/entity/npc/Villager releaseAllPois ()V accessible method net/minecraft/world/entity/npc/Villager setUnhappy ()V @@ -344,7 +324,6 @@ accessible method net/minecraft/server/level/PlayerRespawnLogic getOverworldResp accessible field net/minecraft/world/level/block/SculkSpreader$ChargeCursor charge I accessible field net/minecraft/world/level/block/SculkSpreader$ChargeCursor pos Lnet/minecraft/core/BlockPos; accessible class net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateProgressOperation -accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateProgressOperation (Lnet/minecraft/network/FriendlyByteBuf;)V accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdateProgressOperation (F)V accessible field net/minecraft/world/level/dimension/end/EndDragonFight portalLocation Lnet/minecraft/core/BlockPos; accessible field net/minecraft/world/level/dimension/end/EndDragonFight dragonUUID Ljava/util/UUID; @@ -385,9 +364,6 @@ mutable field net/minecraft/server/level/TicketType timeout J accessible method net/minecraft/world/entity/projectile/ThrownPotion isLingering ()Z accessible class net/minecraft/world/entity/projectile/FishingHook$FishHookState # TODO accessible method net/minecraft/world/entity/animal/MushroomCow m_28928_ (Lnet/minecraft/world/entity/animal/MushroomCow$MushroomType;)V -accessible field net/minecraft/world/entity/AreaEffectCloud effects Ljava/util/List; -mutable field net/minecraft/world/entity/AreaEffectCloud effects Ljava/util/List; -accessible field net/minecraft/world/entity/AreaEffectCloud potion Lnet/minecraft/world/item/alchemy/Potion; accessible field net/minecraft/world/entity/AreaEffectCloud radiusOnUse F accessible field net/minecraft/world/entity/AreaEffectCloud reapplicationDelay I accessible field net/minecraft/world/entity/AreaEffectCloud durationOnUse I @@ -408,7 +384,6 @@ accessible field net/minecraft/world/level/block/entity/ChiseledBookShelfBlockEn accessible field net/minecraft/world/entity/projectile/EvokerFangs warmupDelayTicks I # TODO accessible method net/minecraft/server/Main m_129674_ (Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lcom/google/common/collect/ImmutableSet;)V # TODO accessible method net/minecraft/server/Main m_195488_ (Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lnet/minecraft/world/level/levelgen/WorldGenSettings;)V -accessible method net/minecraft/server/Main forceUpgrade (Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lnet/minecraft/core/Registry;)V accessible field net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity recipesUsed Lit/unimi/dsi/fastutil/objects/Object2IntOpenHashMap; accessible field net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity cookingTotalTime I accessible field net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity litTime I @@ -431,14 +406,12 @@ accessible method net/minecraft/server/players/StoredUserEntry getUser ()Ljava/l # TODO field net/minecraft/world/entity/projectile/ThrownTrident f_37555_ accessible field net/minecraft/world/entity/Mob targetSelector Lnet/minecraft/world/entity/ai/goal/GoalSelector; mutable field net/minecraft/world/entity/Mob targetSelector Lnet/minecraft/world/entity/ai/goal/GoalSelector; -accessible field net/minecraft/world/entity/Mob lootTable Lnet/minecraft/resources/ResourceLocation; accessible field net/minecraft/world/entity/Mob goalSelector Lnet/minecraft/world/entity/ai/goal/GoalSelector; mutable field net/minecraft/world/entity/Mob goalSelector Lnet/minecraft/world/entity/ai/goal/GoalSelector; accessible field net/minecraft/world/entity/Mob handDropChances [F accessible field net/minecraft/world/entity/Mob armorDropChances [F accessible field net/minecraft/world/entity/Mob lootTableSeed J accessible field net/minecraft/world/entity/Mob persistenceRequired Z -accessible method net/minecraft/world/entity/Mob getDefaultLootTable ()Lnet/minecraft/resources/ResourceLocation; accessible field net/minecraft/world/level/block/entity/ChestBlockEntity openersCounter Lnet/minecraft/world/level/block/entity/ContainerOpenersCounter; accessible method net/minecraft/world/level/block/entity/ChestBlockEntity playSound (Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/sounds/SoundEvent;)V accessible field net/minecraft/world/entity/monster/Guardian randomStrollGoal Lnet/minecraft/world/entity/ai/goal/RandomStrollGoal; @@ -447,7 +420,6 @@ accessible field net/minecraft/world/entity/monster/Zombie DATA_DROWNED_CONVERSI accessible field net/minecraft/world/entity/monster/Zombie conversionTime I accessible method net/minecraft/world/entity/monster/Zombie startUnderWaterConversion (I)V accessible class net/minecraft/world/item/crafting/Ingredient$Value -accessible field net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity lootTable Lnet/minecraft/resources/ResourceLocation; accessible field net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity lootTableSeed J accessible field net/minecraft/world/inventory/MerchantContainer selectionHint I accessible method net/minecraft/world/level/chunk/DataLayer set (II)V @@ -462,8 +434,6 @@ accessible field net/minecraft/server/ServerAdvancementManager GSON Lcom/google/ accessible field net/minecraft/world/CompoundContainer container1 Lnet/minecraft/world/Container; accessible field net/minecraft/world/CompoundContainer container2 Lnet/minecraft/world/Container; accessible class net/minecraft/world/level/block/ComposterBlock$OutputContainer -accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity primaryPower Lnet/minecraft/world/effect/MobEffect; -accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity secondaryPower Lnet/minecraft/world/effect/MobEffect; accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity name Lnet/minecraft/network/chat/Component; accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity lockKey Lnet/minecraft/world/LockCode; accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity levels I @@ -477,7 +447,6 @@ accessible method net/minecraft/server/level/ServerPlayer nextContainerCounter ( # TODO accessible method net/minecraft/world/entity/animal/axolotl/Axolotl m_149117_ (Lnet/minecraft/world/entity/animal/axolotl/Axolotl$Variant;)V accessible class net/minecraft/server/MinecraftServer$TimeProfiler accessible method net/minecraft/server/MinecraftServer$TimeProfiler (JI)V -accessible method net/minecraft/world/entity/projectile/ThrowableItemProjectile getItemRaw ()Lnet/minecraft/world/item/ItemStack; accessible method net/minecraft/world/phys/shapes/IndirectMerger (Lit/unimi/dsi/fastutil/doubles/DoubleList;Lit/unimi/dsi/fastutil/doubles/DoubleList;ZZ)V accessible field net/minecraft/world/entity/animal/Bee stayOutOfHiveCountdown I accessible field net/minecraft/world/entity/animal/Bee hivePos Lnet/minecraft/core/BlockPos; @@ -486,7 +455,6 @@ accessible method net/minecraft/world/entity/animal/Bee setHasStung (Z)V # TODO field net/minecraft/server/level/ServerChunkCache f_8328_ accessible field net/minecraft/server/level/ServerChunkCache spawnFriendlies Z accessible field net/minecraft/server/level/ServerChunkCache spawnEnemies Z -accessible field net/minecraft/world/entity/ai/attributes/AttributeModifier name Ljava/lang/String; # TODO field net/minecraft/network/protocol/game/ServerboundResourcePackPacket f_134406_ accessible field net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity exactTeleport Z accessible field net/minecraft/world/level/block/entity/TheEndGatewayBlockEntity exitPortal Lnet/minecraft/core/BlockPos; @@ -496,12 +464,10 @@ accessible field net/minecraft/world/level/block/ShulkerBoxBlock color Lnet/mine accessible field net/minecraft/world/entity/monster/Pillager inventory Lnet/minecraft/world/SimpleContainer; # TODO accessible method net/minecraft/world/level/block/DropperBlock m_5824_ (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;)V # TODO accessible method net/minecraft/world/level/block/DropperBlock m_5824_ (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;)V -accessible method net/minecraft/world/item/MapItem createNewSavedData (Lnet/minecraft/world/level/Level;IIIZZLnet/minecraft/resources/ResourceKey;)I accessible method net/minecraft/world/entity/monster/SpellcasterIllager getCurrentSpell ()Lnet/minecraft/world/entity/monster/SpellcasterIllager$IllagerSpell; # TODO mutable field net/minecraft/world/item/ItemStack item Lnet/minecraft/world/item/Item; accessible class net/minecraft/server/level/ChunkMap$TrackedEntity accessible field net/minecraft/server/level/ChunkMap$TrackedEntity seenBy Ljava/util/Set; -accessible method net/minecraft/util/datafix/fixes/BlockStateData register (ILjava/lang/String;[Ljava/lang/String;)V accessible field net/minecraft/world/entity/monster/Vindicator isJohnny Z accessible field net/minecraft/world/entity/projectile/FireworkRocketEntity DATA_SHOT_AT_ANGLE Lnet/minecraft/network/syncher/EntityDataAccessor; accessible field net/minecraft/world/entity/projectile/FireworkRocketEntity lifetime I @@ -518,7 +484,6 @@ accessible method net/minecraft/server/level/ServerLevel getEntities (Lnet/minec # TODO accessible method net/minecraft/server/level/ServerLevel m_142646_ ()Lnet/minecraft/world/level/entity/LevelEntityGetter; accessible field net/minecraft/world/entity/vehicle/MinecartTNT fuse I accessible method net/minecraft/world/entity/vehicle/MinecartTNT explode (D)V -accessible field net/minecraft/world/level/block/entity/SkullBlockEntity owner Lcom/mojang/authlib/GameProfile; # TODO field net/minecraft/world/level/block/entity/SkullBlockEntity f_59756_ accessible field net/minecraft/world/level/block/entity/SkullBlockEntity noteBlockSound Lnet/minecraft/resources/ResourceLocation; # TODO accessible method net/minecraft/world/level/block/entity/SkullBlockEntity m_292605_ (Lcom/mojang/authlib/GameProfile;)Ljava/util/concurrent/CompletableFuture; @@ -527,7 +492,6 @@ accessible field net/minecraft/util/datafix/fixes/ItemSpawnEggFix ID_TO_ENTITY [ accessible field net/minecraft/world/level/StructureManager level Lnet/minecraft/world/level/LevelAccessor; accessible method net/minecraft/world/item/crafting/SmithingTrimRecipe (Lnet/minecraft/world/item/crafting/Ingredient;Lnet/minecraft/world/item/crafting/Ingredient;Lnet/minecraft/world/item/crafting/Ingredient;)V accessible field net/minecraft/world/entity/raid/Raid numGroups I -accessible field net/minecraft/world/entity/raid/Raid badOmenLevel I accessible field net/minecraft/world/entity/raid/Raid totalHealth F accessible field net/minecraft/world/entity/raid/Raid ticksActive J accessible field net/minecraft/world/entity/raid/Raid heroesOfTheVillage Ljava/util/Set; @@ -565,7 +529,6 @@ accessible field net/minecraft/world/level/chunk/storage/EntityStorage entityDes accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder; # TODO field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator f_188604_ accessible class net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdatePropertiesOperation -accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdatePropertiesOperation (Lnet/minecraft/network/FriendlyByteBuf;)V accessible method net/minecraft/network/protocol/game/ClientboundBossEventPacket$UpdatePropertiesOperation (ZZZ)V accessible class net/minecraft/world/entity/animal/Bee$BeePollinateGoal accessible method net/minecraft/world/entity/animal/Bee$BeePollinateGoal stopPollinating ()V @@ -651,7 +614,6 @@ accessible field net/minecraft/server/level/ChunkMap level Lnet/minecraft/server accessible field net/minecraft/server/level/ChunkMap distanceManager Lnet/minecraft/server/level/ChunkMap$DistanceManager; accessible field net/minecraft/server/level/ChunkMap updatingChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; accessible field net/minecraft/server/level/ChunkMap visibleChunkMap Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap; -accessible field net/minecraft/server/level/ChunkMap generator Lnet/minecraft/world/level/chunk/ChunkGenerator; accessible method net/minecraft/server/level/ChunkMap save (Lnet/minecraft/world/level/chunk/ChunkAccess;)Z accessible field net/minecraft/world/level/block/entity/StructureBlockEntity mode Lnet/minecraft/world/level/block/state/properties/StructureMode; accessible field net/minecraft/world/level/block/entity/StructureBlockEntity metaData Ljava/lang/String; @@ -694,7 +656,6 @@ accessible method net/minecraft/world/entity/monster/Slime setSize (IZ)V accessible class net/minecraft/world/level/block/ComposterBlock$EmptyContainer accessible field net/minecraft/world/entity/monster/piglin/Piglin cannotHunt Z accessible field net/minecraft/world/entity/monster/piglin/Piglin inventory Lnet/minecraft/world/SimpleContainer; -accessible field net/minecraft/world/level/block/entity/DecoratedPotBlockEntity decorations Lnet/minecraft/world/level/block/entity/DecoratedPotBlockEntity$Decorations; # TODO accessible method net/minecraft/server/players/BanListEntry m_7524_ ()Z accessible field net/minecraft/world/BossEvent color Lnet/minecraft/world/BossEvent$BossBarColor; accessible field net/minecraft/world/BossEvent overlay Lnet/minecraft/world/BossEvent$BossBarOverlay; @@ -703,7 +664,6 @@ accessible field net/minecraft/world/level/entity/PersistentEntitySectionManager accessible method net/minecraft/world/level/entity/PersistentEntitySectionManager ensureChunkQueuedForLoad (J)V accessible class net/minecraft/world/entity/monster/SpellcasterIllager$IllagerSpell accessible field net/minecraft/network/protocol/game/ClientboundSetDefaultSpawnPositionPacket pos Lnet/minecraft/core/BlockPos; -accessible field net/minecraft/world/entity/vehicle/AbstractMinecartContainer lootTable Lnet/minecraft/resources/ResourceLocation; accessible field net/minecraft/world/entity/vehicle/AbstractMinecartContainer lootTableSeed J accessible field net/minecraft/world/level/block/entity/BeehiveBlockEntity savedFlowerPos Lnet/minecraft/core/BlockPos; accessible field net/minecraft/world/level/chunk/PalettedContainer registry Lnet/minecraft/core/IdMap; @@ -714,3 +674,62 @@ accessible class net/minecraft/server/dedicated/DedicatedServerProperties$WorldD accessible method net/minecraft/server/dedicated/DedicatedServerProperties$WorldDimensionData (Lcom/google/gson/JsonObject;Ljava/lang/String;)V #accessible class net/minecraftforge/registries/NamespacedWrapper accessible field net/minecraft/world/level/block/state/StateHolder PROPERTY_ENTRY_TO_STRING_FUNCTION Ljava/util/function/Function; +# Bukkit 1.21 +accessible field net/minecraft/world/level/block/entity/trialspawner/TrialSpawner stateAccessor Lnet/minecraft/world/level/block/entity/trialspawner/TrialSpawner$StateAccessor; +accessible field net/minecraft/world/level/block/entity/trialspawner/TrialSpawnerData detectedPlayers Ljava/util/Set; +accessible field net/minecraft/world/level/block/entity/trialspawner/TrialSpawnerData currentMobs Ljava/util/Set; +accessible field net/minecraft/world/level/block/entity/trialspawner/TrialSpawnerData nextSpawnData Ljava/util/Optional; +accessible field net/minecraft/world/item/trading/MerchantOffer costB Ljava/util/Optional; +mutable field net/minecraft/world/item/trading/MerchantOffer costB Ljava/util/Optional; +mutable field net/minecraft/world/item/trading/MerchantOffer xp I +mutable field net/minecraft/world/item/trading/MerchantOffer priceMultiplier F +accessible field net/minecraft/world/item/trading/MerchantOffer baseCostA Lnet/minecraft/world/item/trading/ItemCost; +mutable field net/minecraft/world/item/trading/MerchantOffer baseCostA Lnet/minecraft/world/item/trading/ItemCost; +mutable field net/minecraft/world/item/trading/MerchantOffer rewardExp Z +accessible field net/minecraft/world/item/crafting/RecipeManager byType Lcom/google/common/collect/Multimap; +mutable field net/minecraft/world/item/crafting/RecipeManager byType Lcom/google/common/collect/Multimap; +accessible method net/minecraft/world/entity/animal/Wolf setCollarColor (Lnet/minecraft/world/item/DyeColor;)V +accessible field net/minecraft/world/level/block/entity/BrushableBlockEntity lootTable Lnet/minecraft/resources/ResourceKey; +accessible field net/minecraft/world/item/armortrim/ArmorTrim showInTooltip Z +accessible field net/minecraft/world/entity/projectile/AbstractArrow firedFromWeapon Lnet/minecraft/world/item/ItemStack; +accessible method net/minecraft/world/entity/projectile/AbstractArrow setPierceLevel (B)V +accessible method net/minecraft/world/level/Level getEntities (Lnet/minecraft/world/level/entity/EntityTypeTest;Lnet/minecraft/world/phys/AABB;Ljava/util/function/Predicate;Ljava/util/List;I)V +accessible method net/minecraft/world/level/block/ChiseledBookShelfBlock getHitSlot (Lnet/minecraft/world/phys/BlockHitResult;Lnet/minecraft/world/level/block/state/BlockState;)Ljava/util/OptionalInt; +accessible method net/minecraft/world/level/block/ChiseledBookShelfBlock getSection (F)I +accessible field net/minecraft/world/entity/OminousItemSpawner spawnItemAfterTicks J +accessible method net/minecraft/world/entity/OminousItemSpawner setItem (Lnet/minecraft/world/item/ItemStack;)V +accessible field net/minecraft/world/entity/projectile/FishingHook timeUntilLured I +accessible field net/minecraft/world/entity/projectile/FishingHook timeUntilHooked I +accessible field net/minecraft/server/dedicated/DedicatedServer serverLinks Lnet/minecraft/server/ServerLinks; +mutable field net/minecraft/server/dedicated/DedicatedServer serverLinks Lnet/minecraft/server/ServerLinks; +accessible method net/minecraft/world/entity/projectile/Arrow getPotionContents ()Lnet/minecraft/world/item/alchemy/PotionContents; +accessible method net/minecraft/world/entity/projectile/Arrow setPotionContents (Lnet/minecraft/world/item/alchemy/PotionContents;)V +accessible field net/minecraft/world/item/BucketItem content Lnet/minecraft/world/level/material/Fluid; +accessible class net/minecraft/server/level/ServerPlayer$RespawnPosAngle +accessible method net/minecraft/world/entity/projectile/windcharge/AbstractWindCharge explode (Lnet/minecraft/world/phys/Vec3;)V +accessible field net/minecraft/world/entity/animal/MushroomCow stewEffects Lnet/minecraft/world/item/component/SuspiciousStewEffects; +accessible field net/minecraft/world/entity/AreaEffectCloud potionContents Lnet/minecraft/world/item/alchemy/PotionContents; +accessible method net/minecraft/server/Main forceUpgrade (Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;Lcom/mojang/datafixers/DataFixer;ZLjava/util/function/BooleanSupplier;Lnet/minecraft/core/RegistryAccess;Z)V +accessible method net/minecraft/world/entity/animal/sniffer/Sniffer canDig (Lnet/minecraft/core/BlockPos;)Z +accessible field net/minecraft/world/entity/Mob lootTable Lnet/minecraft/resources/ResourceKey; +accessible field net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity lootTable Lnet/minecraft/resources/ResourceKey; +accessible method net/minecraft/network/protocol/game/ClientboundBlockEntityDataPacket (Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/entity/BlockEntityType;Lnet/minecraft/nbt/CompoundTag;)V +accessible field net/minecraft/world/level/block/entity/TrialSpawnerBlockEntity trialSpawner Lnet/minecraft/world/level/block/entity/trialspawner/TrialSpawner; +accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity primaryPower Lnet/minecraft/core/Holder; +accessible field net/minecraft/world/level/block/entity/BeaconBlockEntity secondaryPower Lnet/minecraft/core/Holder; +accessible method net/minecraft/server/level/ServerPlayer findRespawnAndUseSpawnBlock (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;FZZ)Ljava/util/Optional; +accessible field net/minecraft/world/item/JukeboxSongPlayer song Lnet/minecraft/core/Holder; +accessible method net/minecraft/world/item/MapItem createNewSavedData (Lnet/minecraft/world/level/Level;IIIZZLnet/minecraft/resources/ResourceKey;)Lnet/minecraft/world/level/saveddata/maps/MapId; +mutable field net/minecraft/world/item/ItemStack item Lnet/minecraft/world/item/Item; +accessible field net/minecraft/server/level/ChunkMap$TrackedEntity serverEntity Lnet/minecraft/server/level/ServerEntity; +accessible method net/minecraft/util/datafix/fixes/BlockStateData register (ILjava/lang/String;[Ljava/lang/String;)V +accessible method net/minecraft/world/entity/vehicle/MinecartTNT explode (Lnet/minecraft/world/damagesource/DamageSource;D)V +accessible field net/minecraft/world/level/block/entity/SkullBlockEntity owner Lnet/minecraft/world/item/component/ResolvableProfile; +accessible method net/minecraft/world/entity/animal/Cat setCollarColor (Lnet/minecraft/world/item/DyeColor;)V +accessible field net/minecraft/world/entity/raid/Raid raidOmenLevel I +accessible field net/minecraft/world/item/enchantment/ItemEnchantments$Mutable showInTooltip Z +mutable field net/minecraft/world/item/enchantment/ItemEnchantments$Mutable showInTooltip Z +accessible field net/minecraft/world/item/enchantment/ItemEnchantments showInTooltip Z +accessible method net/minecraft/world/entity/projectile/AbstractHurtingProjectile assignDirectionalMovement (Lnet/minecraft/world/phys/Vec3;D)V +accessible field net/minecraft/world/level/block/entity/DecoratedPotBlockEntity decorations Lnet/minecraft/world/level/block/entity/PotDecorations; +accessible field net/minecraft/world/entity/vehicle/AbstractMinecartContainer lootTable Lnet/minecraft/resources/ResourceKey; diff --git a/arclight-common/src/main/resources/mixins.arclight.bukkit.json b/arclight-common/src/main/resources/mixins.arclight.bukkit.json index 2b40a2c46..de14e80a7 100644 --- a/arclight-common/src/main/resources/mixins.arclight.bukkit.json +++ b/arclight-common/src/main/resources/mixins.arclight.bukkit.json @@ -41,7 +41,6 @@ "MaterialMixin", "PluginClassLoaderMixin", "PotionTypeMixin", - "RecipeIteratorMixin", "Registry_SimpleRegistryMixin", "StandardMessengerMixin", "WatchdogThreadMixin" diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index d2f105d46..8617e2934 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -25,12 +25,14 @@ "commands.arguments.EntityArgumentMixin", "commands.arguments.blocks.BlockStateParserMixin", "commands.arguments.selector.EntitySelectorParserMixin", + "core.component.DataComponentPatch_BuilderMixin", "fluid.FlowingFluidMixin", "fluid.LavaFluidMixin", "nbt.CompoundTagMixin", "network.ConnectionMixin", "network.ServerCommonPacketListenerImplMixin", "network.ServerConfigurationPacketListenerImplMixin", + "network.ServerGamePacketListenerImpl_HandlerMixin", "network.ServerHandshakeNetHandlerMixin", "network.ServerLoginNetHandlerMixin", "network.ServerPlayNetHandlerMixin", @@ -40,6 +42,8 @@ "network.chat.StyleMixin", "network.chat.TextColorMixin", "network.protocol.PacketThreadUtilMixin", + "network.protocol.common.CustomPayloadPacketMixin", + "network.protocol.common.custom.DiscardedPayloadMixin", "network.protocol.game.ClientboundCommandsPacket_ArgumentNodeStubMixin", "network.protocol.game.ClientboundSectionBlocksUpdatePacketMixin", "network.protocol.game.ClientboundSystemChatPacketMixin", @@ -53,6 +57,7 @@ "server.Main_ServerShutdownThreadMixin", "server.MinecraftServerMixin", "server.PlayerAdvancementsMixin", + "server.ServerAdvancementManagerMixin", "server.ServerFunctionManagerMixin", "server.ServerScoreboardMixin", "server.ServerTickRateManagerMixin", @@ -75,12 +80,16 @@ "server.level.ServerEntityMixin", "server.level.ServerLevel_EntityCallbacksMixin", "server.level.ServerLevelMixin", + "server.level.ServerPlayer_RespawnPosAngleMixin", + "server.level.ServerPlayerMixin", "server.level.TicketTypeMixin", "server.management.BanEntryMixin", "server.management.PlayerListMixin", "server.management.ServerPlayerGameModeMixin", "server.management.UserListMixin", "stats.StatisticsCounterMixin", + "util.StringUtilMixin", + "util.thread.BlockableEventLoopMixin", "world.BlockGetterMixin", "world.CompoundContainerMixin", "world.ContainerMixin", @@ -88,6 +97,8 @@ "world.IWorldMixin", "world.IWorldWriterMixin", "world.SimpleContainerMixin", + "world.damagesource.CombatEntryMixin", + "world.damagesource.CombatTrackerMixin", "world.damagesource.DamageSourceMixin", "world.damagesource.DamageSourcesMixin", "world.effect.HealOrHarmMobEffectMixin", @@ -104,11 +115,11 @@ "world.entity.IAngerableMixin", "world.entity.InteractionMixin", "world.entity.ItemBaseSteeringMixin", + "world.entity.LeashableMixin", "world.entity.LightningBoltMixin", "world.entity.LivingEntityMixin", - "world.entity.LivingEntityMixin$ApotheosisCompatMixin", - "world.entity.LivingEntityMixin$ObscureApiCompat", "world.entity.MobMixin", + "world.entity.NeutralMobMixin", "world.entity.PathfinderMobMixin", "world.entity.ai.behavior.AssignProfessionFromJobSiteMixin", "world.entity.ai.behavior.BabyFollowAdultMixin", @@ -126,7 +137,6 @@ "world.entity.ai.goal.BreakDoorGoalMixin", "world.entity.ai.goal.DefendVillageTargetGoalMixin", "world.entity.ai.goal.EatBlockGoalMixin", - "world.entity.ai.goal.FollowOwnerGoalMixin", "world.entity.ai.goal.HurtByTargetGoalMixin", "world.entity.ai.goal.NearestAttackableTargetGoalMixin", "world.entity.ai.goal.OwnerHurtByTargetGoalMixin", @@ -173,12 +183,14 @@ "world.entity.animal.Turtle_LayEggGoalMixin", "world.entity.animal.TurtleMixin", "world.entity.animal.WolfMixin", + "world.entity.animal.armadillo.ArmadilloMixin", "world.entity.animal.axolotl.AxolotlMixin", "world.entity.animal.camel.CamelMixin", "world.entity.animal.frog.ShootTongueMixin", "world.entity.animal.frog.TadpoleMixin", "world.entity.animal.goat.GoatMixin", "world.entity.animal.horse.AbstractHorseMixin", + "world.entity.animal.horse.AbstractHorseMixin$ContainerMixin", "world.entity.animal.horse.LlamaMixin", "world.entity.animal.horse.SkeletonHorseMixin", "world.entity.animal.horse.TraderLlamaEntity_FollowTraderGoalMixin", @@ -191,8 +203,9 @@ "world.entity.decoration.ArmorStandMixin", "world.entity.decoration.ItemFrameMixin", "world.entity.decoration.LeashFenceKnotEntityMixin", + "world.entity.decoration.PaintingMixin", + "world.entity.item.BlockAttachedEntityMixin", "world.entity.item.FallingBlockEntityMixin", - "world.entity.item.HangingEntityMixin", "world.entity.item.ItemEntityMixin", "world.entity.item.PrimedTntMixin", "world.entity.monster.AbstractSkeletonMixin", @@ -234,7 +247,6 @@ "world.entity.npc.WanderingTraderMixin", "world.entity.player.InventoryMixin", "world.entity.player.PlayerMixin", - "world.entity.player.ServerPlayerMixin", "world.entity.projectile.AbstractArrowMixin", "world.entity.projectile.AbstractHurtingProjectileMixin", "world.entity.projectile.ArrowEntityMixin", @@ -258,8 +270,8 @@ "world.entity.projectile.ThrownExperienceBottleMixin", "world.entity.projectile.ThrownPotionMixin", "world.entity.projectile.ThrownTridentMixin", - "world.entity.projectile.WindChargeMixin", "world.entity.projectile.WitherSkullMixin", + "world.entity.projectile.windcharge.AbstractWindChargeMixin", "world.entity.raid.RaidManagerMixin", "world.entity.raid.RaidMixin", "world.entity.raider.Raider_HoldGroundAttackGoalMixin", @@ -286,6 +298,7 @@ "world.inventory.ContainerLevelAccessMixin", "world.inventory.ContainerTypeMixin", "world.inventory.CrafterMenuMixin", + "world.inventory.CraftingContainerMixin", "world.inventory.CraftingMenuMixin", "world.inventory.CraftResultInventoryMixin", "world.inventory.DispenserContainerMixin", @@ -311,14 +324,13 @@ "world.inventory.StonecutterContainer1Mixin", "world.inventory.StonecutterContainerMixin", "world.inventory.TransientCraftingContainerMixin", + "world.item.ArmorItemMixin", "world.item.ArmorStandItemMixin", "world.item.BlockItemMixin", "world.item.BoatItemMixin", "world.item.BoneMealItemMixin", - "world.item.BowItemMixin", "world.item.BucketItemMixin", "world.item.ChorusFruitItemMixin", - "world.item.CrossbowItemMixin", "world.item.DyeItemMixin", "world.item.EggItemMixin", "world.item.EnderCrystalItemMixin", @@ -331,12 +343,12 @@ "world.item.ItemMixin", "world.item.ItemStackMixin", "world.item.LeadItemMixin", - "world.item.MapItemMixin", "world.item.MerchantMixin", "world.item.MerchantOfferMixin", "world.item.MilkBucketItemMixin", "world.item.MinecartItemMixin", "world.item.PotionItemMixin", + "world.item.ProjectileWeaponItemMixin", "world.item.SnowballItemMixin", "world.item.SpawnEggItemMixin", "world.item.StandingAndWallBlockItemMixin", @@ -356,8 +368,10 @@ "world.item.crafting.SmithingTrimRecipeMixin", "world.item.crafting.SmokingRecipeMixin", "world.item.crafting.StonecuttingRecipeMixin", - "world.item.enchantment.DamageEnchantmentMixin", - "world.item.enchantment.FrostWalkerEnchantmentMixin", + "world.item.enchantment.effects.ApplyMobEffectMixin", + "world.item.enchantment.effects.IgniteMixin", + "world.item.enchantment.effects.ReplaceBlockMixin", + "world.item.enchantment.effects.ReplaceDiskMixin", "world.level.ExplosionMixin", "world.level.GameRules_ValueMixin", "world.level.Level_ExplosionInteractionMixin", @@ -402,11 +416,12 @@ "world.level.block.DetectorRailBlockMixin", "world.level.block.DiodeBlockMixin", "world.level.block.DirtPathBlockMixin", - "world.level.block.DispenserBlockMixin_Accessor", + "world.level.block.DispenserBlockMixin", "world.level.block.DoorBlockMixin", "world.level.block.DoublePlantBlockMixin", "world.level.block.DragonEggBlockMixin", "world.level.block.DropperBlockMixin", + "world.level.block.EndGatewayBlockMixin", "world.level.block.EndPortalBlockMixin", "world.level.block.FallingBlockMixin", "world.level.block.FarmBlockMixin", @@ -435,7 +450,6 @@ "world.level.block.ObserverBlockMixin", "world.level.block.PistonBaseBlockMixin", "world.level.block.PointedDripstoneBlockMixin", - "world.level.block.PortalInfoMixin", "world.level.block.PortalShapeMixin", "world.level.block.PowderSnowBlockMixin", "world.level.block.PoweredRailBlockMixin", @@ -470,8 +484,6 @@ "world.level.block.WeightedPressurePlateBlockMixin", "world.level.block.WitherRoseBlockMixin", "world.level.block.WitherSkullBlockMixin", - "world.level.block.WitherSkullBlockMixin$ForgeLike", - "world.level.block.WitherSkullBlockMixin$VanillaLike", "world.level.block.entity.AbstractFurnaceBlockEntityMixin", "world.level.block.entity.BarrelBlockEntityMixin", "world.level.block.entity.BeaconTileEntityMixin", @@ -491,8 +503,6 @@ "world.level.block.entity.DecoratedPotBlockEntityMixin", "world.level.block.entity.DispenserBlockEntityMixin", "world.level.block.entity.EndGatewayBlockEntityMixin", - "world.level.block.entity.EndGatewayBlockEntityMixin$ForgeLike", - "world.level.block.entity.EndGatewayBlockEntityMixin$VanillaLike", "world.level.block.entity.HopperBlockEntityMixin", "world.level.block.entity.JukeboxBlockEntityMixin", "world.level.block.entity.LecternBlockEntityMixin", @@ -502,6 +512,7 @@ "world.level.block.entity.SculkCatalystBlockEntityMixin", "world.level.block.entity.ShulkerBoxBlockEntityMixin", "world.level.block.entity.SignBlockEntityMixin", + "world.level.block.entity.trailspawner.TrialSpawnerMixin", "world.level.block.state.BlockBehaviour_BlockStateBaseMixin", "world.level.block.state.BlockBehaviourMixin", "world.level.border.WorldBorderMixin", @@ -513,25 +524,25 @@ "world.level.chunk.storage.ChunkLoaderMixin", "world.level.chunk.storage.ChunkSerializerMixin", "world.level.chunk.storage.RegionFileCacheMixin", + "world.level.chunk.storage.RegionFileMixin", "world.level.dimension.end.DragonRespawnAnimation_4_Mixin", "world.level.entity.EntityAccessMixin", "world.level.entity.PersistentEntitySectionManagerMixin", "world.level.gameevent.GameEventDispatcherMixin", "world.level.gameevent.vibrations.VibrationListenerMixin", + "world.level.levelgen.feature.EndPlatformFeatureMixin", "world.level.levelgen.structure.StructurePieceMixin", "world.level.levelgen.structure.StructureStartMixin", "world.level.levelgen.structure.templatesystem.StructurePlaceSettingsMixin", "world.level.levelgen.structure.templatesystem.StructureTemplateMixin", + "world.level.portal.DimensionTransitionMixin", "world.level.portal.PortalForcerMixin", "world.level.redstone.NeighborUpdaterMixin", "world.level.saveddata.maps.MapDataMixin", "world.level.saveddata.maps.MapItemSavedData_HoldingPlayerMixin", "world.level.storage.loot.LootContextMixin", - "world.level.storage.loot.LootDataManagerMixin", + "world.level.storage.loot.LootDataTypeMixin", "world.level.storage.loot.LootTableMixin", - "world.level.storage.loot.functions.LootingEnchantBonusMixin", - "world.level.storage.loot.parameters.LootParametersMixin", - "world.level.storage.loot.predicates.RandomChanceWithLootingMixin", "world.level.storage.loot.predicates.SurvivesExplosionMixin", "world.spawner.BaseSpawnerMixin", "world.spawner.NaturalSpawnerMixin", diff --git a/arclight-common/src/main/resources/mixins.arclight.impl.optimization.json b/arclight-common/src/main/resources/mixins.arclight.impl.optimization.json index e22060215..2879fc00c 100644 --- a/arclight-common/src/main/resources/mixins.arclight.impl.optimization.json +++ b/arclight-common/src/main/resources/mixins.arclight.impl.optimization.json @@ -7,7 +7,6 @@ "compatibilityLevel": "JAVA_17", "mixins": [ "ClassInheritanceMultiMapMixin", - "EntityDataManagerMixin_Optimize", "EntityMixin_Optimize", "GoalMixin", "MobMixin_Optimization", diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerCommonPacketListenerImplMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerCommonPacketListenerImplMixin_Fabric.java index d529d2d4a..d7e12b34c 100644 --- a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerCommonPacketListenerImplMixin_Fabric.java +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerCommonPacketListenerImplMixin_Fabric.java @@ -1,8 +1,6 @@ package io.izzel.arclight.fabric.mixin.core.network; import io.izzel.arclight.common.bridge.core.network.common.ServerCommonPacketListenerBridge; -import net.fabricmc.fabric.impl.networking.payload.RetainedPayload; -import net.fabricmc.fabric.impl.networking.payload.UntypedPayload; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.server.network.ServerCommonPacketListenerImpl; @@ -13,11 +11,12 @@ public abstract class ServerCommonPacketListenerImplMixin_Fabric implements Serv @Override public FriendlyByteBuf bridge$getDiscardedData(ServerboundCustomPayloadPacket packet) { - if (packet.payload() instanceof RetainedPayload r) { - return r.buf(); - } else if (packet.payload() instanceof UntypedPayload r) { - return r.buffer(); - } + //TODO + //if (packet.payload() instanceof RetainedPayload r) { + // return r.buf(); + //} else if (packet.payload() instanceof UntypedPayload r) { + // return r.buffer(); + //} return null; } } diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerConfigurationPacketListenerImplMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerConfigurationPacketListenerImplMixin_Fabric.java new file mode 100644 index 000000000..3b9517525 --- /dev/null +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/network/ServerConfigurationPacketListenerImplMixin_Fabric.java @@ -0,0 +1,25 @@ +package io.izzel.arclight.fabric.mixin.core.network; + +import io.izzel.arclight.common.mod.server.ArclightServer; +import net.minecraft.server.network.ServerConfigurationPacketListenerImpl; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ServerConfigurationPacketListenerImpl.class) +public abstract class ServerConfigurationPacketListenerImplMixin_Fabric { + + // @formatter:off + @Shadow public abstract void startConfiguration(); + // @formatter:on + + @Inject(method = "startConfiguration", cancellable = true, at = @At("HEAD")) + private void arclight$runOnMainThread(CallbackInfo ci) { + if (!ArclightServer.isPrimaryThread()) { + ArclightServer.executeOnMainThread(this::startConfiguration); + ci.cancel(); + } + } +} diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/EntityMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/EntityMixin_Fabric.java index 659098496..048dfeb01 100644 --- a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/EntityMixin_Fabric.java +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/EntityMixin_Fabric.java @@ -1,11 +1,9 @@ package io.izzel.arclight.fabric.mixin.core.world.entity; import io.izzel.arclight.common.bridge.core.entity.EntityBridge; -import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.Level; -import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -16,7 +14,6 @@ public abstract class EntityMixin_Fabric implements EntityBridge { // @formatter:off @Shadow public abstract Level level(); @Shadow public abstract boolean isRemoved(); - @Shadow @org.jetbrains.annotations.Nullable protected abstract PortalInfo findDimensionEntryPoint(ServerLevel serverLevel); @Shadow private float yRot; @Shadow private float xRot; @Shadow public abstract float getXRot(); diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/player/ServerPlayerMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/player/ServerPlayerMixin_Fabric.java index 0827ae700..b40b0ac11 100644 --- a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/player/ServerPlayerMixin_Fabric.java +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/entity/player/ServerPlayerMixin_Fabric.java @@ -1,7 +1,6 @@ package io.izzel.arclight.fabric.mixin.core.world.entity.player; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -27,7 +26,6 @@ public abstract class ServerPlayerMixin_Fabric extends PlayerMixin_Fabric implem @Shadow public abstract CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel arg); @Shadow @Final public MinecraftServer server; @Shadow @Nullable private Vec3 enteredNetherPosition; - @Shadow protected abstract void createEndPlatform(ServerLevel arg, BlockPos arg2); @Shadow public abstract void setServerLevel(ServerLevel arg); @Shadow public abstract void triggerDimensionChangeTriggers(ServerLevel arg); @Shadow @Final public ServerPlayerGameMode gameMode; diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/FireBlockMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/FireBlockMixin_Fabric.java index fa3ec00ca..4bdb908b4 100644 --- a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/FireBlockMixin_Fabric.java +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/FireBlockMixin_Fabric.java @@ -6,18 +6,18 @@ @Mixin(FireBlock.class) public abstract class FireBlockMixin_Fabric { - // @Inject(method = "checkBurnOut", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) - // private void arclight$blockBurn(Level worldIn, BlockPos pos, int chance, RandomSource random, int age, CallbackInfo ci) { - // Block theBlock = CraftBlock.at(worldIn, pos); - // Block sourceBlock = CraftBlock.at(worldIn, pos.relative(face)); - // BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); - // Bukkit.getPluginManager().callEvent(event); - // if (event.isCancelled()) { - // ci.cancel(); - // return; - // } - // if (worldIn.getBlockState(pos).getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(worldIn, pos, TNTPrimeEvent.PrimeCause.FIRE, null, pos.relative(face))) { - // ci.cancel(); - // } - // } + // @Inject(method = "checkBurnOut", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) + // private void arclight$blockBurn(Level worldIn, BlockPos pos, int i, RandomSource randomSource, int j, CallbackInfo ci) { + // Block theBlock = CraftBlock.at(worldIn, pos); + // Block sourceBlock = CraftBlock.at(worldIn, pos.relative(face)); + // BlockBurnEvent event = new BlockBurnEvent(theBlock, sourceBlock); + // Bukkit.getPluginManager().callEvent(event); + // if (event.isCancelled()) { + // ci.cancel(); + // return; + // } + // if (worldIn.getBlockState(pos).getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(worldIn, pos, TNTPrimeEvent.PrimeCause.FIRE, null, pos.relative(face))) { + // ci.cancel(); + // } + // } } diff --git a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Fabric.java b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Fabric.java index 23d17a4aa..2ab75d4ea 100644 --- a/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Fabric.java +++ b/arclight-fabric/src/main/java/io/izzel/arclight/fabric/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Fabric.java @@ -24,56 +24,4 @@ @Mixin(BrewingStandBlockEntity.class) public class BrewingStandBlockEntityMixin_Fabric { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private static void doBrew(Level level, BlockPos pos, NonNullList stacks) { - ItemStack itemStack = stacks.get(3); - - if (arclight$brewEvent(level, pos, stacks, itemStack)) { - return; - } - - itemStack.shrink(1); - if (itemStack.getItem().hasCraftingRemainingItem()) { - ItemStack itemStack2 = new ItemStack(itemStack.getItem().getCraftingRemainingItem()); - if (itemStack.isEmpty()) { - itemStack = itemStack2; - } else { - Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemStack2); - } - } - - stacks.set(3, itemStack); - level.levelEvent(1035, pos, 0); - } - - private static boolean arclight$brewEvent(Level level, BlockPos pos, NonNullList stacks, ItemStack ing) { - List brewResults = new ArrayList<>(3); - for (int i = 0; i < 3; ++i) { - var input = stacks.get(i); - var output = ((WorldBridge) level).bridge$forge$potionBrewMix(input, ing); - brewResults.add(i, CraftItemStack.asCraftMirror(output.isEmpty() ? input : output)); - } - BrewingStandBlockEntity entity = ArclightCaptures.getTickingBlockEntity(); - InventoryHolder owner = entity == null ? null : ((TileEntityBridge) entity).bridge$getOwner(); - if (owner != null) { - BrewEvent event = new BrewEvent(CraftBlock.at(level, pos), (BrewerInventory) owner.getInventory(), brewResults, entity.fuel); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return true; - } else { - for (int i = 0; i < 3; ++i) { - if (i < brewResults.size()) { - stacks.set(i, CraftItemStack.asNMSCopy(brewResults.get(i))); - } else { - stacks.set(i, ItemStack.EMPTY); - } - } - } - } - return false; - } } diff --git a/arclight-fabric/src/main/resources/mixins.arclight.fabric.json b/arclight-fabric/src/main/resources/mixins.arclight.fabric.json index 2f5fbd054..d3f028827 100644 --- a/arclight-fabric/src/main/resources/mixins.arclight.fabric.json +++ b/arclight-fabric/src/main/resources/mixins.arclight.fabric.json @@ -18,6 +18,7 @@ "bukkit.CraftHumanEntityMixin_Fabric", "bukkit.CraftServerMixin_Fabric", "core.network.ServerCommonPacketListenerImplMixin_Fabric", + "core.network.ServerConfigurationPacketListenerImplMixin_Fabric", "core.network.ServerLoginNetHandlerMixin_Fabric", "core.world.entity.EntityMixin_Fabric", "core.world.entity.LivingEntityMixin_Fabric", diff --git a/arclight-forge/build.gradle b/arclight-forge/build.gradle index dc1cb065a..ec254e702 100644 --- a/arclight-forge/build.gradle +++ b/arclight-forge/build.gradle @@ -87,10 +87,11 @@ tasks.register('forgeMappings', Copy) { project.sourceSets.main.output.dir file("build/forge_mappings"), builtBy: tasks.forgeMappings processResources { - inputs.property "version", project.version + def ver = "${project.version}+$gitHash" + inputs.property 'version', ver filesMatching("META-INF/mods.toml") { - expand "version": project.version + expand "version": ver } } @@ -105,22 +106,23 @@ shadowJar { remapJar { inputFile.set shadowJar.archiveFile dependsOn shadowJar + enabled = false } tasks.register('reobfJar', RenameJarTask) { - inputJar.set remapJar.archiveFile + inputJar.set shadowJar.archiveFile archiveClassifier.set 'reobf' mappings = arclight.mappingsConfiguration.reobfBukkitPackage } tasks.register('srgJar', Jar) { - from(tasks.remapJar.outputs.files.collect { it.isDirectory() ? it : zipTree(it) }) { + from(tasks.shadowJar.outputs.files.collect { it.isDirectory() ? it : zipTree(it) }) { include 'io/izzel/**' exclude 'io/izzel/arclight/common/mixin/**' exclude 'io/izzel/arclight/forge/mixin/**' } archiveClassifier.set('srg') - dependsOn remapJar + dependsOn shadowJar } tasks.register('spigotJar', RenameJarTask) { diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/bukkit/MaterialMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/bukkit/MaterialMixin_Forge.java index 8cef20622..9cd6ad156 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/bukkit/MaterialMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/bukkit/MaterialMixin_Forge.java @@ -1,30 +1,14 @@ package io.izzel.arclight.forge.mixin.bukkit; import io.izzel.arclight.common.bridge.bukkit.MaterialBridge; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.registries.ForgeRegistries; import org.bukkit.Material; -import org.bukkit.craftbukkit.v.util.CraftMagicNumbers; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(value = Material.class, remap = false) public abstract class MaterialMixin_Forge implements MaterialBridge { - @Override - public int bridge$forge$getMaxStackSize(Item item) { - return item.getMaxStackSize(new ItemStack(item)); - } - - @Override - public int bridge$forge$getDurability(Item item) { - return item.getMaxDamage(new ItemStack(item)); - } - @Override public int bridge$forge$getBurnTime(Item item) { return new ItemStack(item).getBurnTime(null); diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerCommonPacketListenerImplMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerCommonPacketListenerImplMixin_Forge.java index 5e1a6cd64..cdb0c110c 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerCommonPacketListenerImplMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerCommonPacketListenerImplMixin_Forge.java @@ -10,8 +10,4 @@ @Mixin(ServerCommonPacketListenerImpl.class) public abstract class ServerCommonPacketListenerImplMixin_Forge implements ServerCommonPacketListenerBridge { - @Override - public FriendlyByteBuf bridge$getDiscardedData(ServerboundCustomPayloadPacket packet) { - return packet.getInternalData(); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerLoginNetHandlerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerLoginNetHandlerMixin_Forge.java index 3bc08a8e4..028bc3038 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerLoginNetHandlerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerLoginNetHandlerMixin_Forge.java @@ -1,8 +1,6 @@ package io.izzel.arclight.forge.mixin.core.network; import io.izzel.arclight.common.bridge.core.network.login.ServerLoginNetHandlerBridge; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; import net.minecraft.server.network.ServerLoginPacketListenerImpl; import net.minecraftforge.fml.util.thread.SidedThreadGroups; import org.spongepowered.asm.mixin.Mixin; @@ -14,9 +12,4 @@ public abstract class ServerLoginNetHandlerMixin_Forge implements ServerLoginNet public Thread bridge$newHandleThread(String name, Runnable runnable) { return new Thread(SidedThreadGroups.SERVER, runnable, name); } - - @Override - public FriendlyByteBuf bridge$getDiscardedQueryAnswerData(ServerboundCustomQueryAnswerPacket payload) { - return payload.getInternalData(); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerPlayNetHandlerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerPlayNetHandlerMixin_Forge.java index 922e4859d..8933936ac 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerPlayNetHandlerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/ServerPlayNetHandlerMixin_Forge.java @@ -35,6 +35,6 @@ public abstract class ServerPlayNetHandlerMixin_Forge extends ServerCommonPacket @Override public InteractionResult bridge$platform$onInteractEntityAt(ServerPlayer player, Entity entity, Vec3 vec, InteractionHand interactionHand) { - return ForgeHooks.onInteractEntityAt(player, entity, vec, interactionHand); + return ForgeHooks.onInteractEntityAt(entity, player, vec, interactionHand); } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_Forge.java new file mode 100644 index 000000000..5b3f856fb --- /dev/null +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_Forge.java @@ -0,0 +1,37 @@ +package io.izzel.arclight.forge.mixin.core.network.protocol.login; + +import io.izzel.arclight.common.mod.util.ArclightCustomQueryAnswerPayload; +import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; +import net.minecraft.network.protocol.login.custom.DiscardedQueryAnswerPayload; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ServerboundCustomQueryAnswerPacket.class) +public class ServerboundCustomQueryAnswerPacketMixin_Forge { + + @Shadow @Final private static int MAX_PAYLOAD_SIZE; + + @Inject(method = "readPayload", cancellable = true, at = @At("HEAD")) + private static void readResponse(int id, FriendlyByteBuf buf, CallbackInfoReturnable cir) { + boolean hasPayload = buf.readBoolean(); + if (!hasPayload) { + cir.setReturnValue(DiscardedQueryAnswerPayload.INSTANCE); + return; + } + int i = buf.readableBytes(); + if (i >= 0 && i < MAX_PAYLOAD_SIZE) { + var payload = Unpooled.buffer(i); + buf.readBytes(payload); + cir.setReturnValue(new ArclightCustomQueryAnswerPayload(payload)); + } else { + throw new IllegalArgumentException("Payload may not be larger than 1048576 bytes"); + } + } +} diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/server/management/ServerPlayerGameModeMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/server/management/ServerPlayerGameModeMixin_Forge.java index 8f9a256fa..b6b4b8148 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/server/management/ServerPlayerGameModeMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/server/management/ServerPlayerGameModeMixin_Forge.java @@ -18,7 +18,7 @@ public abstract class ServerPlayerGameModeMixin_Forge implements PlayerInteracti ArclightCaptures.captureNextBlockBreakEventAsPrimaryEvent(); } - @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I")) + @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, remap = false, target = "Lnet/minecraftforge/common/ForgeHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I")) public void arclight$handleSecondaryBlockBreakEvents(BlockPos pos, CallbackInfoReturnable cir) { ArclightCaptures.BlockBreakEventContext breakEventContext = ArclightCaptures.popSecondaryBlockBreakEvent(); while (breakEventContext != null) { diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/EntityMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/EntityMixin_Forge.java index a30b44457..6abcfe879 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/EntityMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/EntityMixin_Forge.java @@ -2,34 +2,26 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import io.izzel.arclight.common.mod.util.ArclightCaptures; import io.izzel.tools.product.Product; import io.izzel.tools.product.Product4; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.FluidTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.extensions.IForgeEntity; import net.minecraftforge.entity.PartEntity; import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.entity.EntityTeleportEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import javax.annotation.Nullable; import java.util.Collection; @Mixin(Entity.class) @@ -38,7 +30,6 @@ public abstract class EntityMixin_Forge implements EntityBridge, IForgeEntity { // @formatter:off @Shadow public abstract Level level(); @Shadow public abstract boolean isRemoved(); - @Shadow @org.jetbrains.annotations.Nullable protected abstract PortalInfo findDimensionEntryPoint(ServerLevel serverLevel); @Shadow private float yRot; @Shadow private float xRot; @Shadow public abstract float getXRot(); @@ -81,74 +72,6 @@ public abstract class EntityMixin_Forge implements EntityBridge, IForgeEntity { return drops; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @Nullable - public Entity changeDimension(ServerLevel arg) { - return this.changeDimension(arg, arg.getPortalForcer()); - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - @Nullable - public Entity changeDimension(ServerLevel server, net.minecraftforge.common.util.ITeleporter teleporter) { - if (ForgeEventFactory.onTravelToDimension((Entity) (Object) this, server.dimension())) - return null; - if (this.level() instanceof ServerLevel && !this.isRemoved()) { - this.level().getProfiler().push("changeDimension"); - if (server == null) { - return null; - } - this.level().getProfiler().push("reposition"); - var bukkitPos = bridge$getLastTpPos(); - PortalInfo portalinfo = bukkitPos == null ? teleporter.getPortalInfo((Entity) (Object) this, server, this::findDimensionEntryPoint) - : new PortalInfo(new Vec3(bukkitPos.x(), bukkitPos.y(), bukkitPos.z()), Vec3.ZERO, this.yRot, this.xRot); - if (portalinfo == null) { - return null; - } else { - ServerLevel world = ((PortalInfoBridge) portalinfo).bridge$getWorld() == null ? server : ((PortalInfoBridge) portalinfo).bridge$getWorld(); - if (world == this.level()) { - this.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, this.getXRot()); - this.setDeltaMovement(portalinfo.speed); - return (Entity) (Object) this; - } - this.unRide(); - Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerLevel) this.level(), world, this.getYRot(), spawnPortal -> { //Forge: Start vanilla logic - this.level().getProfiler().popPush("reloading"); - Entity entity = this.getType().create(world); - if (entity != null) { - entity.restoreFrom((Entity) (Object) this); - entity.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, entity.getXRot()); - entity.setDeltaMovement(portalinfo.speed); - if (this.bridge$isInWorld()) { - world.addDuringTeleport(entity); - if (((WorldBridge) world).bridge$getTypeKey() == LevelStem.END) { - ArclightCaptures.captureEndPortalEntity((Entity) (Object) this, spawnPortal); - ServerLevel.makeObsidianPlatform(world); - } - } - } - return entity; - }); //Forge: End vanilla logic - - this.removeAfterChangingDimensions(); - this.level().getProfiler().pop(); - ((ServerLevel) this.level()).resetEmptyTime(); - world.resetEmptyTime(); - this.level().getProfiler().pop(); - return transportedEntity; - } - } else { - return null; - } - } - @Override public boolean bridge$forge$isPartEntity() { return (Object) this instanceof PartEntity; diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java index 48b9aebb5..73dd3c898 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java @@ -2,9 +2,8 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffectInstance; @@ -13,12 +12,8 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.event.entity.living.LivingChangeTargetEvent; -import net.minecraftforge.event.entity.living.MobEffectEvent; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -37,7 +32,7 @@ public abstract class LivingEntityMixin_Forge extends EntityMixin_Forge implemen // @formatter:off @Shadow public abstract boolean isSleeping(); @Shadow public abstract Collection getActiveEffects(); - @Shadow protected abstract void dropExperience(); + @Shadow protected abstract void dropExperience(@Nullable Entity entity); // @formatter:on @Inject(method = "hurt", cancellable = true, at = @At("HEAD")) @@ -65,39 +60,13 @@ public abstract class LivingEntityMixin_Forge extends EntityMixin_Forge implemen } } - @Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience()V")) - private void arclight$dropLater(LivingEntity livingEntity) { + @Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$dropLater(LivingEntity instance, Entity entity) { } @Inject(method = "dropAllDeathLoot", at = @At("RETURN")) - private void arclight$dropLast(DamageSource damageSourceIn, CallbackInfo ci) { - this.dropExperience(); - } - - @Override - public boolean bridge$forge$mobEffectExpired(MobEffectInstance effect) { - return MinecraftForge.EVENT_BUS.post(new MobEffectEvent.Expired((LivingEntity) (Object) this, effect)); - } - - @Override - public boolean bridge$forge$mobEffectAdded(MobEffectInstance old, MobEffectInstance effect, Entity entity) { - return MinecraftForge.EVENT_BUS.post(new MobEffectEvent.Added((LivingEntity) (Object) this, old, effect, entity)); - } - - @Override - public float bridge$forge$onLivingHurt(LivingEntity entity, DamageSource src, float amount) { - return ForgeHooks.onLivingHurt(entity, src, amount); - } - - @Override - public Product3 bridge$forge$onShieldBlock(LivingEntity blocker, DamageSource source, float blocked) { - var event = ForgeEventFactory.onShieldBlock(blocker, source, blocked); - return Product.of(event.isCanceled(), event.getBlockedDamage(), event.shieldTakesDamage()); - } - - @Override - public float bridge$forge$onLivingDamage(LivingEntity entity, DamageSource src, float amount) { - return ForgeHooks.onLivingDamage(entity, src, amount); + private void arclight$dropLast(ServerLevel arg, DamageSource damageSource, CallbackInfo ci) { + this.dropExperience(damageSource.getEntity()); } @Override @@ -105,19 +74,6 @@ public abstract class LivingEntityMixin_Forge extends EntityMixin_Forge implemen return ForgeHooks.onLivingUseTotem(entity, damageSource, totem, hand); } - @Nullable - @Override - public LivingEntity bridge$forge$onLivingChangeTarget(LivingEntity entity, LivingEntity originalTarget, LivingTargetType targetType) { - var event = ForgeHooks.onLivingChangeTarget(entity, originalTarget, LivingChangeTargetEvent.LivingTargetType.valueOf(targetType.name())); - return event.isCanceled() ? null : event.getNewTarget(); - } - - @Override - public BlockPos bridge$forge$onEnderTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { - var event = ForgeEventFactory.onEnderTeleport(entity, targetX, targetY, targetZ); - return event.isCanceled() ? null : BlockPos.containing(event.getTarget()); - } - @Override public void bridge$forge$onLivingConvert(LivingEntity entity, LivingEntity outcome) { ForgeEventFactory.onLivingConvert(entity, outcome); @@ -128,11 +84,6 @@ public abstract class LivingEntityMixin_Forge extends EntityMixin_Forge implemen return ForgeHooks.canEntityDestroy(level, pos, entity); } - @Override - public boolean bridge$forge$onEntityDestroyBlock(LivingEntity entity, BlockPos pos, BlockState state) { - return ForgeEventFactory.onEntityDestroyBlock(entity, pos, state); - } - @Override public void bridge$common$startCaptureDrops() { } @@ -152,6 +103,6 @@ public abstract class LivingEntityMixin_Forge extends EntityMixin_Forge implemen } @Override - public void bridge$common$finishCaptureAndFireEvent() { + public void bridge$common$finishCaptureAndFireEvent(DamageSource damageSource) { } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/animal/frog/TadpoleMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/animal/frog/TadpoleMixin_Forge.java index 505217421..516c996ef 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/animal/frog/TadpoleMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/animal/frog/TadpoleMixin_Forge.java @@ -17,17 +17,4 @@ @Mixin(Tadpole.class) public abstract class TadpoleMixin_Forge { - // @formatter:off - @Shadow protected abstract void setAge(int p_218711_); - // @formatter:on - - @Inject(method = "ageUp()V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void arclight$transform(CallbackInfo ci, Level level, ServerLevel serverLevel, Frog frog) { - if (CraftEventFactory.callEntityTransformEvent((Tadpole) (Object) this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { - this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled - ci.cancel(); - } else { - ((ServerWorldBridge) serverLevel).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); - } - } } \ No newline at end of file diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java index 7a078aee0..47bc79b26 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/item/ItemEntityMixin_Forge.java @@ -2,26 +2,8 @@ import io.izzel.arclight.common.bridge.core.entity.item.ItemEntityBridge; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.event.ForgeEventFactory; import org.spongepowered.asm.mixin.Mixin; @Mixin(ItemEntity.class) public class ItemEntityMixin_Forge implements ItemEntityBridge { - - @Override - public int bridge$forge$onItemPickup(Player player) { - return ForgeEventFactory.onItemPickup((ItemEntity) (Object) this, player); - } - - @Override - public void bridge$forge$firePlayerItemPickupEvent(Player player, ItemStack clone) { - ForgeEventFactory.firePlayerItemPickupEvent(player, (ItemEntity) (Object) this, clone); - } - - @Override - public boolean bridge$common$itemDespawnEvent() { - return true; - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/monster/ZombieMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/monster/ZombieMixin_Forge.java index c56bfce12..04281679f 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/monster/ZombieMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/monster/ZombieMixin_Forge.java @@ -1,28 +1,8 @@ package io.izzel.arclight.forge.mixin.core.world.entity.monster; -import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.monster.Zombie; -import net.minecraftforge.event.entity.living.ZombieEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityTargetEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Zombie.class) public class ZombieMixin_Forge { - - @Inject(method = "hurt", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Zombie;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$spawnWithReasonForge(DamageSource source, float amount, CallbackInfoReturnable cir, ServerLevel world, LivingEntity livingEntity, int i, int j, int k, ZombieEvent.SummonAidEvent event, net.minecraft.world.entity.monster.Zombie zombieEntity) { - ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); - if (livingEntity != null) { - ((MobEntityBridge) zombieEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); - } - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/PlayerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/PlayerMixin_Forge.java index 2542438d5..952755a98 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/PlayerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/PlayerMixin_Forge.java @@ -2,23 +2,13 @@ import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.forge.mixin.core.world.entity.LivingEntityMixin_Forge; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; -import io.izzel.tools.product.Product6; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; -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.player.Abilities; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.extensions.IForgePlayer; -import net.minecraftforge.eventbus.api.Event; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -50,29 +40,4 @@ public abstract class PlayerMixin_Forge extends LivingEntityMixin_Forge implemen } } - @Override - public Float bridge$forge$getCriticalHit(Player player, Entity target, boolean vanillaCritical, float damageModifier) { - var hit = ForgeHooks.getCriticalHit(player, target, vanillaCritical, damageModifier); - return hit == null ? null : hit.getDamageModifier(); - } - - @Override - public double bridge$forge$getEntityReach() { - return this.getEntityReach(); - } - - @Override - public Product3 bridge$platform$onLeftClickBlock(BlockPos pos, Direction direction, ServerboundPlayerActionPacket.Action action) { - var event = ForgeHooks.onLeftClickBlock((Player) (Object) this, pos, direction, action); - return Product.of(event.isCanceled(), event.getUseItem() == Event.Result.DENY, event.getUseBlock() == Event.Result.DENY); - } - - @Override - public Product6 bridge$platform$onRightClickBlock(InteractionHand hand, BlockPos pos, BlockHitResult hitResult) { - var event = ForgeHooks.onRightClickBlock((Player) (Object) this, hand, pos, hitResult); - return Product.of(event.isCanceled(), - event.getUseItem() == Event.Result.ALLOW, event.getUseItem() == Event.Result.DENY, - event.getUseBlock() == Event.Result.ALLOW, event.getUseBlock() == Event.Result.DENY, - event.getCancellationResult()); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/ServerPlayerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/ServerPlayerMixin_Forge.java index 39b7c252c..b8af2853b 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/ServerPlayerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/entity/player/ServerPlayerMixin_Forge.java @@ -1,62 +1,18 @@ package io.izzel.arclight.forge.mixin.core.world.entity.player; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import io.izzel.arclight.common.mod.server.block.ChestBlockDoubleInventoryHacks; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.core.BlockPos; -import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; -import net.minecraft.network.protocol.game.ClientboundGameEventPacket; -import net.minecraft.network.protocol.game.ClientboundLevelEventPacket; -import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; -import net.minecraft.network.protocol.game.ClientboundRespawnPacket; -import net.minecraft.network.protocol.game.ClientboundUpdateMobEffectPacket; import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; -import net.minecraft.resources.ResourceKey; 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.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.Container; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.portal.PortalInfo; -import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.util.ITeleporter; -import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.event.entity.player.PlayerContainerEvent; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v.CraftWorld; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; -import java.util.OptionalInt; @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Forge extends PlayerMixin_Forge implements ServerPlayerEntityBridge { @@ -70,7 +26,6 @@ public abstract class ServerPlayerMixin_Forge extends PlayerMixin_Forge implemen @Shadow public abstract CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel arg); @Shadow @Final public MinecraftServer server; @Shadow @Nullable private Vec3 enteredNetherPosition; - @Shadow protected abstract void createEndPlatform(ServerLevel arg, BlockPos arg2); @Shadow public abstract void setServerLevel(ServerLevel arg); @Shadow public abstract void triggerDimensionChangeTriggers(ServerLevel arg); @Shadow @Final public ServerPlayerGameMode gameMode; @@ -78,170 +33,4 @@ public abstract class ServerPlayerMixin_Forge extends PlayerMixin_Forge implemen @Shadow private float lastSentHealth; @Shadow private int lastSentFood; // @formatter:on - - @Inject(method = "die", cancellable = true, at = @At("HEAD")) - private void arclight$onDeath(DamageSource source, CallbackInfo ci) { - if (net.minecraftforge.common.ForgeHooks.onLivingDeath((ServerPlayer) (Object) this, source)) { - ci.cancel(); - } - } - - @Inject(method = "openHorseInventory", at = @At("TAIL")) - private void arclight$openHorstContainer(AbstractHorse arg, Container arg2, CallbackInfo ci) { - MinecraftForge.EVENT_BUS.post(new PlayerContainerEvent.Open((ServerPlayer) (Object) this, this.containerMenu)); - } - - @Inject(method = "setRespawnPosition", cancellable = true, at = @At("HEAD")) - private void arclight$forgeRespawnPos(ResourceKey arg, BlockPos arg2, float f, boolean bl, boolean bl2, CallbackInfo ci) { - if (ForgeEventFactory.onPlayerSpawnSet((ServerPlayer) (Object) this, arg2 == null ? Level.OVERWORLD : arg, arg2, bl)) { - ci.cancel(); - } - } - - /** - * @author IzzelAliz - * @reason - */ - @Override - @Nullable - public Entity changeDimension(ServerLevel arg) { - return this.changeDimension(arg, arg.getPortalForcer()); - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - @Nullable - public Entity changeDimension(ServerLevel server, ITeleporter teleporter) { - PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN); - if (this.isSleeping()) { - return (ServerPlayer) (Object) this; - } - if (ForgeEventFactory.onTravelToDimension((ServerPlayer) (Object) this, server.dimension())) return null; - - // this.invulnerableDimensionChange = true; - ServerLevel serverworld = this.serverLevel(); - ResourceKey registrykey = ((WorldBridge) serverworld).bridge$getTypeKey(); - if (registrykey == LevelStem.END && ((WorldBridge) server).bridge$getTypeKey() == LevelStem.OVERWORLD && teleporter.isVanilla()) { //Forge: Fix non-vanilla teleporters triggering end credits - this.isChangingDimension = true; - this.unRide(); - this.serverLevel().removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - if (!this.wonGame) { - this.wonGame = true; - this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); - this.seenCredits = true; - } - - return (ServerPlayer) (Object) this; - } else { - PortalInfo portalinfo = teleporter.getPortalInfo((ServerPlayer) (Object) this, server, this::findDimensionEntryPoint); - if (portalinfo != null) { - if (((PortalInfoBridge) portalinfo).bridge$getWorld() != null) { - server = ((PortalInfoBridge) portalinfo).bridge$getWorld(); - } - ServerLevel[] exitWorld = new ServerLevel[]{server}; - LevelData iworldinfo = server.getLevelData(); - this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(server), (byte) 3)); - this.connection.send(new ClientboundChangeDifficultyPacket(iworldinfo.getDifficulty(), iworldinfo.isDifficultyLocked())); - PlayerList playerlist = this.server.getPlayerList(); - playerlist.sendPlayerPermissionLevel((ServerPlayer) (Object) this); - this.serverLevel().removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - this.revive(); - Entity e = teleporter.placeEntity((ServerPlayer) (Object) this, serverworld, exitWorld[0], this.getYRot(), spawnPortal -> {//Forge: Start vanilla logic - serverworld.getProfiler().push("moving"); - if (exitWorld[0] != null) { - if (registrykey == LevelStem.OVERWORLD && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.NETHER) { - this.enteredNetherPosition = this.position(); - } else if (spawnPortal && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.END - && (((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo() == null || ((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo().getCanCreatePortal())) { - this.createEndPlatform(exitWorld[0], BlockPos.containing(portalinfo.pos)); - } - } - - Location enter = this.bridge$getBukkitEntity().getLocation(); - Location exit = (exitWorld[0] == null) ? null : new Location(exitWorld[0].bridge$getWorld(), portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, portalinfo.xRot); - PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.bridge$getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); - if (tpEvent.isCancelled() || tpEvent.getTo() == null) { - return null; - } - exit = tpEvent.getTo(); - - serverworld.getProfiler().pop(); - serverworld.getProfiler().push("placing"); - - this.isChangingDimension = true; - ServerLevel newWorld = ((CraftWorld) exit.getWorld()).getHandle(); - if (newWorld != exitWorld[0]) { - exitWorld[0] = newWorld; - LevelData newWorldInfo = exitWorld[0].getLevelData(); - this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(newWorld), (byte) 3)); - this.connection.send(new ClientboundChangeDifficultyPacket(newWorldInfo.getDifficulty(), newWorldInfo.isDifficultyLocked())); - } - - this.setServerLevel(exitWorld[0]); - exitWorld[0].addDuringPortalTeleport((ServerPlayer) (Object) this); - - ((ServerPlayNetHandlerBridge) this.connection).bridge$teleport(exit); - this.connection.resetPosition(); - - serverworld.getProfiler().pop(); - this.triggerDimensionChangeTriggers(exitWorld[0]); - return (ServerPlayer) (Object) this;//forge: this is part of the ITeleporter patch - });//Forge: End vanilla logic - if (e == null) { - serverworld.addDuringPortalTeleport((ServerPlayer) (Object) this); - return (ServerPlayer) (Object) this; - } else if (e != (Object) this) { - throw new IllegalArgumentException(String.format("Teleporter %s returned not the player entity but instead %s, expected PlayerEntity %s", teleporter, e, this)); - } - - this.gameMode.setLevel(exitWorld[0]); - this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); - playerlist.sendLevelInfo((ServerPlayer) (Object) this, exitWorld[0]); - playerlist.sendAllPlayerInfo((ServerPlayer) (Object) this); - - for (MobEffectInstance effectinstance : this.getActiveEffects()) { - this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectinstance)); - } - - if (teleporter.playTeleportSound((ServerPlayer) (Object) this, serverworld, exitWorld[0])) { - this.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); - } - this.lastSentExp = -1; - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - ForgeEventFactory.onPlayerChangedDimension((ServerPlayer) (Object) this, serverworld.dimension(), exitWorld[0].dimension()); - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.bridge$getBukkitEntity(), serverworld.bridge$getWorld()); - Bukkit.getPluginManager().callEvent(changeEvent); - } - - return (ServerPlayer) (Object) this; - } - } - - @Redirect(method = "openMenu", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;closeContainer()V")) - private void arclight$skipSwitch(ServerPlayer serverPlayer) { - } - - @Inject(method = "openMenu", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/MenuProvider;createMenu(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/inventory/AbstractContainerMenu;")) - private void arclight$invOpen(MenuProvider iTileInventory, CallbackInfoReturnable cir, AbstractContainerMenu container) { - if (container != null) { - ((ContainerBridge) container).bridge$setTitle(iTileInventory.getDisplayName()); - boolean cancelled = false; - ArclightCaptures.captureContainerOwner((ServerPlayer) (Object) this); - container = CraftEventFactory.callInventoryOpenEvent((ServerPlayer) (Object) this, container, cancelled); - ArclightCaptures.resetContainerOwner(); - if (container == null && !cancelled) { - if (iTileInventory instanceof Container) { - ((Container) iTileInventory).stopOpen((ServerPlayer) (Object) this); - } else if (ChestBlockDoubleInventoryHacks.isInstance(iTileInventory)) { - ChestBlockDoubleInventoryHacks.get(iTileInventory).stopOpen((ServerPlayer) (Object) this); - } - cir.setReturnValue(OptionalInt.empty()); - } - } - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/food/FoodDataMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/food/FoodDataMixin_Forge.java index 2dc2ce3a2..08eff0cbc 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/food/FoodDataMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/food/FoodDataMixin_Forge.java @@ -1,21 +1,9 @@ package io.izzel.arclight.forge.mixin.core.world.food; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodData; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.FoodLevelChangeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import javax.annotation.Nullable; @Mixin(FoodData.class) public abstract class FoodDataMixin_Forge implements FoodStatsBridge { @@ -24,28 +12,4 @@ public abstract class FoodDataMixin_Forge implements FoodStatsBridge { @Shadow public int foodLevel; @Shadow public abstract void eat(int i, float f); // @formatter:on - - @Redirect(method = "eat(Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)V", remap = false, - at = @At(value = "INVOKE", remap = true, target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) - private void arclight$foodLevelChangeForge(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, Item maybeFood, ItemStack stack, @Nullable LivingEntity entity) { - var player = this.bridge$getEntityHuman() != null ? this.bridge$getEntityHuman() : (entity instanceof Player p ? p : null); - if (player == null) { - foodStats.eat(foodLevelIn, foodSaturationModifier); - return; - } else if (this.bridge$getEntityHuman() == null) { - this.bridge$setEntityHuman(player); - } - FoodProperties food = maybeFood.getFoodProperties(stack, entity); - int oldFoodLevel = this.foodLevel; - FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(player, food.getNutrition() + oldFoodLevel, stack); - if (!event.isCancelled()) { - this.eat(event.getFoodLevel() - oldFoodLevel, food.getSaturationModifier()); - } - ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity().sendHealthUpdate(); - } - - @Override - public FoodProperties bridge$forge$getFoodProperties(ItemStack stack, LivingEntity entity) { - return stack.getFoodProperties(entity); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/inventory/AbstractContainerMenuMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/inventory/AbstractContainerMenuMixin_Forge.java index c0dbb0342..d3e04be98 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/inventory/AbstractContainerMenuMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/inventory/AbstractContainerMenuMixin_Forge.java @@ -1,20 +1,10 @@ package io.izzel.arclight.forge.mixin.core.world.inventory; import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import net.minecraft.world.entity.SlotAccess; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickAction; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.ForgeHooks; import org.spongepowered.asm.mixin.Mixin; @Mixin(AbstractContainerMenu.class) public abstract class AbstractContainerMenuMixin_Forge implements ContainerBridge { - @Override - public boolean bridge$forge$onItemStackedOn(ItemStack carriedItem, ItemStack stackedOnItem, Slot slot, ClickAction action, Player player, SlotAccess carriedSlotAccess) { - return ForgeHooks.onItemStackedOn(carriedItem, stackedOnItem, slot, action, player, carriedSlotAccess); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemMixin_Forge.java index cb13bfdbf..54350a632 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemMixin_Forge.java @@ -5,7 +5,6 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; -import net.minecraft.world.item.ArrowItem; import net.minecraft.world.item.BowItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -28,11 +27,6 @@ public class ItemMixin_Forge implements ItemBridge { return ForgeEventFactory.onArrowLoose(stack, level, player, charge, hasAmmo); } - @Override - public boolean bridge$forge$isInfinite(ArrowItem item, ItemStack stack, ItemStack bow, Player player) { - return item.isInfinite(stack, bow, player); - } - @Override public boolean bridge$forge$onChorusFruitTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { return ForgeEventFactory.onChorusFruitTeleport(entity, targetX, targetY, targetZ).isCanceled(); diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemStackMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemStackMixin_Forge.java index 748544477..c5c51d579 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemStackMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/ItemStackMixin_Forge.java @@ -2,77 +2,28 @@ import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.LevelReader; -import net.minecraft.world.phys.AABB; -import net.minecraftforge.common.capabilities.CapabilityProvider; import net.minecraftforge.common.extensions.IForgeItemStack; -import net.minecraftforge.registries.ForgeRegistries; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import javax.annotation.Nullable; -import java.util.Locale; @Mixin(ItemStack.class) -public abstract class ItemStackMixin_Forge extends CapabilityProvider implements ItemStackBridge, IForgeItemStack { +public abstract class ItemStackMixin_Forge implements ItemStackBridge, IForgeItemStack { // @formatter:off - @Shadow(remap = false) private CompoundTag capNBT; - @Mutable @Shadow(remap = false) @Final private net.minecraft.core.Holder.Reference delegate; @Shadow @Deprecated @Nullable private Item item; // @formatter:on - protected ItemStackMixin_Forge(Class baseClass) { - super(baseClass); - } - - @Override - public CompoundTag bridge$getForgeCaps() { - return this.serializeCaps(); - } - - @Override - public void bridge$setForgeCaps(CompoundTag caps) { - this.capNBT = caps; - if (caps != null) { - this.deserializeCaps(caps); - } - } - @Deprecated public void setItem(Item item) { this.item = item; - this.delegate = ForgeRegistries.ITEMS.getDelegateOrThrow(item); - } - - @Override - public boolean bridge$forge$hasCraftingRemainingItem() { - return this.hasCraftingRemainingItem(); - } - - @Override - public ItemStack bridge$forge$getCraftingRemainingItem() { - return this.getCraftingRemainingItem(); - } - - @Override - public boolean bridge$forge$canPerformAction(ToolAction action) { - return this.canPerformAction(net.minecraftforge.common.ToolAction.get(action.name().toLowerCase(Locale.ROOT))); - } - - @Override - public AABB bridge$forge$getSweepHitBox(@NotNull Player player, @NotNull Entity target) { - return this.getSweepHitBox(player, target); } @Override diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/crafting/RecipeManagerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/crafting/RecipeManagerMixin_Forge.java index f7bbf38b0..cda9aefbe 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/crafting/RecipeManagerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/item/crafting/RecipeManagerMixin_Forge.java @@ -1,11 +1,6 @@ package io.izzel.arclight.forge.mixin.core.world.item.crafting; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeManagerBridge; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraftforge.common.crafting.conditions.ICondition; import org.spongepowered.asm.mixin.Final; @@ -17,14 +12,5 @@ public abstract class RecipeManagerMixin_Forge implements RecipeManagerBridge { // @formatter:off @Shadow(remap = false) @Final private ICondition.IContext context; - @Shadow protected static RecipeHolder fromJson(ResourceLocation p_44046_, JsonObject p_44047_) { return null; } // @formatter:on - - @Override - public RecipeHolder bridge$platform$loadRecipe(ResourceLocation key, JsonElement element) { - if (element.isJsonObject() && !net.minecraftforge.common.ForgeHooks.readAndTestCondition(this.context, element.getAsJsonObject())) { - return null; - } - return fromJson(key, GsonHelper.convertToJsonObject(element, "top element")); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/BaseSpawnerMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/BaseSpawnerMixin_Forge.java index 53af98658..9737a21e9 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/BaseSpawnerMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/BaseSpawnerMixin_Forge.java @@ -18,22 +18,4 @@ @Mixin(BaseSpawner.class) public class BaseSpawnerMixin_Forge implements BaseSpawnerBridge { - @Override - public boolean bridge$forge$checkSpawnRules(Mob mob, ServerLevelAccessor level, MobSpawnType spawnType, SpawnData spawnData, boolean original) { - var spawnEvent = new MobSpawnEvent.PositionCheck(mob, level, spawnType, null); - MinecraftForge.EVENT_BUS.post(spawnEvent); - var result = spawnEvent.getResult(); - if (result == Event.Result.DEFAULT) { - return original; - } - return result == Event.Result.ALLOW; - } - - @Override - public void bridge$forge$finalizeSpawnerSpawn(Mob mob, ServerLevelAccessor level, DifficultyInstance difficulty, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag spawnTag) { - var event = net.minecraftforge.event.ForgeEventFactory.onFinalizeSpawnSpawner(mob, level, difficulty, spawnData, spawnTag, (BaseSpawner) (Object) this); - if (event != null) { - mob.finalizeSpawn(level, event.getDifficulty(), event.getSpawnType(), event.getSpawnData(), event.getSpawnTag()); - } - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/LevelMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/LevelMixin_Forge.java index d7566668a..39df39fe5 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/LevelMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/LevelMixin_Forge.java @@ -12,7 +12,6 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; -import net.minecraftforge.common.brewing.BrewingRecipeRegistry; import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.event.ForgeEventFactory; import org.bukkit.Bukkit; @@ -72,11 +71,6 @@ public abstract class LevelMixin_Forge implements WorldBridge { return ForgeEventFactory.getMobGriefingEvent((Level) (Object) this, entity); } - @Override - public ItemStack bridge$forge$potionBrewMix(ItemStack a, ItemStack b) { - return BrewingRecipeRegistry.getOutput(a, b); - } - @Override public void bridge$forge$onPotionBrewed(NonNullList stacks) { ForgeEventFactory.onPotionBrewed(stacks); diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/BlockMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/BlockMixin_Forge.java index 860f6adf0..e2fd4a6d6 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/BlockMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/BlockMixin_Forge.java @@ -3,34 +3,18 @@ import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.PoweredRailBlock; -import net.minecraft.world.level.block.entity.DispenserBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.extensions.IForgeBlock; -import net.minecraftforge.items.VanillaInventoryCodeHooks; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @Mixin(Block.class) public abstract class BlockMixin_Forge implements BlockBridge, IForgeBlock { - @Override - public int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) { - int silkTouch = itemStack.getEnchantmentLevel(Enchantments.SILK_TOUCH); - int fortune = itemStack.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE); - return this.getExpDrop(blockState, world, world.random, blockPos, fortune, silkTouch); - } - @Override public boolean bridge$forge$onCropsGrowPre(Level level, BlockPos pos, BlockState state, boolean def) { return ForgeHooks.onCropsGrowPre(level, pos, state, def); @@ -41,23 +25,9 @@ public abstract class BlockMixin_Forge implements BlockBridge, IForgeBlock { ForgeHooks.onCropsGrowPost(level, pos, state); } - @Override - public boolean bridge$forge$dropperInsertHook(Level level, BlockPos pos, DispenserBlockEntity dropper, int slot, @NotNull ItemStack stack) { - return VanillaInventoryCodeHooks.dropperInsertHook(level, pos, dropper, slot, stack); - } - @Override public void bridge$forge$onCaughtFire(BlockState state, Level level, BlockPos pos, @Nullable Direction direction, @Nullable LivingEntity igniter) { this.onCaughtFire(state, level, pos, direction, igniter); } - @Override - public boolean bridge$forge$isActivatorRail(BlockState state) { - return state.getBlock() instanceof PoweredRailBlock block && block.isActivatorRail(); - } - - @Override - public boolean bridge$forge$canEntityDestroy(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { - return this.canEntityDestroy(state, level, pos, entity); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java index 0679de8ab..38418a8d2 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/FireBlockMixin_Forge.java @@ -20,7 +20,7 @@ @Mixin(FireBlock.class) public class FireBlockMixin_Forge { - @Inject(method = "tryCatchFire", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) + @Inject(method = "checkBurnOut", cancellable = true, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")) private void arclight$blockBurn(Level worldIn, BlockPos pos, int chance, RandomSource random, int age, Direction face, CallbackInfo ci) { Block theBlock = CraftBlock.at(worldIn, pos); Block sourceBlock = CraftBlock.at(worldIn, pos.relative(face)); diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/TntBlockMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/TntBlockMixin_Forge.java index 4a72be3f0..5fcea20b4 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/TntBlockMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/TntBlockMixin_Forge.java @@ -3,10 +3,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.TntBlock; @@ -32,10 +33,10 @@ public abstract class TntBlockMixin_Forge extends BlockMixin_Forge { } } - @Inject(method = "use", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$player(BlockState p_57450_, Level level, BlockPos pos, Player player, InteractionHand p_57454_, BlockHitResult p_57455_, CallbackInfoReturnable cir) { + @Inject(method = "useItemOn", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$player(ItemStack arg, BlockState arg2, Level level, BlockPos pos, Player player, InteractionHand arg6, BlockHitResult arg7, CallbackInfoReturnable cir) { if (!CraftEventFactory.callTNTPrimeEvent(level, pos, TNTPrimeEvent.PrimeCause.PLAYER, player, null)) { - cir.setReturnValue(InteractionResult.CONSUME); + cir.setReturnValue(ItemInteractionResult.CONSUME); } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 1d7082c7a..2c8e46e9b 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -1,76 +1,9 @@ package io.izzel.arclight.forge.mixin.core.world.level.block.entity; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v.block.CraftBlock; -import org.bukkit.craftbukkit.v.inventory.CraftItemStack; -import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import javax.annotation.Nullable; @Mixin(AbstractFurnaceBlockEntity.class) public abstract class AbstractFurnaceBlockEntityMixin_Forge { - // @formatter:off - @Shadow protected abstract boolean canBurn(RegistryAccess p_266924_, @org.jetbrains.annotations.Nullable RecipeHolder p_155006_, NonNullList p_155007_, int p_155008_); - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private boolean burn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, NonNullList items, int i) { - if (recipe != null && this.canBurn(registryAccess, recipe, items, i)) { - ItemStack itemstack = items.get(0); - ItemStack itemstack1 = recipe.value().getResultItem(registryAccess); - ItemStack itemstack2 = items.get(2); - - if (ArclightCaptures.getTickingBlockEntity() != null) { - var blockEntity = ArclightCaptures.getTickingBlockEntity(); - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - - FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()), source, result); - Bukkit.getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { - return false; - } - - result = furnaceSmeltEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - } - - if (!itemstack1.isEmpty()) { - if (itemstack2.isEmpty()) { - items.set(2, itemstack1.copy()); - } else if (ItemStack.isSameItemSameTags(itemstack2, itemstack1)) { - itemstack2.grow(itemstack1.getCount()); - } else { - return false; - } - } - - if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) { - items.set(1, new ItemStack(Items.WATER_BUCKET)); - } - - itemstack.shrink(1); - return true; - } else { - return false; - } - } - } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Forge.java index 6b0197bec..c5e7f3c0a 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_Forge.java @@ -14,10 +14,4 @@ @Mixin(BrewingStandBlockEntity.class) public class BrewingStandBlockEntityMixin_Forge { - @Inject(method = "doBrew", cancellable = true, at = @At("HEAD")) - private static void arclight$forgeBrew(Level arg, BlockPos arg2, NonNullList stacks, CallbackInfo ci) { - if (ForgeEventFactory.onPotionAttemptBrew(stacks)) { - ci.cancel(); - } - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Forge.java index 58a835464..735241c8e 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_Forge.java @@ -17,18 +17,4 @@ @Mixin(StructureTemplate.class) public abstract class StructureTemplateMixin_Forge implements StructureTemplateBridge { - // @formatter:off - @Shadow(remap = false) public static List processBlockInfos(ServerLevelAccessor p_278297_, BlockPos p_74519_, BlockPos p_74520_, StructurePlaceSettings p_74521_, List p_74522_, @Nullable StructureTemplate template) { return null; } - @Shadow(remap = false) protected abstract void addEntitiesToWorld(ServerLevelAccessor par1, BlockPos par2, StructurePlaceSettings par3); - // @formatter:on - - @Override - public List bridge$platform$processBlockInfos(ServerLevelAccessor arg, BlockPos arg2, BlockPos arg3, StructurePlaceSettings arg4, List list2, @Nullable StructureTemplate template) { - return processBlockInfos(arg, arg2, arg3, arg4, list2, template); - } - - @Override - public void bridge$platform$placeEntities(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, Mirror mirror, Rotation rotation, BlockPos blockPos2, @Nullable BoundingBox boundingBox, boolean bl, StructurePlaceSettings placementIn) { - this.addEntitiesToWorld(serverLevelAccessor, blockPos, placementIn); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/storage/loot/LootContextMixin_Forge.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/storage/loot/LootContextMixin_Forge.java index 3b212e42d..698bb6c2d 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/storage/loot/LootContextMixin_Forge.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/core/world/level/storage/loot/LootContextMixin_Forge.java @@ -1,20 +1,10 @@ package io.izzel.arclight.forge.mixin.core.world.level.storage.loot; import io.izzel.arclight.common.bridge.core.world.storage.loot.LootContextBridge; -import net.minecraft.world.entity.Entity; import net.minecraft.world.level.storage.loot.LootContext; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; @Mixin(LootContext.class) public abstract class LootContextMixin_Forge implements LootContextBridge { - // @formatter:off - @Shadow(remap = false) public abstract int getLootingModifier(); - // @formatter:on - - @Override - public int bridge$forge$getLootingModifier(Entity entity) { - return this.getLootingModifier(); - } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/forge/RegisterChannelsTaskMixin.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/forge/RegisterChannelsTaskMixin.java index 764a3fa21..09d5fd5cc 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/forge/RegisterChannelsTaskMixin.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mixin/forge/RegisterChannelsTaskMixin.java @@ -16,6 +16,6 @@ public class RegisterChannelsTaskMixin { @Inject(method = "start(Lnet/minecraftforge/network/config/ConfigurationTaskContext;)V", at = @At("HEAD")) private void arclight$registerBukkitChannels(ConfigurationTaskContext ctx, CallbackInfo ci) { - ChannelListManager.addChannels(ctx.getConnection(), Bukkit.getMessenger().getIncomingChannels().stream().map(ResourceLocation::new).collect(Collectors.toList())); + ChannelListManager.addChannels(ctx.getConnection(), Bukkit.getMessenger().getIncomingChannels().stream().map(ResourceLocation::parse).collect(Collectors.toList())); } } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/event/EntityEventDispatcher.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/event/EntityEventDispatcher.java index c16d3e962..91d7a148e 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/event/EntityEventDispatcher.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/event/EntityEventDispatcher.java @@ -38,7 +38,7 @@ public void onLivingDeath(LivingDropsEvent event) { itemEntity.setDefaultPickUpDelay(); return itemEntity; }); - ArclightEventFactory.callEntityDeathEvent(livingEntity, itemStackList); + ArclightEventFactory.callEntityDeathEvent(livingEntity, itemStackList, event.getSource()); if (drops.isEmpty()) { event.setCanceled(true); } diff --git a/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/permission/ArclightPermissionHandler.java b/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/permission/ArclightPermissionHandler.java index 32dc464d9..23bbdfc67 100644 --- a/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/permission/ArclightPermissionHandler.java +++ b/arclight-forge/src/main/java/io/izzel/arclight/forge/mod/permission/ArclightPermissionHandler.java @@ -24,7 +24,7 @@ public ArclightPermissionHandler(IPermissionHandler delegate) { @Override public ResourceLocation getIdentifier() { - return new ResourceLocation("arclight", "permission"); + return ResourceLocation.parse("arclight:permission"); } @Override diff --git a/arclight-forge/src/main/resources/mixins.arclight.forge.json b/arclight-forge/src/main/resources/mixins.arclight.forge.json index bd9e3ca68..9dc00f1ee 100644 --- a/arclight-forge/src/main/resources/mixins.arclight.forge.json +++ b/arclight-forge/src/main/resources/mixins.arclight.forge.json @@ -26,6 +26,7 @@ "core.network.ServerLoginNetHandlerMixin_Forge", "core.network.ServerPlayNetHandlerMixin_Forge", "core.network.ServerStatusNetHandlerMixin_Forge", + "core.network.protocol.login.ServerboundCustomQueryAnswerPacketMixin_Forge", "core.network.protocol.status.ServerStatusMixin", "core.server.MinecraftServerMixin_Forge", "core.server.dedicated.DedicatedServerMixin_Forge", diff --git a/arclight-neoforge/build.gradle b/arclight-neoforge/build.gradle index b9ece74b5..a3224d05f 100644 --- a/arclight-neoforge/build.gradle +++ b/arclight-neoforge/build.gradle @@ -83,10 +83,11 @@ tasks.register('neoforgeMappings', Copy) { project.sourceSets.main.output.dir file('build/neoforge_mappings'), builtBy: tasks.neoforgeMappings processResources { - inputs.property 'version', project.version + def ver = "${project.version}+$gitHash" + inputs.property 'version', ver - filesMatching('META-INF/mods.toml') { - expand 'version': project.version + filesMatching('META-INF/neoforge.mods.toml') { + expand 'version': ver } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerCommonPacketListenerImplMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerCommonPacketListenerImplMixin_NeoForge.java index a5a9b12df..a4a3192c5 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerCommonPacketListenerImplMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerCommonPacketListenerImplMixin_NeoForge.java @@ -9,9 +9,4 @@ @Mixin(ServerCommonPacketListenerImpl.class) public abstract class ServerCommonPacketListenerImplMixin_NeoForge implements ServerCommonPacketListenerBridge { - @Override - public FriendlyByteBuf bridge$getDiscardedData(ServerboundCustomPayloadPacket packet) { - // Todo: Payload data. - return null; - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerConfigurationPacketListenerImplMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerConfigurationPacketListenerImplMixin_NeoForge.java new file mode 100644 index 000000000..0a6d841b2 --- /dev/null +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerConfigurationPacketListenerImplMixin_NeoForge.java @@ -0,0 +1,38 @@ +package io.izzel.arclight.neoforge.mixin.core.network; + +import io.izzel.arclight.common.mod.server.ArclightServer; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.ServerLinks; +import net.minecraft.server.network.ServerConfigurationPacketListenerImpl; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.CraftServerLinks; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerLinksSendEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ServerConfigurationPacketListenerImpl.class) +public abstract class ServerConfigurationPacketListenerImplMixin_NeoForge extends ServerCommonPacketListenerImplMixin_NeoForge { + + // @formatter:off + @Shadow protected abstract void runConfiguration(); + // @formatter:on + + @Decorate(method = "runConfiguration", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;serverLinks()Lnet/minecraft/server/ServerLinks;")) + private ServerLinks arclight$sendLinksEvent(MinecraftServer instance) throws Throwable { + var links = (ServerLinks) DecorationOps.callsite().invoke(instance); + var wrapper = new CraftServerLinks(links); + var event = new PlayerLinksSendEvent((Player) bridge$getPlayer().bridge$getBukkitEntity(), wrapper); + Bukkit.getPluginManager().callEvent(event); + return wrapper.getServerLinks(); + } + + @Redirect(method = "handlePong", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerConfigurationPacketListenerImpl;runConfiguration()V")) + private void arclight$runConfigurationMainThread(ServerConfigurationPacketListenerImpl instance) { + ArclightServer.executeOnMainThread(() -> this.runConfiguration()); + } +} diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerLoginNetHandlerMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerLoginNetHandlerMixin_NeoForge.java index 1893b6a8b..a08e55a80 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerLoginNetHandlerMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/ServerLoginNetHandlerMixin_NeoForge.java @@ -1,9 +1,6 @@ package io.izzel.arclight.neoforge.mixin.core.network; import io.izzel.arclight.common.bridge.core.network.login.ServerLoginNetHandlerBridge; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; -import net.minecraft.network.protocol.login.custom.DiscardedQueryAnswerPayload; import net.minecraft.server.network.ServerLoginPacketListenerImpl; import net.neoforged.fml.util.thread.SidedThreadGroups; import org.spongepowered.asm.mixin.Mixin; @@ -15,10 +12,4 @@ public abstract class ServerLoginNetHandlerMixin_NeoForge implements ServerLogin public Thread bridge$newHandleThread(String name, Runnable runnable) { return new Thread(SidedThreadGroups.SERVER, runnable, name); } - - @Override - public FriendlyByteBuf bridge$getDiscardedQueryAnswerData(ServerboundCustomQueryAnswerPacket payload) { - // Todo: Payload data. - return null; - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/common/CustomPayloadPacketMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/common/CustomPayloadPacketMixin_NeoForge.java new file mode 100644 index 000000000..67994d0cf --- /dev/null +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/common/CustomPayloadPacketMixin_NeoForge.java @@ -0,0 +1,27 @@ +package io.izzel.arclight.neoforge.mixin.core.network.protocol.common; + +import io.izzel.arclight.common.mod.util.DiscardedPayloadCodec; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import org.bukkit.Bukkit; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin({ServerboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket.class}) +public class CustomPayloadPacketMixin_NeoForge { + + @ModifyArg(method = "", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/network/protocol/common/custom/CustomPacketPayload;codec(Lnet/minecraft/network/protocol/common/custom/CustomPacketPayload$FallbackProvider;Ljava/util/List;Lnet/minecraft/network/ConnectionProtocol;Lnet/minecraft/network/protocol/PacketFlow;)Lnet/minecraft/network/codec/StreamCodec;")) + private static CustomPacketPayload.FallbackProvider arclight$fallbackBukkit(CustomPacketPayload.FallbackProvider arg) { + return resourceLocation -> { + if (Bukkit.getMessenger().getIncomingChannels().contains(resourceLocation.toString()) + || Bukkit.getMessenger().getOutgoingChannels().contains(resourceLocation.toString())) { + return DiscardedPayloadCodec.codec(resourceLocation, 32767); + } else { + return arg.create(resourceLocation); + } + }; + } +} diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_NeoForge.java new file mode 100644 index 000000000..0521ee69e --- /dev/null +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/network/protocol/login/ServerboundCustomQueryAnswerPacketMixin_NeoForge.java @@ -0,0 +1,37 @@ +package io.izzel.arclight.neoforge.mixin.core.network.protocol.login; + +import io.izzel.arclight.common.mod.util.ArclightCustomQueryAnswerPayload; +import io.netty.buffer.Unpooled; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; +import net.minecraft.network.protocol.login.custom.DiscardedQueryAnswerPayload; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ServerboundCustomQueryAnswerPacket.class) +public class ServerboundCustomQueryAnswerPacketMixin_NeoForge { + + @Shadow @Final private static int MAX_PAYLOAD_SIZE; + + @Inject(method = "readPayload", cancellable = true, at = @At("HEAD")) + private static void readResponse(int id, FriendlyByteBuf buf, CallbackInfoReturnable cir) { + boolean hasPayload = buf.readBoolean(); + if (!hasPayload) { + cir.setReturnValue(DiscardedQueryAnswerPayload.INSTANCE); + return; + } + int i = buf.readableBytes(); + if (i >= 0 && i < MAX_PAYLOAD_SIZE) { + var payload = Unpooled.buffer(i); + buf.readBytes(payload); + cir.setReturnValue(new ArclightCustomQueryAnswerPayload(payload)); + } else { + throw new IllegalArgumentException("Payload may not be larger than 1048576 bytes"); + } + } +} diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/server/management/ServerPlayerGameModeMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/server/management/ServerPlayerGameModeMixin_NeoForge.java index 617471cd3..4be99bada 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/server/management/ServerPlayerGameModeMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/server/management/ServerPlayerGameModeMixin_NeoForge.java @@ -13,12 +13,12 @@ @Mixin(ServerPlayerGameMode.class) public abstract class ServerPlayerGameModeMixin_NeoForge implements PlayerInteractionManagerBridge { - @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/common/CommonHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I")) + @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/common/CommonHooks;fireBlockBreak(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/neoforged/neoforge/event/level/BlockEvent$BreakEvent;")) public void arclight$beforePrimaryEventFired(BlockPos pos, CallbackInfoReturnable cir) { ArclightCaptures.captureNextBlockBreakEventAsPrimaryEvent(); } - @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE_ASSIGN", remap = false, target = "Lnet/neoforged/neoforge/common/CommonHooks;onBlockBreakEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;)I")) + @Inject(method = "destroyBlock", remap = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, remap = false, target = "Lnet/neoforged/neoforge/common/CommonHooks;fireBlockBreak(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/GameType;Lnet/minecraft/server/level/ServerPlayer;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/level/block/state/BlockState;)Lnet/neoforged/neoforge/event/level/BlockEvent$BreakEvent;")) public void arclight$handleSecondaryBlockBreakEvents(BlockPos pos, CallbackInfoReturnable cir) { ArclightCaptures.BlockBreakEventContext breakEventContext = ArclightCaptures.popSecondaryBlockBreakEvent(); while (breakEventContext != null) { diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/EntityMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/EntityMixin_NeoForge.java index 6b7f92b3c..e9dccac11 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/EntityMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/EntityMixin_NeoForge.java @@ -2,35 +2,25 @@ import io.izzel.arclight.common.bridge.core.entity.EntityBridge; import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import io.izzel.arclight.common.mod.util.ArclightCaptures; import io.izzel.tools.product.Product; import io.izzel.tools.product.Product4; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.FluidTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.portal.PortalInfo; import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.common.extensions.IEntityExtension; -import net.neoforged.neoforge.common.util.ITeleporter; import net.neoforged.neoforge.entity.PartEntity; import net.neoforged.neoforge.event.EventHooks; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import javax.annotation.Nullable; import java.util.Collection; @Mixin(Entity.class) @@ -39,7 +29,6 @@ public abstract class EntityMixin_NeoForge implements EntityBridge, IEntityExten // @formatter:off @Shadow public abstract Level level(); @Shadow public abstract boolean isRemoved(); - @Shadow @org.jetbrains.annotations.Nullable protected abstract PortalInfo findDimensionEntryPoint(ServerLevel serverLevel); @Shadow private float yRot; @Shadow private float xRot; @Shadow public abstract float getXRot(); @@ -57,7 +46,6 @@ public abstract class EntityMixin_NeoForge implements EntityBridge, IEntityExten @Shadow public abstract double getX(); @Shadow public abstract double getY(double d); @Shadow public abstract double getZ(); - @Shadow(remap = false) public abstract boolean canUpdate(); // @formatter:on @Override @@ -82,74 +70,6 @@ public abstract class EntityMixin_NeoForge implements EntityBridge, IEntityExten return drops; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - @Nullable - public Entity changeDimension(ServerLevel arg) { - return this.changeDimension(arg, arg.getPortalForcer()); - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - @Nullable - public Entity changeDimension(ServerLevel server, ITeleporter teleporter) { - if (!CommonHooks.onTravelToDimension((Entity) (Object) this, server.dimension())) - return null; - if (this.level() instanceof ServerLevel && !this.isRemoved()) { - this.level().getProfiler().push("changeDimension"); - if (server == null) { - return null; - } - this.level().getProfiler().push("reposition"); - var bukkitPos = bridge$getLastTpPos(); - PortalInfo portalinfo = bukkitPos == null ? teleporter.getPortalInfo((Entity) (Object) this, server, this::findDimensionEntryPoint) - : new PortalInfo(new Vec3(bukkitPos.x(), bukkitPos.y(), bukkitPos.z()), Vec3.ZERO, this.yRot, this.xRot); - if (portalinfo == null) { - return null; - } else { - ServerLevel world = ((PortalInfoBridge) portalinfo).bridge$getWorld() == null ? server : ((PortalInfoBridge) portalinfo).bridge$getWorld(); - if (world == this.level()) { - this.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, this.getXRot()); - this.setDeltaMovement(portalinfo.speed); - return (Entity) (Object) this; - } - this.unRide(); - Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerLevel) this.level(), world, this.getYRot(), spawnPortal -> { //Forge: Start vanilla logic - this.level().getProfiler().popPush("reloading"); - Entity entity = this.getType().create(world); - if (entity != null) { - entity.restoreFrom((Entity) (Object) this); - entity.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, entity.getXRot()); - entity.setDeltaMovement(portalinfo.speed); - if (this.bridge$isInWorld()) { - world.addDuringTeleport(entity); - if (((WorldBridge) world).bridge$getTypeKey() == LevelStem.END) { - ArclightCaptures.captureEndPortalEntity((Entity) (Object) this, spawnPortal); - ServerLevel.makeObsidianPlatform(world); - } - } - } - return entity; - }); //Forge: End vanilla logic - - this.removeAfterChangingDimensions(); - this.level().getProfiler().pop(); - ((ServerLevel) this.level()).resetEmptyTime(); - world.resetEmptyTime(); - this.level().getProfiler().pop(); - return transportedEntity; - } - } else { - return null; - } - } - @Override public boolean bridge$forge$isPartEntity() { return (Object) this instanceof PartEntity; @@ -170,9 +90,4 @@ public Entity changeDimension(ServerLevel server, ITeleporter teleporter) { var event = EventHooks.onEntityTeleportCommand((Entity) (Object) this, x, y, z); return Product.of(event.isCanceled(), event.getTargetX(), event.getTargetY(), event.getTargetZ()); } - - @Override - public boolean bridge$forge$canUpdate() { - return this.canUpdate(); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/LivingEntityMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/LivingEntityMixin_NeoForge.java index 08d903f22..a3bf8474a 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/LivingEntityMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/LivingEntityMixin_NeoForge.java @@ -2,9 +2,8 @@ import io.izzel.arclight.common.bridge.core.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.damagesource.DamageSource; import net.minecraft.world.effect.MobEffectInstance; @@ -13,12 +12,8 @@ import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.common.CommonHooks; -import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.EventHooks; -import net.neoforged.neoforge.event.entity.living.LivingChangeTargetEvent; -import net.neoforged.neoforge.event.entity.living.MobEffectEvent; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -37,7 +32,7 @@ public abstract class LivingEntityMixin_NeoForge extends EntityMixin_NeoForge im // @formatter:off @Shadow public abstract boolean isSleeping(); @Shadow public abstract Collection getActiveEffects(); - @Shadow protected abstract void dropExperience(); + @Shadow protected abstract void dropExperience(@Nullable Entity entity); // @formatter:on @Inject(method = "hurt", cancellable = true, at = @At("HEAD")) @@ -65,40 +60,13 @@ public abstract class LivingEntityMixin_NeoForge extends EntityMixin_NeoForge im } } - @Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience()V")) - private void arclight$dropLater(LivingEntity livingEntity) { + @Redirect(method = "dropAllDeathLoot", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;dropExperience(Lnet/minecraft/world/entity/Entity;)V")) + private void arclight$dropLater(LivingEntity instance, Entity entity) { } @Inject(method = "dropAllDeathLoot", at = @At("RETURN")) - private void arclight$dropLast(DamageSource damageSourceIn, CallbackInfo ci) { - this.dropExperience(); - } - - @Override - public boolean bridge$forge$mobEffectExpired(MobEffectInstance effect) { - return !NeoForge.EVENT_BUS.post(new MobEffectEvent.Expired((LivingEntity) (Object) this, effect)).isCanceled(); - } - - @Override - public boolean bridge$forge$mobEffectAdded(MobEffectInstance old, MobEffectInstance effect, Entity entity) { - NeoForge.EVENT_BUS.post(new MobEffectEvent.Added((LivingEntity) (Object) this, old, effect, entity)); - return false; - } - - @Override - public float bridge$forge$onLivingHurt(LivingEntity entity, DamageSource src, float amount) { - return CommonHooks.onLivingHurt(entity, src, amount); - } - - @Override - public Product3 bridge$forge$onShieldBlock(LivingEntity blocker, DamageSource source, float blocked) { - var event = CommonHooks.onShieldBlock(blocker, source, blocked); - return Product.of(event.isCanceled(), event.getBlockedDamage(), event.shieldTakesDamage()); - } - - @Override - public float bridge$forge$onLivingDamage(LivingEntity entity, DamageSource src, float amount) { - return CommonHooks.onLivingDamage(entity, src, amount); + private void arclight$dropLast(ServerLevel arg, DamageSource damageSource, CallbackInfo ci) { + this.dropExperience(damageSource.getEntity()); } @Override @@ -106,19 +74,6 @@ public abstract class LivingEntityMixin_NeoForge extends EntityMixin_NeoForge im return CommonHooks.onLivingUseTotem(entity, damageSource, totem, hand); } - @Nullable - @Override - public LivingEntity bridge$forge$onLivingChangeTarget(LivingEntity entity, LivingEntity originalTarget, LivingTargetType targetType) { - var event = CommonHooks.onLivingChangeTarget(entity, originalTarget, LivingChangeTargetEvent.LivingTargetType.valueOf(targetType.name())); - return event.isCanceled() ? null : event.getNewTarget(); - } - - @Override - public BlockPos bridge$forge$onEnderTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { - var event = EventHooks.onEnderTeleport(entity, targetX, targetY, targetZ); - return event.isCanceled() ? null : BlockPos.containing(event.getTarget()); - } - @Override public void bridge$forge$onLivingConvert(LivingEntity entity, LivingEntity outcome) { EventHooks.onLivingConvert(entity, outcome); @@ -129,11 +84,6 @@ public abstract class LivingEntityMixin_NeoForge extends EntityMixin_NeoForge im return CommonHooks.canEntityDestroy(level, pos, entity); } - @Override - public boolean bridge$forge$onEntityDestroyBlock(LivingEntity entity, BlockPos pos, BlockState state) { - return EventHooks.onEntityDestroyBlock(entity, pos, state); - } - @Override public void bridge$common$startCaptureDrops() { } @@ -153,6 +103,6 @@ public abstract class LivingEntityMixin_NeoForge extends EntityMixin_NeoForge im } @Override - public void bridge$common$finishCaptureAndFireEvent() { + public void bridge$common$finishCaptureAndFireEvent(DamageSource damageSource) { } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/animal/frog/TadpoleMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/animal/frog/TadpoleMixin_NeoForge.java index aca3669fe..a29ef44ca 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/animal/frog/TadpoleMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/animal/frog/TadpoleMixin_NeoForge.java @@ -17,17 +17,4 @@ @Mixin(Tadpole.class) public abstract class TadpoleMixin_NeoForge { - // @formatter:off - @Shadow protected abstract void setAge(int p_218711_); - // @formatter:on - - @Inject(method = "ageUp()V", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/animal/frog/Tadpole;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void arclight$transform(CallbackInfo ci, Level level, ServerLevel serverLevel, Frog frog) { - if (CraftEventFactory.callEntityTransformEvent((Tadpole) (Object) this, frog, org.bukkit.event.entity.EntityTransformEvent.TransformReason.METAMORPHOSIS).isCancelled()) { - this.setAge(0); // Sets the age to 0 for avoid a loop if the event is canceled - ci.cancel(); - } else { - ((ServerWorldBridge) serverLevel).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.METAMORPHOSIS); - } - } } \ No newline at end of file diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/item/ItemEntityMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/item/ItemEntityMixin_NeoForge.java index b44057ba7..6344c618d 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/item/ItemEntityMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/item/ItemEntityMixin_NeoForge.java @@ -2,26 +2,8 @@ import io.izzel.arclight.common.bridge.core.entity.item.ItemEntityBridge; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.event.EventHooks; import org.spongepowered.asm.mixin.Mixin; @Mixin(ItemEntity.class) public abstract class ItemEntityMixin_NeoForge implements ItemEntityBridge { - - @Override - public int bridge$forge$onItemPickup(Player player) { - return EventHooks.onItemPickup((ItemEntity) (Object) this, player); - } - - @Override - public void bridge$forge$firePlayerItemPickupEvent(Player player, ItemStack clone) { - EventHooks.firePlayerItemPickupEvent(player, (ItemEntity) (Object) this, clone); - } - - @Override - public boolean bridge$common$itemDespawnEvent() { - return true; - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/monster/ZombieMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/monster/ZombieMixin_NeoForge.java index b2e837558..ee078fd16 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/monster/ZombieMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/monster/ZombieMixin_NeoForge.java @@ -1,28 +1,9 @@ package io.izzel.arclight.neoforge.mixin.core.world.entity.monster; -import io.izzel.arclight.common.bridge.core.entity.MobEntityBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.monster.Zombie; -import net.neoforged.neoforge.event.entity.living.ZombieEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.event.entity.EntityTargetEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @Mixin(Zombie.class) public abstract class ZombieMixin_NeoForge { - @Inject(method = "hurt", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/monster/Zombie;setTarget(Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$spawnWithReasonForge(DamageSource source, float amount, CallbackInfoReturnable cir, ServerLevel world, LivingEntity livingEntity, int i, int j, int k, ZombieEvent.SummonAidEvent event, Zombie zombieEntity) { - ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); - if (livingEntity != null) { - ((MobEntityBridge) zombieEntity).bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); - } - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/PlayerMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/PlayerMixin_NeoForge.java index c9c25e349..a3bea8e31 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/PlayerMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/PlayerMixin_NeoForge.java @@ -2,21 +2,11 @@ import io.izzel.arclight.common.bridge.core.entity.player.PlayerEntityBridge; import io.izzel.arclight.neoforge.mixin.core.world.entity.LivingEntityMixin_NeoForge; -import io.izzel.tools.product.Product; -import io.izzel.tools.product.Product3; -import io.izzel.tools.product.Product6; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; -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.player.Abilities; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.phys.BlockHitResult; -import net.neoforged.bus.api.Event; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.common.extensions.IPlayerExtension; import org.spongepowered.asm.mixin.Mixin; @@ -50,32 +40,6 @@ public abstract class PlayerMixin_NeoForge extends LivingEntityMixin_NeoForge im } } - @Override - public Float bridge$forge$getCriticalHit(Player player, Entity target, boolean vanillaCritical, float damageModifier) { - var hit = CommonHooks.getCriticalHit(player, target, vanillaCritical, damageModifier); - return hit == null ? null : hit.getDamageModifier(); - } - - @Override - public double bridge$forge$getEntityReach() { - return this.getEntityReach(); - } - - @Override - public Product3 bridge$platform$onLeftClickBlock(BlockPos pos, Direction direction, ServerboundPlayerActionPacket.Action action) { - var event = CommonHooks.onLeftClickBlock((Player) (Object) this, pos, direction, action); - return Product.of(event.isCanceled(), event.getUseItem() == Event.Result.DENY, event.getUseBlock() == Event.Result.DENY); - } - - @Override - public Product6 bridge$platform$onRightClickBlock(InteractionHand hand, BlockPos pos, BlockHitResult hitResult) { - var event = CommonHooks.onRightClickBlock((Player) (Object) this, hand, pos, hitResult); - return Product.of(event.isCanceled(), - event.getUseItem() == Event.Result.ALLOW, event.getUseItem() == Event.Result.DENY, - event.getUseBlock() == Event.Result.ALLOW, event.getUseBlock() == Event.Result.DENY, - event.getCancellationResult()); - } - @Override public boolean bridge$platform$mayfly() { return this.mayFly(); diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/ServerPlayerMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/ServerPlayerMixin_NeoForge.java index 541ea3688..7a035bcd0 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/ServerPlayerMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/entity/player/ServerPlayerMixin_NeoForge.java @@ -1,59 +1,18 @@ package io.izzel.arclight.neoforge.mixin.core.world.entity.player; import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; -import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBridge; -import io.izzel.arclight.common.bridge.core.world.WorldBridge; -import io.izzel.arclight.common.bridge.core.world.level.block.PortalInfoBridge; -import io.izzel.arclight.common.mod.server.block.ChestBlockDoubleInventoryHacks; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.protocol.game.*; -import net.minecraft.resources.ResourceKey; +import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; 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.server.network.ServerGamePacketListenerImpl; -import net.minecraft.server.players.PlayerList; -import net.minecraft.world.Container; -import net.minecraft.world.MenuProvider; -import net.minecraft.world.damagesource.DamageSource; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.horse.AbstractHorse; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.portal.PortalInfo; -import net.minecraft.world.level.storage.LevelData; import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.common.CommonHooks; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.common.util.ITeleporter; -import net.neoforged.neoforge.event.EventHooks; -import net.neoforged.neoforge.event.entity.player.PlayerContainerEvent; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.craftbukkit.v.CraftWorld; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerTeleportEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; -import java.util.OptionalInt; -import java.util.function.Consumer; @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_NeoForge extends PlayerMixin_NeoForge implements ServerPlayerEntityBridge { @@ -67,7 +26,6 @@ public abstract class ServerPlayerMixin_NeoForge extends PlayerMixin_NeoForge im @Shadow public abstract CommonPlayerSpawnInfo createCommonSpawnInfo(ServerLevel arg); @Shadow @Final public MinecraftServer server; @Shadow @Nullable private Vec3 enteredNetherPosition; - @Shadow protected abstract void createEndPlatform(ServerLevel arg, BlockPos arg2); @Shadow public abstract void setServerLevel(ServerLevel arg); @Shadow public abstract void triggerDimensionChangeTriggers(ServerLevel arg); @Shadow @Final public ServerPlayerGameMode gameMode; @@ -75,160 +33,4 @@ public abstract class ServerPlayerMixin_NeoForge extends PlayerMixin_NeoForge im @Shadow private float lastSentHealth; @Shadow private int lastSentFood; // @formatter:on - - @Inject(method = "die", cancellable = true, at = @At("HEAD")) - private void arclight$onDeath(DamageSource source, CallbackInfo ci) { - if (CommonHooks.onLivingDeath((ServerPlayer) (Object) this, source)) { - ci.cancel(); - } - } - - @Inject(method = "openHorseInventory", at = @At("TAIL")) - private void arclight$openHorstContainer(AbstractHorse arg, Container arg2, CallbackInfo ci) { - NeoForge.EVENT_BUS.post(new PlayerContainerEvent.Open((ServerPlayer) (Object) this, this.containerMenu)); - } - - @Inject(method = "setRespawnPosition", cancellable = true, at = @At("HEAD")) - private void arclight$forgeRespawnPos(ResourceKey arg, BlockPos arg2, float f, boolean bl, boolean bl2, CallbackInfo ci) { - if (EventHooks.onPlayerSpawnSet((ServerPlayer) (Object) this, arg2 == null ? Level.OVERWORLD : arg, arg2, bl)) { - ci.cancel(); - } - } - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - @Nullable - public Entity changeDimension(ServerLevel server, ITeleporter teleporter) { - PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN); - if (this.isSleeping()) { - return (ServerPlayer) (Object) this; - } - if (!CommonHooks.onTravelToDimension((ServerPlayer) (Object) this, server.dimension())) return null; - - // this.invulnerableDimensionChange = true; - ServerLevel serverworld = this.serverLevel(); - ResourceKey registrykey = ((WorldBridge) serverworld).bridge$getTypeKey(); - if (registrykey == LevelStem.END && ((WorldBridge) server).bridge$getTypeKey() == LevelStem.OVERWORLD && teleporter.isVanilla()) { //Forge: Fix non-vanilla teleporters triggering end credits - this.isChangingDimension = true; - this.unRide(); - this.serverLevel().removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - if (!this.wonGame) { - this.wonGame = true; - this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.WIN_GAME, this.seenCredits ? 0.0F : 1.0F)); - this.seenCredits = true; - } - - return (ServerPlayer) (Object) this; - } else { - PortalInfo portalinfo = teleporter.getPortalInfo((ServerPlayer) (Object) this, server, this::findDimensionEntryPoint); - if (portalinfo != null) { - if (((PortalInfoBridge) portalinfo).bridge$getWorld() != null) { - server = ((PortalInfoBridge) portalinfo).bridge$getWorld(); - } - ServerLevel[] exitWorld = new ServerLevel[]{server}; - LevelData iworldinfo = server.getLevelData(); - this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(server), (byte) 3)); - this.connection.send(new ClientboundChangeDifficultyPacket(iworldinfo.getDifficulty(), iworldinfo.isDifficultyLocked())); - PlayerList playerlist = this.server.getPlayerList(); - playerlist.sendPlayerPermissionLevel((ServerPlayer) (Object) this); - this.serverLevel().removePlayerImmediately((ServerPlayer) (Object) this, Entity.RemovalReason.CHANGED_DIMENSION); - this.revive(); - Entity e = teleporter.placeEntity((ServerPlayer) (Object) this, serverworld, exitWorld[0], this.getYRot(), spawnPortal -> {//Forge: Start vanilla logic - serverworld.getProfiler().push("moving"); - if (exitWorld[0] != null) { - if (registrykey == LevelStem.OVERWORLD && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.NETHER) { - this.enteredNetherPosition = this.position(); - } else if (spawnPortal && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.END - && (((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo() == null || ((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo().getCanCreatePortal())) { - this.createEndPlatform(exitWorld[0], BlockPos.containing(portalinfo.pos)); - } - } - - Location enter = this.bridge$getBukkitEntity().getLocation(); - Location exit = (exitWorld[0] == null) ? null : new Location(exitWorld[0].bridge$getWorld(), portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, portalinfo.xRot); - PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.bridge$getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); - if (tpEvent.isCancelled() || tpEvent.getTo() == null) { - return null; - } - exit = tpEvent.getTo(); - - serverworld.getProfiler().pop(); - serverworld.getProfiler().push("placing"); - - this.isChangingDimension = true; - ServerLevel newWorld = ((CraftWorld) exit.getWorld()).getHandle(); - if (newWorld != exitWorld[0]) { - exitWorld[0] = newWorld; - LevelData newWorldInfo = exitWorld[0].getLevelData(); - this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(newWorld), (byte) 3)); - this.connection.send(new ClientboundChangeDifficultyPacket(newWorldInfo.getDifficulty(), newWorldInfo.isDifficultyLocked())); - } - - this.setServerLevel(exitWorld[0]); - exitWorld[0].addDuringPortalTeleport((ServerPlayer) (Object) this); - - ((ServerPlayNetHandlerBridge) this.connection).bridge$teleport(exit); - this.connection.resetPosition(); - - serverworld.getProfiler().pop(); - this.triggerDimensionChangeTriggers(exitWorld[0]); - return (ServerPlayer) (Object) this;//forge: this is part of the ITeleporter patch - });//Forge: End vanilla logic - if (e == null) { - serverworld.addDuringPortalTeleport((ServerPlayer) (Object) this); - return (ServerPlayer) (Object) this; - } else if (e != (Object) this) { - throw new IllegalArgumentException(String.format("Teleporter %s returned not the player entity but instead %s, expected PlayerEntity %s", teleporter, e, this)); - } - - this.gameMode.setLevel(exitWorld[0]); - this.connection.send(new ClientboundPlayerAbilitiesPacket(this.getAbilities())); - playerlist.sendLevelInfo((ServerPlayer) (Object) this, exitWorld[0]); - playerlist.sendAllPlayerInfo((ServerPlayer) (Object) this); - - for (MobEffectInstance effectinstance : this.getActiveEffects()) { - this.connection.send(new ClientboundUpdateMobEffectPacket(this.getId(), effectinstance)); - } - - if (teleporter.playTeleportSound((ServerPlayer) (Object) this, serverworld, exitWorld[0])) { - this.connection.send(new ClientboundLevelEventPacket(1032, BlockPos.ZERO, 0, false)); - } - this.lastSentExp = -1; - this.lastSentHealth = -1.0F; - this.lastSentFood = -1; - EventHooks.firePlayerChangedDimensionEvent((ServerPlayer) (Object) this, serverworld.dimension(), exitWorld[0].dimension()); - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.bridge$getBukkitEntity(), serverworld.bridge$getWorld()); - Bukkit.getPluginManager().callEvent(changeEvent); - } - - return (ServerPlayer) (Object) this; - } - } - - @Redirect(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;closeContainer()V")) - private void arclight$skipSwitch(ServerPlayer serverPlayer) { - } - - @Inject(method = "openMenu(Lnet/minecraft/world/MenuProvider;Ljava/util/function/Consumer;)Ljava/util/OptionalInt;", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/MenuProvider;createMenu(ILnet/minecraft/world/entity/player/Inventory;Lnet/minecraft/world/entity/player/Player;)Lnet/minecraft/world/inventory/AbstractContainerMenu;")) - private void arclight$invOpen(MenuProvider iTileInventory, Consumer extraDataWriter, CallbackInfoReturnable cir, AbstractContainerMenu container) { - if (container != null) { - ((ContainerBridge) container).bridge$setTitle(iTileInventory.getDisplayName()); - boolean cancelled = false; - ArclightCaptures.captureContainerOwner((ServerPlayer) (Object) this); - container = CraftEventFactory.callInventoryOpenEvent((ServerPlayer) (Object) this, container, cancelled); - ArclightCaptures.resetContainerOwner(); - if (container == null && !cancelled) { - if (iTileInventory instanceof Container) { - ((Container) iTileInventory).stopOpen((ServerPlayer) (Object) this); - } else if (ChestBlockDoubleInventoryHacks.isInstance(iTileInventory)) { - ChestBlockDoubleInventoryHacks.get(iTileInventory).stopOpen((ServerPlayer) (Object) this); - } - cir.setReturnValue(OptionalInt.empty()); - } - } - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/food/FoodDataMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/food/FoodDataMixin_NeoForge.java index 87eeb8e46..71641036c 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/food/FoodDataMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/food/FoodDataMixin_NeoForge.java @@ -1,21 +1,9 @@ package io.izzel.arclight.neoforge.mixin.core.world.food; -import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.food.FoodData; -import net.minecraft.world.food.FoodProperties; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import org.bukkit.craftbukkit.v.event.CraftEventFactory; -import org.bukkit.event.entity.FoodLevelChangeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -import javax.annotation.Nullable; @Mixin(FoodData.class) public abstract class FoodDataMixin_NeoForge implements FoodStatsBridge { @@ -24,28 +12,4 @@ public abstract class FoodDataMixin_NeoForge implements FoodStatsBridge { @Shadow public int foodLevel; @Shadow public abstract void eat(int i, float f); // @formatter:on - - @Redirect(method = "eat(Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)V", remap = false, - at = @At(value = "INVOKE", remap = true, target = "Lnet/minecraft/world/food/FoodData;eat(IF)V")) - private void arclight$foodLevelChangeForge(FoodData foodStats, int foodLevelIn, float foodSaturationModifier, Item maybeFood, ItemStack stack, @Nullable LivingEntity entity) { - var player = this.bridge$getEntityHuman() != null ? this.bridge$getEntityHuman() : (entity instanceof Player p ? p : null); - if (player == null) { - foodStats.eat(foodLevelIn, foodSaturationModifier); - return; - } else if (this.bridge$getEntityHuman() == null) { - this.bridge$setEntityHuman(player); - } - FoodProperties food = maybeFood.getFoodProperties(stack, entity); - int oldFoodLevel = this.foodLevel; - FoodLevelChangeEvent event = CraftEventFactory.callFoodLevelChangeEvent(player, food.getNutrition() + oldFoodLevel, stack); - if (!event.isCancelled()) { - this.eat(event.getFoodLevel() - oldFoodLevel, food.getSaturationModifier()); - } - ((ServerPlayerEntityBridge) player).bridge$getBukkitEntity().sendHealthUpdate(); - } - - @Override - public FoodProperties bridge$forge$getFoodProperties(ItemStack stack, LivingEntity entity) { - return stack.getFoodProperties(entity); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/inventory/AbstractContainerMenuMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/inventory/AbstractContainerMenuMixin_NeoForge.java index d6e0538ba..b0e6fab3d 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/inventory/AbstractContainerMenuMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/inventory/AbstractContainerMenuMixin_NeoForge.java @@ -1,20 +1,10 @@ package io.izzel.arclight.neoforge.mixin.core.world.inventory; import io.izzel.arclight.common.bridge.core.inventory.container.ContainerBridge; -import net.minecraft.world.entity.SlotAccess; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.inventory.ClickAction; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; -import net.neoforged.neoforge.common.CommonHooks; import org.spongepowered.asm.mixin.Mixin; @Mixin(AbstractContainerMenu.class) public abstract class AbstractContainerMenuMixin_NeoForge implements ContainerBridge { - @Override - public boolean bridge$forge$onItemStackedOn(ItemStack carriedItem, ItemStack stackedOnItem, Slot slot, ClickAction action, Player player, SlotAccess carriedSlotAccess) { - return CommonHooks.onItemStackedOn(carriedItem, stackedOnItem, slot, action, player, carriedSlotAccess); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemMixin_NeoForge.java index 4030da02a..467bc86b8 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemMixin_NeoForge.java @@ -5,7 +5,6 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.AbstractArrow; -import net.minecraft.world.item.ArrowItem; import net.minecraft.world.item.BowItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -28,11 +27,6 @@ public abstract class ItemMixin_NeoForge implements ItemBridge { return EventHooks.onArrowLoose(stack, level, player, charge, hasAmmo); } - @Override - public boolean bridge$forge$isInfinite(ArrowItem item, ItemStack stack, ItemStack bow, Player player) { - return item.isInfinite(stack, bow, player); - } - @Override public boolean bridge$forge$onChorusFruitTeleport(LivingEntity entity, double targetX, double targetY, double targetZ) { return EventHooks.onChorusFruitTeleport(entity, targetX, targetY, targetZ).isCanceled(); diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemStackMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemStackMixin_NeoForge.java index 227bcb14e..34cf88bb0 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemStackMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ItemStackMixin_NeoForge.java @@ -1,45 +1,65 @@ package io.izzel.arclight.neoforge.mixin.core.world.item; +import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.core.world.item.ItemStackBridge; +import io.izzel.arclight.mixin.Decorate; +import io.izzel.arclight.mixin.DecorationOps; +import io.izzel.arclight.mixin.Local; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.LevelReader; -import net.minecraft.world.phys.AABB; -import net.neoforged.neoforge.attachment.AttachmentHolder; -import net.neoforged.neoforge.attachment.AttachmentUtils; import net.neoforged.neoforge.common.extensions.IItemStackExtension; -import org.jetbrains.annotations.NotNull; -import org.spongepowered.asm.mixin.Final; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.craftbukkit.v.inventory.CraftItemStack; +import org.bukkit.event.player.PlayerItemDamageEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; -import java.util.Locale; +import java.util.function.Consumer; -@SuppressWarnings("MixinSuperClass") @Mixin(ItemStack.class) -public abstract class ItemStackMixin_NeoForge extends AttachmentHolder implements ItemStackBridge, IItemStackExtension { +public abstract class ItemStackMixin_NeoForge implements ItemStackBridge, IItemStackExtension { // @formatter:off - @Mutable @Shadow @Final @Deprecated @Nullable private Item item; + @Mutable @Shadow @Deprecated @Nullable private Item item; + @Shadow private int count; // @formatter:on - @Override - public CompoundTag bridge$getForgeCaps() { - return this.serializeAttachments(); + @Decorate(method = "hurtAndBreak(ILnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/enchantment/EnchantmentHelper;processDurabilityChange(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;I)I")) + private int arclight$itemDamage(ServerLevel serverLevel, ItemStack itemStack, int i, @Local(ordinal = 0) LivingEntity damager) throws Throwable { + int result = (int) DecorationOps.callsite().invoke(serverLevel, itemStack, i); + if (damager instanceof ServerPlayer) { + PlayerItemDamageEvent event = new PlayerItemDamageEvent(((ServerPlayerEntityBridge) damager).bridge$getBukkitEntity(), CraftItemStack.asCraftMirror((ItemStack) (Object) this), result); + event.getPlayer().getServer().getPluginManager().callEvent(event); + + if (result != event.getDamage() || event.isCancelled()) { + event.getPlayer().updateInventory(); + } + if (event.isCancelled()) { + return (int) DecorationOps.cancel().invoke(); + } + result = event.getDamage(); + } + return result; } - @Override - public void bridge$setForgeCaps(CompoundTag caps) { - if (caps != null) { - this.deserializeAttachments(caps); + @Inject(method = "hurtAndBreak(ILnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Consumer;)V", at = @At(value = "INVOKE", target = "Ljava/util/function/Consumer;accept(Ljava/lang/Object;)V")) + private void arclight$itemBreak(int amount, ServerLevel level, @org.jetbrains.annotations.Nullable LivingEntity livingEntity, Consumer onBroken, CallbackInfo ci) { + if (this.count == 1 && livingEntity instanceof ServerPlayer serverPlayer) { + CraftEventFactory.callPlayerItemBreakEvent(serverPlayer, (ItemStack) (Object) this); } } @@ -48,26 +68,6 @@ public void setItem(Item item) { this.item = item; } - @Override - public boolean bridge$forge$hasCraftingRemainingItem() { - return this.hasCraftingRemainingItem(); - } - - @Override - public ItemStack bridge$forge$getCraftingRemainingItem() { - return this.getCraftingRemainingItem(); - } - - @Override - public boolean bridge$forge$canPerformAction(ToolAction action) { - return this.canPerformAction(net.neoforged.neoforge.common.ToolAction.get(action.name().toLowerCase(Locale.ROOT))); - } - - @Override - public AABB bridge$forge$getSweepHitBox(@NotNull Player player, @NotNull Entity target) { - return this.getSweepHitBox(player, target); - } - @Override public InteractionResult bridge$forge$onItemUseFirst(UseOnContext context) { return onItemUseFirst(context); @@ -77,9 +77,4 @@ public void setItem(Item item) { public boolean bridge$forge$doesSneakBypassUse(LevelReader level, BlockPos pos, Player player) { return doesSneakBypassUse(level, pos, player); } - - @Override - public void bridge$platform$copyAdditionalFrom(ItemStack from) { - AttachmentUtils.copyStackAttachments(from, (ItemStack) (Object) this); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ShearsItemMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ShearsItemMixin_NeoForge.java index 085dc3073..43c14fd97 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ShearsItemMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/ShearsItemMixin_NeoForge.java @@ -15,7 +15,7 @@ @Mixin(ShearsItem.class) public abstract class ShearsItemMixin_NeoForge { - @Inject(method = "interactLivingEntity", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/common/IShearable;isShearable(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z")) + @Inject(method = "interactLivingEntity", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/common/IShearable;isShearable(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;)Z")) private void arclight$onShear(ItemStack stack, Player playerIn, LivingEntity entity, InteractionHand hand, CallbackInfoReturnable cir) { if (!CraftEventFactory.handlePlayerShearEntityEvent(playerIn, entity, stack, hand)) { cir.setReturnValue(InteractionResult.PASS); diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_NeoForge.java index 2ce909e60..d06cd7b5a 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/item/crafting/RecipeManagerMixin_NeoForge.java @@ -1,35 +1,15 @@ package io.izzel.arclight.neoforge.mixin.core.world.item.crafting; import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.mojang.serialization.DynamicOps; import io.izzel.arclight.common.bridge.core.world.item.crafting.RecipeManagerBridge; -import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; -import net.neoforged.neoforge.common.conditions.ConditionalOps; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -import java.util.Optional; @Mixin(RecipeManager.class) public abstract class RecipeManagerMixin_NeoForge extends SimpleJsonResourceReloadListener implements RecipeManagerBridge { - // @formatter:off - @Shadow public static Optional> fromJson(ResourceLocation arg, JsonObject jsonObject, DynamicOps jsonElementOps) { return Optional.empty(); } - // @formatter:on - public RecipeManagerMixin_NeoForge(Gson gson, String string) { super(gson, string); } - - @Override - public RecipeHolder bridge$platform$loadRecipe(ResourceLocation key, JsonElement element) { - ConditionalOps ops = this.makeConditionalOps(); - return fromJson(key, GsonHelper.convertToJsonObject(element, "top element"), ops).orElse(null); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/BaseSpawnerMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/BaseSpawnerMixin_NeoForge.java index 95c5dec0a..cca4f5fcd 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/BaseSpawnerMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/BaseSpawnerMixin_NeoForge.java @@ -19,21 +19,4 @@ @Mixin(BaseSpawner.class) public abstract class BaseSpawnerMixin_NeoForge implements BaseSpawnerBridge { - @Override - public boolean bridge$forge$checkSpawnRules(Mob mob, ServerLevelAccessor level, MobSpawnType spawnType, SpawnData spawnData, boolean original) { - var event = new MobSpawnEvent.PositionCheck(mob, level, spawnType, null); - NeoForge.EVENT_BUS.post(event); - if (event.getResult() == Event.Result.DEFAULT) { - return original; - } - return event.getResult() == Event.Result.ALLOW; - } - - @Override - public void bridge$forge$finalizeSpawnerSpawn(Mob mob, ServerLevelAccessor level, DifficultyInstance difficulty, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag spawnTag) { - var event = EventHooks.onFinalizeSpawnSpawner(mob, level, difficulty, spawnData, spawnTag, (BaseSpawner) (Object) this); - if (event != null) { - mob.finalizeSpawn(level, event.getDifficulty(), event.getSpawnType(), event.getSpawnData(), event.getSpawnTag()); - } - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/LevelMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/LevelMixin_NeoForge.java index cf218330c..b98b2c347 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/LevelMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/LevelMixin_NeoForge.java @@ -12,7 +12,6 @@ import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.chunk.LevelChunk; -import net.neoforged.neoforge.common.brewing.BrewingRecipeRegistry; import net.neoforged.neoforge.common.util.BlockSnapshot; import net.neoforged.neoforge.event.EventHooks; import org.bukkit.Bukkit; @@ -69,12 +68,7 @@ public abstract class LevelMixin_NeoForge implements WorldBridge { @Override public boolean bridge$forge$mobGriefing(Entity entity) { - return EventHooks.getMobGriefingEvent((Level) (Object) this, entity); - } - - @Override - public ItemStack bridge$forge$potionBrewMix(ItemStack a, ItemStack b) { - return BrewingRecipeRegistry.getOutput(a, b); + return EventHooks.canEntityGrief((Level) (Object) this, entity); } @Override diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/BlockMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/BlockMixin_NeoForge.java index fff721484..5ba48ea5a 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/BlockMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/BlockMixin_NeoForge.java @@ -3,61 +3,30 @@ import io.izzel.arclight.common.bridge.core.world.level.block.BlockBridge; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.PoweredRailBlock; -import net.minecraft.world.level.block.entity.DispenserBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.common.extensions.IBlockExtension; -import net.neoforged.neoforge.items.VanillaInventoryCodeHooks; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @Mixin(Block.class) public abstract class BlockMixin_NeoForge implements BlockBridge, IBlockExtension { - @Override - public int bridge$getExpDrop(BlockState blockState, ServerLevel world, BlockPos blockPos, ItemStack itemStack) { - int silkTouch = itemStack.getEnchantmentLevel(Enchantments.SILK_TOUCH); - int fortune = itemStack.getEnchantmentLevel(Enchantments.BLOCK_FORTUNE); - return this.getExpDrop(blockState, world, world.random, blockPos, fortune, silkTouch); - } - @Override public boolean bridge$forge$onCropsGrowPre(Level level, BlockPos pos, BlockState state, boolean def) { - return CommonHooks.onCropsGrowPre(level, pos, state, def); + return CommonHooks.canCropGrow(level, pos, state, def); } @Override public void bridge$forge$onCropsGrowPost(Level level, BlockPos pos, BlockState state) { - CommonHooks.onCropsGrowPost(level, pos, state); - } - - @Override - public boolean bridge$forge$dropperInsertHook(Level level, BlockPos pos, DispenserBlockEntity dropper, int slot, @NotNull ItemStack stack) { - return VanillaInventoryCodeHooks.dropperInsertHook(level, pos, dropper, slot, stack); + CommonHooks.fireCropGrowPost(level, pos, state); } @Override public void bridge$forge$onCaughtFire(BlockState state, Level level, BlockPos pos, @Nullable Direction direction, @Nullable LivingEntity igniter) { this.onCaughtFire(state, level, pos, direction, igniter); } - - @Override - public boolean bridge$forge$isActivatorRail(BlockState state) { - return state.getBlock() instanceof PoweredRailBlock block && block.isActivatorRail(); - } - - @Override - public boolean bridge$forge$canEntityDestroy(BlockState state, BlockGetter level, BlockPos pos, Entity entity) { - return this.canEntityDestroy(state, level, pos, entity); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/CropBlockMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/CropBlockMixin_NeoForge.java index 017f9d67f..f0cfb4bd7 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/CropBlockMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/CropBlockMixin_NeoForge.java @@ -14,9 +14,9 @@ @Mixin(CropBlock.class) public abstract class CropBlockMixin_NeoForge { - @Redirect(method = "entityInside", at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/event/EventHooks;getMobGriefingEvent(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;)Z")) + @Redirect(method = "entityInside", at = @At(value = "INVOKE", remap = false, target = "Lnet/neoforged/neoforge/event/EventHooks;canEntityGrief(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;)Z")) public boolean arclight$entityChangeBlock(Level world, Entity entity, BlockState state, Level worldIn, BlockPos pos) { - boolean result = EventHooks.getMobGriefingEvent(world, entity); + boolean result = EventHooks.canEntityGrief(world, entity); return !CraftEventFactory.callEntityChangeBlockEvent(entity, pos, state, result); } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/TntBlockMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/TntBlockMixin_NeoForge.java index e7d2ab15b..189670fab 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/TntBlockMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/TntBlockMixin_NeoForge.java @@ -7,6 +7,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.TntBlock; @@ -32,8 +33,8 @@ public abstract class TntBlockMixin_NeoForge extends BlockMixin_NeoForge { } } - @Inject(method = "use", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) - private void arclight$player(BlockState p_57450_, Level level, BlockPos pos, Player player, InteractionHand p_57454_, BlockHitResult p_57455_, CallbackInfoReturnable cir) { + @Inject(method = "useItemOn", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$player(ItemStack arg, BlockState p_57450_, Level level, BlockPos pos, Player player, InteractionHand p_57454_, BlockHitResult p_57455_, CallbackInfoReturnable cir) { if (!CraftEventFactory.callTNTPrimeEvent(level, pos, TNTPrimeEvent.PrimeCause.PLAYER, player, null)) { cir.setReturnValue(InteractionResult.CONSUME); } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_NeoForge.java index 8c35a24ab..229df6390 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_NeoForge.java @@ -1,76 +1,9 @@ package io.izzel.arclight.neoforge.mixin.core.world.level.block.entity; -import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v.block.CraftBlock; -import org.bukkit.craftbukkit.v.inventory.CraftItemStack; -import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; -import org.spongepowered.asm.mixin.Shadow; - -import javax.annotation.Nullable; @Mixin(AbstractFurnaceBlockEntity.class) public abstract class AbstractFurnaceBlockEntityMixin_NeoForge { - // @formatter:off - @Shadow protected abstract boolean canBurn(RegistryAccess p_266924_, @org.jetbrains.annotations.Nullable RecipeHolder p_155006_, NonNullList p_155007_, int p_155008_); - // @formatter:on - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - private boolean burn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, NonNullList items, int i) { - if (recipe != null && this.canBurn(registryAccess, recipe, items, i)) { - ItemStack itemstack = items.get(0); - ItemStack itemstack1 = recipe.value().getResultItem(registryAccess); - ItemStack itemstack2 = items.get(2); - - if (ArclightCaptures.getTickingBlockEntity() != null) { - var blockEntity = ArclightCaptures.getTickingBlockEntity(); - CraftItemStack source = CraftItemStack.asCraftMirror(itemstack); - org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1); - - FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(blockEntity.getLevel(), blockEntity.getBlockPos()), source, result); - Bukkit.getPluginManager().callEvent(furnaceSmeltEvent); - - if (furnaceSmeltEvent.isCancelled()) { - return false; - } - - result = furnaceSmeltEvent.getResult(); - itemstack1 = CraftItemStack.asNMSCopy(result); - } - - if (!itemstack1.isEmpty()) { - if (itemstack2.isEmpty()) { - items.set(2, itemstack1.copy()); - } else if (ItemStack.isSameItemSameTags(itemstack2, itemstack1)) { - itemstack2.grow(itemstack1.getCount()); - } else { - return false; - } - } - - if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) { - items.set(1, new ItemStack(Items.WATER_BUCKET)); - } - - itemstack.shrink(1); - return true; - } else { - return false; - } - } - } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_NeoForge.java index 81f947a30..7150a4c35 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/block/entity/BrewingStandBlockEntityMixin_NeoForge.java @@ -14,10 +14,4 @@ @Mixin(BrewingStandBlockEntity.class) public class BrewingStandBlockEntityMixin_NeoForge { - @Inject(method = "doBrew", cancellable = true, at = @At("HEAD")) - private static void arclight$forgeBrew(Level arg, BlockPos arg2, NonNullList stacks, CallbackInfo ci) { - if (EventHooks.onPotionAttemptBrew(stacks)) { - ci.cancel(); - } - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_NeoForge.java index 38e12b729..f9a21377e 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/levelgen/structure/templatesystem/StructureTemplateMixin_NeoForge.java @@ -17,18 +17,4 @@ @Mixin(StructureTemplate.class) public abstract class StructureTemplateMixin_NeoForge implements StructureTemplateBridge { - // @formatter:off - @Shadow(remap = false) public static List processBlockInfos(ServerLevelAccessor p_278297_, BlockPos p_74519_, BlockPos p_74520_, StructurePlaceSettings p_74521_, List p_74522_, @Nullable StructureTemplate template) { return null; } - @Shadow(remap = false) protected abstract void addEntitiesToWorld(ServerLevelAccessor par1, BlockPos par2, StructurePlaceSettings par3); - // @formatter:on - - @Override - public List bridge$platform$processBlockInfos(ServerLevelAccessor arg, BlockPos arg2, BlockPos arg3, StructurePlaceSettings arg4, List list2, @Nullable StructureTemplate template) { - return processBlockInfos(arg, arg2, arg3, arg4, list2, template); - } - - @Override - public void bridge$platform$placeEntities(ServerLevelAccessor serverLevelAccessor, BlockPos blockPos, Mirror mirror, Rotation rotation, BlockPos blockPos2, @Nullable BoundingBox boundingBox, boolean bl, StructurePlaceSettings placementIn) { - this.addEntitiesToWorld(serverLevelAccessor, blockPos, placementIn); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/storage/loot/LootContextMixin_NeoForge.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/storage/loot/LootContextMixin_NeoForge.java index 514564a2a..11847aeef 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/storage/loot/LootContextMixin_NeoForge.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/core/world/level/storage/loot/LootContextMixin_NeoForge.java @@ -1,20 +1,10 @@ package io.izzel.arclight.neoforge.mixin.core.world.level.storage.loot; import io.izzel.arclight.common.bridge.core.world.storage.loot.LootContextBridge; -import net.minecraft.world.entity.Entity; import net.minecraft.world.level.storage.loot.LootContext; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; @Mixin(LootContext.class) public abstract class LootContextMixin_NeoForge implements LootContextBridge { - // @formatter:off - @Shadow(remap = false) public abstract int getLootingModifier(); - // @formatter:on - - @Override - public int bridge$forge$getLootingModifier(Entity entity) { - return this.getLootingModifier(); - } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/forge/PacketDistributorMixin.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/forge/PacketDistributorMixin.java index 6b2e8f3b1..3b22c8dbb 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/forge/PacketDistributorMixin.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mixin/forge/PacketDistributorMixin.java @@ -1,26 +1,20 @@ package io.izzel.arclight.neoforge.mixin.forge; -import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.PacketDistributor; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Overwrite; - -import java.util.function.Consumer; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(PacketDistributor.class) public abstract class PacketDistributorMixin { - /** - * @author IzzelAliz - * @reason - */ - @Overwrite(remap = false) - private Consumer> playerConsumer(ServerPlayer entity) { - return p -> { - if (entity.connection != null && entity.connection.isAcceptingMessages()) { - entity.connection.send(p); - } - }; + @Inject(method = "sendToPlayer", cancellable = true, at = @At("HEAD")) + private static void arclight$returnIfNotConnected(ServerPlayer player, CustomPacketPayload payload, CustomPacketPayload[] payloads, CallbackInfo ci) { + if (player.connection == null) { + ci.cancel(); + } } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/BlockBreakEventDispatcher.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/BlockBreakEventDispatcher.java index e379d23e7..98d3af4f8 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/BlockBreakEventDispatcher.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/BlockBreakEventDispatcher.java @@ -11,6 +11,7 @@ public class BlockBreakEventDispatcher { + // todo @SubscribeEvent(receiveCanceled = true) public void onBreakBlock(BlockEvent.BreakEvent event) { if (DistValidate.isValid(event.getLevel())) { @@ -18,10 +19,10 @@ public void onBreakBlock(BlockEvent.BreakEvent event) { BlockBreakEvent breakEvent = new BlockBreakEvent(craftBlock, ((ServerPlayerEntityBridge) event.getPlayer()).bridge$getBukkitEntity()); ArclightCaptures.captureBlockBreakPlayer(breakEvent); breakEvent.setCancelled(event.isCanceled()); - breakEvent.setExpToDrop(event.getExpToDrop()); + //breakEvent.setExpToDrop(event.getExpToDrop()); Bukkit.getPluginManager().callEvent(breakEvent); event.setCanceled(breakEvent.isCancelled()); - event.setExpToDrop(breakEvent.getExpToDrop()); + //event.setExpToDrop(breakEvent.getExpToDrop()); } } } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/EntityEventDispatcher.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/EntityEventDispatcher.java index d9cebac28..97779fb54 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/EntityEventDispatcher.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/event/EntityEventDispatcher.java @@ -38,7 +38,7 @@ public void onLivingDeath(LivingDropsEvent event) { itemEntity.setDefaultPickUpDelay(); return itemEntity; }); - ArclightEventFactory.callEntityDeathEvent(livingEntity, itemStackList); + ArclightEventFactory.callEntityDeathEvent(livingEntity, itemStackList, event.getSource()); if (drops.isEmpty()) { event.setCanceled(true); } diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/permission/ArclightPermissionHandler.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/permission/ArclightPermissionHandler.java index 065c96a82..80ddae5d4 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/permission/ArclightPermissionHandler.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/permission/ArclightPermissionHandler.java @@ -24,7 +24,7 @@ public ArclightPermissionHandler(IPermissionHandler delegate) { @Override public ResourceLocation getIdentifier() { - return new ResourceLocation("arclight", "permission"); + return ResourceLocation.parse("arclight:permission"); } @Override diff --git a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/util/ArclightBlockSnapshot.java b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/util/ArclightBlockSnapshot.java index 3ad5974b0..c6ef5aeb6 100644 --- a/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/util/ArclightBlockSnapshot.java +++ b/arclight-neoforge/src/main/java/io/izzel/arclight/neoforge/mod/util/ArclightBlockSnapshot.java @@ -10,7 +10,7 @@ public class ArclightBlockSnapshot extends CraftBlock { public ArclightBlockSnapshot(BlockSnapshot blockSnapshot, boolean current) { super(blockSnapshot.getLevel(), blockSnapshot.getPos()); - this.blockState = current ? blockSnapshot.getCurrentBlock() : blockSnapshot.getReplacedBlock(); + this.blockState = current ? blockSnapshot.getCurrentState() : blockSnapshot.getState(); } @Override diff --git a/arclight-neoforge/src/main/resources/META-INF/mods.toml b/arclight-neoforge/src/main/resources/META-INF/neoforge.mods.toml similarity index 100% rename from arclight-neoforge/src/main/resources/META-INF/mods.toml rename to arclight-neoforge/src/main/resources/META-INF/neoforge.mods.toml diff --git a/arclight-neoforge/src/main/resources/mixins.arclight.neoforge.json b/arclight-neoforge/src/main/resources/mixins.arclight.neoforge.json index 02c5c1c3f..36f30020d 100644 --- a/arclight-neoforge/src/main/resources/mixins.arclight.neoforge.json +++ b/arclight-neoforge/src/main/resources/mixins.arclight.neoforge.json @@ -22,9 +22,12 @@ "core.command.CommandsMixin_NeoForge", "core.fluid.LavaFluidMixin_NeoForge", "core.network.ServerCommonPacketListenerImplMixin_NeoForge", + "core.network.ServerConfigurationPacketListenerImplMixin_NeoForge", "core.network.ServerLoginNetHandlerMixin_NeoForge", "core.network.ServerPlayNetHandlerMixin_NeoForge", "core.network.ServerStatusNetHandlerMixin_NeoForge", + "core.network.protocol.common.CustomPayloadPacketMixin_NeoForge", + "core.network.protocol.login.ServerboundCustomQueryAnswerPacketMixin_NeoForge", "core.network.protocol.status.ServerStatusMixin", "core.server.MinecraftServerMixin_NeoForge", "core.server.dedicated.DedicatedServerMixin_NeoForge", diff --git a/bootstrap/build.gradle b/bootstrap/build.gradle index e01e561c9..d28a03472 100644 --- a/bootstrap/build.gradle +++ b/bootstrap/build.gradle @@ -26,8 +26,6 @@ sourceSets { fabric {} } -java.toolchain.languageVersion = JavaLanguageVersion.of(17) - configurations { installer installerFabric @@ -46,7 +44,7 @@ repositories { } maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } - maven { url = 'https://files.minecraftforge.net/maven/' } + maven { url = 'https://maven.minecraftforge.net/' } maven { url = 'https://maven.neoforged.net/releases/' } maven { url = 'https://maven.izzel.io/releases' } maven { url = 'https://jitpack.io/' } @@ -99,8 +97,7 @@ dependencies { forgeImplementation 'net.minecraftforge:bootstrap:2.1.0' forgeImplementation 'net.minecraftforge:bootstrap-api:2.1.0' - neoforgeImplementation 'net.neoforged.fancymodloader:spi:2.0.7' - neoforgeImplementation 'net.neoforged.fancymodloader:loader:2.0.7' + neoforgeImplementation 'net.neoforged.fancymodloader:loader:4.0.1' neoforgeImplementation 'cpw.mods:securejarhandler:2.1.24' fabricImplementation "net.fabricmc:fabric-loader:$fabricLoaderVersion" @@ -162,7 +159,7 @@ tasks.register('forgeJar', Jar) { from sourceSets.main.output from sourceSets.forge.output duplicatesStrategy = DuplicatesStrategy.EXCLUDE - dependsOn(project(':arclight-forge').tasks.reobfJar) + dependsOn(project(':arclight-forge').tasks.shadowJar) } tasks.register('neoforgeJar', Jar) { @@ -253,13 +250,13 @@ project.sourceSets.fabric.output.dir file("build/fabric_async_catcher"), builtBy } compileJava { - sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = targetCompatibility = JavaVersion.VERSION_21 options.compilerArgs << '-XDignore.symbol.file' << '-XDenableSunApiLintControl' options.encoding = 'UTF-8' } compileApplaunchJava { - sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_7 + sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8 } tasks.register('runProdServer', JavaExec) { @@ -277,7 +274,7 @@ tasks.register('runProdServer', JavaExec) { args 'nogui' standardInput System.in javaLauncher.convention(javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) }) dependsOn project.tasks.forgeJar } @@ -290,12 +287,14 @@ tasks.register('runProdNeoforge', JavaExec) { systemProperties 'mixin.dumpTargetOnFailure': 'true' systemProperties 'arclight.alwaysExtract': 'true' systemProperties 'arclight.remapper.dump': './.mixin.out/plugin_classes' + systemProperties 'sun.stdout.encoding': 'UTF-8' + systemProperties 'sun.stderr.encoding': 'UTF-8' workingDir System.env.ARCLIGHT_PROD_DIR ?: file('run_prod/neoforge') maxHeapSize '4G' args 'nogui' standardInput System.in javaLauncher.convention(javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) }) dependsOn project.tasks.neoforgeJar } @@ -308,12 +307,14 @@ tasks.register('runProdFabric', JavaExec) { systemProperties 'mixin.dumpTargetOnFailure': 'true' systemProperties 'arclight.alwaysExtract': 'true' systemProperties 'arclight.remapper.dump': './.mixin.out/plugin_classes' + systemProperties 'sun.stdout.encoding': 'UTF-8' + systemProperties 'sun.stderr.encoding': 'UTF-8' workingDir System.env.ARCLIGHT_PROD_DIR ?: file('run_prod/fabric') maxHeapSize '4G' args 'nogui' standardInput System.in javaLauncher.convention(javaToolchains.launcherFor { - languageVersion = JavaLanguageVersion.of(17) + languageVersion = JavaLanguageVersion.of(21) }) dependsOn project.tasks.fabricJar } diff --git a/bootstrap/src/applaunch/java/io/izzel/arclight/server/Launcher.java b/bootstrap/src/applaunch/java/io/izzel/arclight/server/Launcher.java index 4a08bd204..1a883c6b0 100644 --- a/bootstrap/src/applaunch/java/io/izzel/arclight/server/Launcher.java +++ b/bootstrap/src/applaunch/java/io/izzel/arclight/server/Launcher.java @@ -8,8 +8,8 @@ public class Launcher { - private static final int MIN_CLASS_VERSION = 61; - private static final int MIN_JAVA_VERSION = 17; + private static final int MIN_CLASS_VERSION = 65; + private static final int MIN_JAVA_VERSION = 21; private static final int MAX_CLASS_VERSION = 66; private static final int MAX_JAVA_VERSION = 22; diff --git a/bootstrap/src/main/java/io/izzel/arclight/boot/AbstractBootstrap.java b/bootstrap/src/main/java/io/izzel/arclight/boot/AbstractBootstrap.java index 5904f8b26..15ac95e1a 100644 --- a/bootstrap/src/main/java/io/izzel/arclight/boot/AbstractBootstrap.java +++ b/bootstrap/src/main/java/io/izzel/arclight/boot/AbstractBootstrap.java @@ -94,7 +94,7 @@ default void setupMod(ArclightPlatform platform) throws Exception { } default void setupMod(ArclightPlatform platform, boolean extract) throws Exception { - ArclightVersion.setVersion(ArclightVersion.WHISPER); + ArclightVersion.setVersion(ArclightVersion.FEUDAL_KINGS); ArclightPlatform.setPlatform(platform); try (InputStream stream = getClass().getResourceAsStream("/META-INF/MANIFEST.MF")) { Manifest manifest = new Manifest(stream); diff --git a/bootstrap/src/main/java/io/izzel/arclight/boot/asm/AsyncCatcher.java b/bootstrap/src/main/java/io/izzel/arclight/boot/asm/AsyncCatcher.java index 08b5d6c83..477f52017 100644 --- a/bootstrap/src/main/java/io/izzel/arclight/boot/asm/AsyncCatcher.java +++ b/bootstrap/src/main/java/io/izzel/arclight/boot/asm/AsyncCatcher.java @@ -13,6 +13,7 @@ import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldInsnNode; +import org.objectweb.asm.tree.FrameNode; import org.objectweb.asm.tree.InsnList; import org.objectweb.asm.tree.InsnNode; import org.objectweb.asm.tree.InvokeDynamicInsnNode; @@ -62,7 +63,8 @@ public AsyncCatcher() { Gson gson = new GsonBuilder().disableHtmlEscaping().create(); this.reasons = gson.fromJson( new InputStreamReader(AsyncCatcher.class.getResourceAsStream("/async_catcher.json")), - new TypeToken>>() {}.getType() + new TypeToken>>() { + }.getType() ); this.defaultOp = ArclightConfig.spec().getAsyncCatcher().getDefaultOp(); this.dump = ArclightConfig.spec().getAsyncCatcher().isDump(); @@ -121,6 +123,7 @@ private void injectCheck(ClassNode node, MethodNode methodNode, String reason) { insnList.add(labelNode1); insnList.add(new InsnNode(Opcodes.POP)); insnList.add(labelNode); + insnList.add(new FrameNode(Opcodes.F_SAME, 0, null, 0, null)); methodNode.instructions.insert(insnList); } diff --git a/bootstrap/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java b/bootstrap/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java index c0a8eb38f..15af212d0 100644 --- a/bootstrap/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java +++ b/bootstrap/src/main/java/io/izzel/arclight/boot/asm/EnumDefinalizer.java @@ -31,8 +31,7 @@ public boolean processClass(ClassNode node) { if (ENUM.contains(node.name)) { var find = false; for (FieldNode field : node.fields) { - if (Modifier.isStatic(field.access) && Modifier.isFinal(field.access) - && field.name.equals("ENUM$VALUES")) { + if (Modifier.isStatic(field.access) && Modifier.isFinal(field.access) && (field.name.equals("ENUM$VALUES") || field.name.equals("$VALUES"))) { field.access &= ~Opcodes.ACC_FINAL; Implementer.LOGGER.debug("Definalize enum class {} values field {}", node.name, field.name); if (find) { diff --git a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarAdaptor.java b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarAdaptor.java deleted file mode 100644 index 97e7e0e3f..000000000 --- a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarAdaptor.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.izzel.arclight.boot.neoforge.mod; - -import net.neoforged.fml.loading.FMLLoader; -import net.neoforged.fml.loading.moddiscovery.JarInJarDependencyLocator; -import net.neoforged.fml.loading.moddiscovery.ModDiscoverer; -import net.neoforged.neoforgespi.locating.IDependencyLocator; -import net.neoforged.neoforgespi.locating.IModFile; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; - -public class ArclightJarInJarAdaptor implements IDependencyLocator { - - private static final Logger LOGGER = LoggerFactory.getLogger("ArclightJiJ"); - - private final IDependencyLocator delegate; - - public ArclightJarInJarAdaptor(IDependencyLocator delegate) { - this.delegate = delegate; - } - - @Override - public List scanMods(Iterable loadedMods) { - return delegate.scanMods(loadedMods).stream().filter(it -> { - var optional = getClass().getModule().getLayer().findModule(it.getModFileInfo().moduleName()); - optional.ifPresent(module -> LOGGER.info("Skip jij dependency {}@{} because Arclight has {}", - it.getModFileInfo().moduleName(), it.getModFileInfo().versionString(), module.getDescriptor().toNameAndVersion())); - return optional.isEmpty(); - }).toList(); - } - - @Override - public String name() { - return "arclight_jij"; - } - - @Override - public void scanFile(IModFile modFile, Consumer pathConsumer) { - delegate.scanFile(modFile, pathConsumer); - } - - @Override - public void initArguments(Map arguments) { - delegate.initArguments(arguments); - } - - @Override - public boolean isValid(IModFile modFile) { - return delegate.isValid(modFile); - } - - @SuppressWarnings("unchecked") - static void inject() { - try { - var field = FMLLoader.class.getDeclaredField("modDiscoverer"); - field.setAccessible(true); - var discoverer = (ModDiscoverer) field.get(null); - var locatorField = ModDiscoverer.class.getDeclaredField("dependencyLocatorList"); - locatorField.setAccessible(true); - var locatorList = (List) locatorField.get(discoverer); - var newList = locatorList.stream().map(it -> { - if (it instanceof JarInJarDependencyLocator) { - return new ArclightJarInJarAdaptor(it); - } else { - return it; - } - }).toList(); - locatorField.set(discoverer, newList); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarFilter.java b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarFilter.java new file mode 100644 index 000000000..c3f1ff1ea --- /dev/null +++ b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightJarInJarFilter.java @@ -0,0 +1,38 @@ +package io.izzel.arclight.boot.neoforge.mod; + +import net.neoforged.fml.loading.moddiscovery.ModFile; +import net.neoforged.neoforgespi.locating.IDependencyLocator; +import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; +import net.neoforged.neoforgespi.locating.IModFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ArclightJarInJarFilter implements IDependencyLocator { + + private static final Logger LOGGER = LoggerFactory.getLogger("ArclightJiJ"); + + @SuppressWarnings("unchecked") + @Override + public void scanMods(List loadedMods, IDiscoveryPipeline pipeline) { + try { + var field = pipeline.getClass().getDeclaredField("loadedFiles"); + field.setAccessible(true); + var loadedFiles = (List) field.get(pipeline); + loadedFiles.removeIf(it -> { + var optional = getClass().getModule().getLayer().findModule(it.getModFileInfo().moduleName()); + optional.ifPresent(module -> LOGGER.info("Skip jij dependency {}@{} because Arclight has {}", + it.getModFileInfo().moduleName(), it.getModFileInfo().versionString(), module.getDescriptor().toNameAndVersion())); + return optional.isPresent(); + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public String toString() { + return "arclight_jij"; + } +} diff --git a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLaunchHandler.java b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLaunchHandler.java index cc76d1665..0bddc063c 100644 --- a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLaunchHandler.java +++ b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLaunchHandler.java @@ -1,8 +1,8 @@ package io.izzel.arclight.boot.neoforge.mod; -import net.neoforged.fml.loading.targets.ForgeServerLaunchHandler; +import net.neoforged.fml.loading.targets.NeoForgeServerLaunchHandler; -public class ArclightLaunchHandler extends ForgeServerLaunchHandler { +public class ArclightLaunchHandler extends NeoForgeServerLaunchHandler { @Override public String name() { diff --git a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLocator_Neoforge.java b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLocator_Neoforge.java index 00adfa5e7..b137c50b4 100644 --- a/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLocator_Neoforge.java +++ b/bootstrap/src/neoforge/java/io/izzel/arclight/boot/neoforge/mod/ArclightLocator_Neoforge.java @@ -1,92 +1,35 @@ package io.izzel.arclight.boot.neoforge.mod; -import cpw.mods.jarhandling.JarContentsBuilder; -import cpw.mods.jarhandling.SecureJar; -import cpw.mods.jarhandling.impl.SimpleJarMetadata; -import net.neoforged.neoforgespi.language.IModFileInfo; -import net.neoforged.neoforgespi.locating.IModFile; -import net.neoforged.neoforgespi.locating.IModLocator; -import net.neoforged.neoforgespi.locating.IModProvider; -import net.neoforged.neoforgespi.locating.ModFileFactory; +import net.neoforged.neoforgespi.ILaunchContext; +import net.neoforged.neoforgespi.locating.IDiscoveryPipeline; +import net.neoforged.neoforgespi.locating.IModFileCandidateLocator; +import net.neoforged.neoforgespi.locating.IncompatibleFileReporting; +import net.neoforged.neoforgespi.locating.ModFileDiscoveryAttributes; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Stream; -import static java.lang.Class.forName; +public class ArclightLocator_Neoforge implements IModFileCandidateLocator { -public class ArclightLocator_Neoforge implements IModLocator { - - private final IModFile arclight; + private final Path arclight; public ArclightLocator_Neoforge() { ModBootstrap.run(); this.arclight = loadJar(); } - @Override - public List scanMods() { - ArclightJarInJarAdaptor.inject(); - return List.of(new ModFileOrException(arclight, null)); - } - - @Override - public String name() { - return "arclight"; - } - - @Override - public void scanFile(IModFile file, Consumer pathConsumer) { - final Function status = p -> file.getSecureJar().verifyPath(p); - try (Stream files = Files.find(file.getSecureJar().getRootPath(), Integer.MAX_VALUE, (p, a) -> p.getNameCount() > 0 && p.getFileName().toString().endsWith(".class"))) { - file.setSecurityStatus(files.peek(pathConsumer).map(status).reduce((s1, s2) -> SecureJar.Status.values()[Math.min(s1.ordinal(), s2.ordinal())]).orElse(SecureJar.Status.INVALID)); - } catch (IOException e) { - e.printStackTrace(); - } + protected Path loadJar() { + var version = System.getProperty("arclight.version"); + return Paths.get(".arclight", "mod_file", version + ".jar"); } @Override - public void initArguments(Map arguments) { + public void findCandidates(ILaunchContext context, IDiscoveryPipeline pipeline) { + pipeline.addPath(this.arclight, ModFileDiscoveryAttributes.DEFAULT, IncompatibleFileReporting.WARN_ALWAYS); } @Override - public boolean isValid(IModFile modFile) { - return true; - } - - protected IModFile loadJar() { - try { - var cl = forName("net.neoforged.fml.loading.moddiscovery.ModFile"); - var lookup = MethodHandles.lookup(); - var handle = lookup.findConstructor(cl, MethodType.methodType(void.class, SecureJar.class, IModProvider.class, ModFileFactory.ModFileInfoParser.class)); - var version = System.getProperty("arclight.version"); - var path = Paths.get(".arclight", "mod_file", version + ".jar"); - var parserCl = forName("net.neoforged.fml.loading.moddiscovery.ModFileParser"); - var modsToml = lookup.findStatic(parserCl, "modsTomlParser", MethodType.methodType(IModFileInfo.class, IModFile.class)); - ModFileFactory.ModFileInfoParser parser = modFile -> { - try { - return (IModFileInfo) modsToml.invoke(modFile); - } catch (Throwable e) { - throw new RuntimeException(e); - } - }; - return (IModFile) handle.invoke(withVersion(path, version), this, parser); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - private SecureJar withVersion(Path path, String version) { - var contents = new JarContentsBuilder().paths(path).build(); - return SecureJar.from(contents, new SimpleJarMetadata("arclight", version.substring(version.indexOf('-') + 1), - contents::getPackages, List.of())); + public String toString() { + return "arclight"; } } diff --git a/bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator b/bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator new file mode 100644 index 000000000..8bf24d18e --- /dev/null +++ b/bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IDependencyLocator @@ -0,0 +1 @@ +io.izzel.arclight.boot.neoforge.mod.ArclightJarInJarFilter \ No newline at end of file diff --git a/bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModLocator b/bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator similarity index 100% rename from bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModLocator rename to bootstrap/src/neoforge/resources/META-INF/services/net.neoforged.neoforgespi.locating.IModFileCandidateLocator diff --git a/build.gradle b/build.gradle index 2fd4a73e8..147efd5cc 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ allprojects { apply plugin: 'java' group 'io.izzel.arclight' - version '1.0.4' + version '1.0.0-SNAPSHOT' def getGitHash = { -> def stdout = new ByteArrayOutputStream() @@ -16,21 +16,21 @@ allprojects { } ext { - minecraftVersion = '1.20.4' + minecraftVersion = '1.21' supportedPlatforms = ['forge', 'neoforge', 'fabric'] fabricLoaderVersion = '0.15.11' - fabricApiVersion = '0.97.1+1.20.4' - forgeVersion = '49.1.0' - neoForgeVersion = '20.4.237' - apiVersion = '1.7.1' + fabricApiVersion = '0.100.1+1.21' + forgeVersion = '51.0.5' + neoForgeVersion = '21.0.4-beta' + apiVersion = '1.7.3' toolsVersion = '1.3.0' mixinVersion = '0.8.5' - mixinToolsVersion = '1.2.3' - versionName = 'whisper' + mixinToolsVersion = '1.2.4' + versionName = 'feudal-kings' gitHash = getGitHash() } - java.toolchain.languageVersion = JavaLanguageVersion.of(17) + java.toolchain.languageVersion = JavaLanguageVersion.of(21) repositories { maven { url = 'https://repo.spongepowered.org/maven' } @@ -41,6 +41,7 @@ allprojects { maven { url = 'https://maven.izzel.io/releases' } maven { url = 'https://jitpack.io/' } mavenCentral() + mavenLocal() } tasks.register('cleanBuild') { @@ -54,7 +55,7 @@ jar.enabled = false tasks.register('collect', Copy) { destinationDir = file('build/libs') - from project(':bootstrap').tasks.forgeJar.outputs + // TODO arch loom updates from project(':bootstrap').tasks.forgeJar.outputs from project(':bootstrap').tasks.neoforgeJar.outputs from project(':bootstrap').tasks.fabricJar.outputs } diff --git a/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/CompatSpec.java b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/CompatSpec.java index 2c8f01436..81e1ad5f3 100644 --- a/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/CompatSpec.java +++ b/i18n-config/src/main/java/io/izzel/arclight/i18n/conf/CompatSpec.java @@ -29,6 +29,9 @@ public class CompatSpec { @Setting("valid-username-regex") private String validUsernameRegex; + @Setting("exact-plugin-entity-damage-control") + private boolean exactPluginEntityDamageControl; + public Map getMaterials() { return materials; } @@ -64,4 +67,8 @@ public boolean isForwardPermissionReverse() { public String getValidUsernameRegex() { return validUsernameRegex; } + + public boolean isExactPluginEntityDamageControl() { + return exactPluginEntityDamageControl; + } } diff --git a/i18n-config/src/main/resources/META-INF/arclight.conf b/i18n-config/src/main/resources/META-INF/arclight.conf index 4aabd60ff..e70f78355 100644 --- a/i18n-config/src/main/resources/META-INF/arclight.conf +++ b/i18n-config/src/main/resources/META-INF/arclight.conf @@ -19,6 +19,7 @@ compatibility { ] forward-permission = true valid-username-regex = "" + exact-plugin-entity-damage-control = false } async-catcher { dump = true diff --git a/i18n-config/src/main/resources/META-INF/i18n/en_us.conf b/i18n-config/src/main/resources/META-INF/i18n/en_us.conf index 0485e2c8b..37587b9f9 100644 --- a/i18n-config/src/main/resources/META-INF/i18n/en_us.conf +++ b/i18n-config/src/main/resources/META-INF/i18n/en_us.conf @@ -21,6 +21,7 @@ release-name { Trials = "顿顽 (Trials)" Net = "毕宿 (Net)" Whisper = "附耳 (Whisper)" + FeudalKings = "诸王 (Feudal Kings)" } java { deprecated = [ @@ -133,6 +134,10 @@ comments { "Following allows any username to login:" "valid-username-regex = \".+\"" ] + exact-plugin-entity-damage-control.comment = [ + "Let plugin or mod controls the final entity damage" + "When set to true, mod added damage will potentially be overridden by plugins" + ] } velocity { enable.comment = [ diff --git a/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf b/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf index a1edbff69..588eba21c 100644 --- a/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf +++ b/i18n-config/src/main/resources/META-INF/i18n/zh_cn.conf @@ -19,6 +19,7 @@ release-name { Trials = "顿顽" Net = "毕宿" Whisper = "附耳" + FeudalKings = "诸王" } java { deprecated = [ @@ -136,6 +137,10 @@ comments { "如果允许任何用户名可以使用" "valid-username-regex = \".+\"" ] + exact-plugin-entity-damage-control.comment = [ + "设置使用插件或模组控制实体伤害" + "设置为 false 时,模组的额外实体伤害可能会被插件覆盖" + ] } velocity { enable.comment = [