diff --git a/docs/README.md b/docs/README.md index fd9ad59741..df333931d5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -5,13 +5,13 @@ +[![discord-widget][]][discord-invite] +[![forge-version][]][forge-commit] + # Ketting Ketting is a fork of [MinecraftForge](https://github.com/MinecraftForge/MinecraftForge/) that enables the use of Bukkit plugins on Forge servers. -
-[ ![discord-widget][] ][discord-invite] -[ ![forge-version][] ][forge-commit] ## Notice @@ -70,4 +70,4 @@ To create a jar, run ```bash ./gradlew kettingJar ``` -(this might take a while, but when it's done, you can find the jar in `build/libs` under `projects/forge`) \ No newline at end of file +(this might take a while, but when it's done, you can find the jar in `build/libs` under `projects/forge`) diff --git a/patches/minecraft/net/minecraft/world/entity/Mob.java.patch b/patches/minecraft/net/minecraft/world/entity/Mob.java.patch index 57082a37e6..64ffd598e3 100644 --- a/patches/minecraft/net/minecraft/world/entity/Mob.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/Mob.java.patch @@ -1,42 +1,177 @@ --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -117,6 +_,9 @@ +@@ -22,6 +_,7 @@ + import net.minecraft.network.syncher.SynchedEntityData; + import net.minecraft.resources.ResourceLocation; + import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; + import net.minecraft.sounds.SoundEvent; + import net.minecraft.tags.TagKey; + import net.minecraft.util.Mth; +@@ -71,6 +_,9 @@ + import net.minecraft.world.level.material.Fluid; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; ++import org.bukkit.craftbukkit.v1_20_R2.entity.CraftLivingEntity; ++import org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory; ++import org.bukkit.event.entity.*; + + public abstract class Mob extends LivingEntity implements Targeting { + private static final EntityDataAccessor DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE); +@@ -95,21 +_,21 @@ + protected JumpControl jumpControl; + private final BodyRotationControl bodyRotationControl; + protected PathNavigation navigation; +- public final GoalSelector goalSelector; +- public final GoalSelector targetSelector; ++ public GoalSelector goalSelector; ++ public GoalSelector targetSelector; + @Nullable + private LivingEntity target; + private final Sensing sensing; + private final NonNullList handItems = NonNullList.withSize(2, ItemStack.EMPTY); +- protected final float[] handDropChances = new float[2]; ++ public final float[] handDropChances = new float[2]; + private final NonNullList armorItems = NonNullList.withSize(4, ItemStack.EMPTY); +- protected final float[] armorDropChances = new float[4]; ++ public final float[] armorDropChances = new float[4]; + private boolean canPickUpLoot; + private boolean persistenceRequired; + private final Map pathfindingMalus = Maps.newEnumMap(BlockPathTypes.class); + @Nullable +- private ResourceLocation lootTable; +- private long lootTableSeed; ++ public ResourceLocation lootTable; ++ public long lootTableSeed; + @Nullable + private Entity leashHolder; + private int delayedLeashHolderId; +@@ -117,6 +_,11 @@ private CompoundTag leashInfoTag; private BlockPos restrictCenter = BlockPos.ZERO; private float restrictRadius = -1.0F; + @Nullable + private MobSpawnType spawnType; + private boolean spawnCancelled = false; ++ ++ public boolean aware = true; // CraftBukkit protected Mob(EntityType p_21368_, Level p_21369_) { super(p_21368_, p_21369_); -@@ -231,7 +_,10 @@ +@@ -136,6 +_,12 @@ + + } + ++ // CraftBukkit start ++ public void setPersistenceRequired(boolean persistenceRequired) { ++ this.persistenceRequired = persistenceRequired; ++ } ++ // CraftBukkit end ++ + protected void registerGoals() { + } + +@@ -231,7 +_,43 @@ } public void setTarget(@Nullable LivingEntity p_21544_) { - this.target = p_21544_; ++ // CraftBukkit start - fire event ++ setTarget(p_21544_, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ public boolean setTarget(@Nullable LivingEntity p_21544_, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (getTarget() == p_21544_) return false; ++ if (fireEvent) { ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN && getTarget() != null && p_21544_ == null) { ++ reason = getTarget().isAlive() ? EntityTargetEvent.TargetReason.FORGOT_TARGET : EntityTargetEvent.TargetReason.TARGET_DIED; ++ } ++ if (reason == EntityTargetEvent.TargetReason.UNKNOWN) { ++ this.level().getCraftServer().getLogger().log(java.util.logging.Level.WARNING, "Unknown target reason, please report on the issue tracker", new Exception()); ++ } ++ CraftLivingEntity ctarget = null; ++ if (p_21544_ != null) { ++ ctarget = (CraftLivingEntity) p_21544_.getBukkitEntity(); ++ } ++ EntityTargetLivingEntityEvent event = new EntityTargetLivingEntityEvent(this.getBukkitEntity(), ctarget, reason); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return false; ++ } ++ ++ if (event.getTarget() != null) { ++ p_21544_ = ((CraftLivingEntity) event.getTarget()).getHandle(); ++ } else { ++ p_21544_ = null; ++ } ++ } ++ + net.minecraftforge.event.entity.living.LivingChangeTargetEvent changeTargetEvent = net.minecraftforge.common.ForgeHooks.onLivingChangeTarget(this, p_21544_, net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.MOB_TARGET); + if(!changeTargetEvent.isCanceled()) { -+ this.target = changeTargetEvent.getNewTarget(); ++ this.target = changeTargetEvent.getNewTarget(); ++ return true; + } ++ return false; ++ // CraftBukkit end } public boolean canAttackType(EntityType p_21399_) { -@@ -429,6 +_,9 @@ +@@ -358,6 +_,12 @@ + return null; + } + ++ // CraftBukkit start - Add delegate method ++ public SoundEvent getAmbientSound0() { ++ return getAmbientSound(); ++ } ++ // CraftBukkit end ++ + public void addAdditionalSaveData(CompoundTag p_21484_) { + super.addAdditionalSaveData(p_21484_); + p_21484_.putBoolean("CanPickUpLoot", this.canPickUpLoot()); +@@ -429,15 +_,29 @@ p_21484_.putBoolean("NoAI", this.isNoAi()); } + if (this.spawnType != null) { + p_21484_.putString("forge:spawn_type", this.spawnType.name()); + } ++ ++ p_21484_.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit } public void readAdditionalSaveData(CompoundTag p_21450_) { -@@ -481,6 +_,14 @@ + super.readAdditionalSaveData(p_21450_); ++ ++ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it + if (p_21450_.contains("CanPickUpLoot", 1)) { +- this.setCanPickUpLoot(p_21450_.getBoolean("CanPickUpLoot")); ++ boolean data = p_21450_.getBoolean("CanPickUpLoot"); ++ if (isLevelAtLeast(p_21450_, 1) || data) { ++ this.setCanPickUpLoot(data); ++ } + } + +- this.persistenceRequired = p_21450_.getBoolean("PersistenceRequired"); ++ boolean data = p_21450_.getBoolean("PersistenceRequired"); ++ if (isLevelAtLeast(p_21450_, 1) || data) { ++ this.persistenceRequired = data; ++ } ++ // CraftBukkit end + if (p_21450_.contains("ArmorItems", 9)) { + ListTag listtag = p_21450_.getList("ArmorItems", 10); + +@@ -481,6 +_,20 @@ } this.setNoAi(p_21450_.getBoolean("NoAI")); + ++ // CraftBukkit start ++ if (p_21450_.contains("Bukkit.Aware")) { ++ this.aware = p_21450_.getBoolean("Bukkit.Aware"); ++ } ++ // CraftBukkit end ++ + if (p_21450_.contains("forge:spawn_type")) { + try { + this.spawnType = MobSpawnType.valueOf(p_21450_.getString("forge:spawn_type")); @@ -58,6 +193,48 @@ for(ItemEntity itementity : this.level().getEntitiesOfClass(ItemEntity.class, this.getBoundingBox().inflate((double)vec3i.getX(), (double)vec3i.getY(), (double)vec3i.getZ()))) { if (!itementity.isRemoved() && !itementity.getItem().isEmpty() && !itementity.hasPickUpDelay() && this.wantsToPickUp(itementity.getItem())) { this.pickUpItem(itementity); +@@ -539,7 +_,7 @@ + + protected void pickUpItem(ItemEntity p_21471_) { + ItemStack itemstack = p_21471_.getItem(); +- ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy()); ++ ItemStack itemstack1 = this.equipItemIfPossible(itemstack.copy(), p_21471_); // CraftBukkit - add item + if (!itemstack1.isEmpty()) { + this.onItemPickup(p_21471_); + this.take(p_21471_, itemstack1.getCount()); +@@ -552,6 +_,12 @@ + } + + public ItemStack equipItemIfPossible(ItemStack p_255842_) { ++ // CraftBukkit start - add item ++ return this.equipItemIfPossible(p_255842_, null); ++ } ++ ++ public ItemStack equipItemIfPossible(ItemStack p_255842_, ItemEntity entity) { ++ // CraftBukkit end + EquipmentSlot equipmentslot = getEquipmentSlotForItem(p_255842_); + ItemStack itemstack = this.getItemBySlot(equipmentslot); + boolean flag = this.canReplaceCurrentItem(p_255842_, itemstack); +@@ -561,10 +_,18 @@ + flag = itemstack.isEmpty(); + } + +- if (flag && this.canHoldItem(p_255842_)) { ++ // CraftBukkit start ++ boolean canPickup = flag && this.canHoldItem(p_255842_); ++ if (entity != null) { ++ canPickup = !org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.callEntityPickupItemEvent(this, entity, 0, !canPickup).isCancelled(); ++ } ++ if (canPickup) { ++ // CraftBukkit end + double d0 = (double)this.getEquipmentDropChance(equipmentslot); + if (!itemstack.isEmpty() && (double)Math.max(this.random.nextFloat() - 0.1F, 0.0F) < d0) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + + if (equipmentslot.isArmor() && p_255842_.getCount() > 1) { @@ -698,6 +_,14 @@ this.discard(); } else if (!this.isPersistenceRequired() && !this.requiresCustomPersistence()) { @@ -73,6 +250,14 @@ if (entity != null) { double d0 = entity.distanceToSqr(this); int i = this.getType().getCategory().getDespawnDistance(); +@@ -722,6 +_,7 @@ + + protected final void serverAiStep() { + ++this.noActionTime; ++ if (!this.aware) return; // CraftBukkit + this.level().getProfiler().push("sensing"); + this.sensing.tick(); + this.level().getProfiler().pop(); @@ -1031,6 +_,16 @@ } @@ -98,6 +283,113 @@ return p_21437_; } +@@ -1080,6 +_,12 @@ + if (!this.isAlive()) { + return InteractionResult.PASS; + } else if (this.getLeashHolder() == p_21420_) { ++ // CraftBukkit start - fire PlayerUnleashEntityEvent ++ if (CraftEventFactory.callPlayerUnleashEntityEvent(this, p_21420_, p_21421_).isCancelled()) { ++ ((ServerPlayer) p_21420_).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.dropLeash(true, !p_21420_.getAbilities().instabuild); + this.gameEvent(GameEvent.ENTITY_INTERACT, p_21420_); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1103,6 +_,12 @@ + private InteractionResult checkAndHandleImportantInteractions(Player p_21500_, InteractionHand p_21501_) { + ItemStack itemstack = p_21500_.getItemInHand(p_21501_); + if (itemstack.is(Items.LEAD) && this.canBeLeashed(p_21500_)) { ++ // CraftBukkit start - fire PlayerLeashEntityEvent ++ if (CraftEventFactory.callPlayerLeashEntityEvent(this, p_21500_, p_21500_, p_21501_).isCancelled()) { ++ ((ServerPlayer) p_21500_).connection.send(new ClientboundSetEntityLinkPacket(this, this.getLeashHolder())); ++ return InteractionResult.PASS; ++ } ++ // CraftBukkit end + this.setLeashedTo(p_21500_, true); + itemstack.shrink(1); + return InteractionResult.sidedSuccess(this.level().isClientSide); +@@ -1171,8 +_,15 @@ + return this.restrictRadius != -1.0F; + } + ++ // CraftBukkit start + @Nullable + public T convertTo(EntityType p_21407_, boolean p_21408_) { ++ return this.convertTo(p_21407_, p_21408_, EntityTransformEvent.TransformReason.UNKNOWN, CreatureSpawnEvent.SpawnReason.DEFAULT); ++ } ++ ++ @Nullable ++ public T convertTo(EntityType p_21407_, boolean p_21408_, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { ++ // CraftBukkit end + if (this.isRemoved()) { + return (T)null; + } else { +@@ -1205,7 +_,12 @@ + } + } + +- this.level().addFreshEntity(t); ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, t, transformReason).isCancelled()) { ++ return null; ++ } ++ this.level().addFreshEntity(t, spawnReason); ++ // CraftBukkit end + if (this.isPassenger()) { + Entity entity = this.getVehicle(); + this.stopRiding(); +@@ -1225,6 +_,7 @@ + + if (this.leashHolder != null) { + if (!this.isAlive() || !this.leashHolder.isAlive()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), (!this.isAlive()) ? EntityUnleashEvent.UnleashReason.PLAYER_UNLEASH : EntityUnleashEvent.UnleashReason.HOLDER_GONE)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1236,7 +_,9 @@ + this.leashHolder = null; + this.leashInfoTag = null; + if (!this.level().isClientSide && p_21457_) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + } + + if (!this.level().isClientSide && p_21456_ && this.level() instanceof ServerLevel) { +@@ -1284,6 +_,7 @@ + public boolean startRiding(Entity p_21396_, boolean p_21397_) { + boolean flag = super.startRiding(p_21396_, p_21397_); + if (flag && this.isLeashed()) { ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, true); + } + +@@ -1306,7 +_,9 @@ + } + + if (this.tickCount > 100) { ++ this.forceDrops = true; // CraftBukkit + this.spawnAtLocation(Items.LEAD); ++ this.forceDrops = false; // CraftBukkit + this.leashInfoTag = null; + } + } +@@ -1379,6 +_,14 @@ + + int i = EnchantmentHelper.getFireAspect(this); + if (i > 0) { ++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item ++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), p_21372_.getBukkitEntity(), i * 4); ++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent); ++ ++ if (!combustEvent.isCancelled()) { ++ p_21372_.setSecondsOnFire(combustEvent.getDuration(), false); ++ } ++ // CraftBukkit end + p_21372_.setSecondsOnFire(i * 4); + } + @@ -1425,15 +_,25 @@ return false; } @@ -125,6 +417,14 @@ public void removeFreeWill() { this.removeAllGoals((p_262562_) -> { return true; +@@ -1447,6 +_,7 @@ + + protected void removeAfterChangingDimensions() { + super.removeAfterChangingDimensions(); ++ this.level().getCraftServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); // CraftBukkit + this.dropLeash(true, false); + this.getAllSlots().forEach((p_278936_) -> { + if (!p_278936_.isEmpty()) { @@ -1460,5 +_,40 @@ public ItemStack getPickResult() { SpawnEggItem spawneggitem = SpawnEggItem.byId(this.getType());