From 4f0e52fb699a8e86a9859bc038fa1fb3bfba4cec Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sun, 14 Jun 2020 14:49:42 +0800 Subject: [PATCH] Entities --- .../common/bridge/entity/EntityBridge.java | 2 + .../bridge/entity/LivingEntityBridge.java | 7 + .../common/bridge/entity/MobEntityBridge.java | 2 + .../entity/player/PlayerEntityBridge.java | 4 +- .../player/ServerPlayerEntityBridge.java | 4 + .../ProjectileItemEntityBridge.java | 11 + .../common/bridge/world/ExplosionBridge.java | 2 + .../common/bridge/world/TeleporterBridge.java | 12 + .../world/dimension/DimensionTypeBridge.java | 8 + .../common/mixin/core/entity/EntityMixin.java | 7 + .../mixin/core/entity/LivingEntityMixin.java | 227 +----------- .../mixin/core/entity/MobEntityMixin.java | 30 +- .../core/entity/item/ItemEntityMixin.java | 13 +- .../core/entity/item/TNTEntityMixin.java | 13 +- .../minecart/AbstractMinecartEntityMixin.java | 25 +- ...rfishEntity_SummonSilverfishGoalMixin.java | 7 +- .../core/entity/monster/SlimeEntityMixin.java | 1 + .../monster/ZombieVillagerEntityMixin.java | 4 +- .../entity/passive/OcelotEntityMixin.java | 10 - .../core/entity/passive/PandaEntityMixin.java | 4 +- .../core/entity/passive/SheepEntityMixin.java | 2 +- .../core/entity/passive/WolfEntityMixin.java | 14 +- .../core/entity/player/PlayerEntityMixin.java | 119 +------ .../player/ServerPlayerEntityMixin.java | 252 ++------------ .../DamagingProjectileEntityMixin.java | 3 +- .../entity/projectile/PotionEntityMixin.java | 19 + .../projectile/ProjectileItemEntityMixin.java | 44 +++ .../projectile/SmallFireballEntityMixin.java | 4 + .../projectile/WitherSkullEntityMixin.java | 2 +- .../mixin/core/fluid/FlowingFluidMixin.java | 42 +-- .../mixin/core/fluid/LavaFluidMixin.java | 18 + .../inventory/EnderChestInventoryMixin.java | 9 + .../mixin/core/world/ExplosionMixin.java | 108 +----- .../mixin/core/world/IBlockReaderMixin.java | 8 +- .../mixin/core/world/TeleporterMixin.java | 16 +- .../mixin/core/world/TrackedEntityMixin.java | 12 +- .../world/chunk/storage/ChunkLoaderMixin.java | 17 + .../v1_15/block/LilyPadBlockMixin_1_15.java | 24 ++ .../mixin/v1_15/entity/EntityMixin_1_15.java | 16 +- .../v1_15/entity/LivingEntityMixin_1_15.java | 274 +++++++++++++++ .../entity/boss/WitherEntityMixin_1_15.java | 177 ++++++++++ .../entity/item/ItemEntityMixin_1_15.java | 18 + .../monster/AbstractRaiderEntityMixin.java | 24 ++ .../monster/RavagerEntityMixin_1_15.java | 22 ++ .../monster/ShulkerEntityMixin_1_15.java | 19 + .../monster/ZombiePigmanEntityMixin_1_15.java | 57 +++ .../entity/player/PlayerEntityMixin_1_15.java | 145 ++++++++ .../player/ServerPlayerEntityMixin_1_15.java | 326 ++++++++++++++++++ .../item/crafting/SpecialRecipeMixin.java | 15 + .../v1_15/world/ExplosionMixin_1_15.java | 139 ++++++++ .../dimension/DimensionTypeMixin_1_15.java | 8 +- .../resources/mixins.arclight.core.1_15.json | 11 + .../main/resources/mixins.arclight.core.json | 11 +- .../v1_14/block/LilyPadBlockMixin_1_14.java | 4 +- .../mixin/v1_14/entity/EntityMixin_1_14.java | 16 +- .../v1_14/entity/LivingEntityMixin_1_14.java | 278 +++++++++++++++ .../entity/boss/WitherEntityMixin_1_14.java | 4 +- .../entity/item/ItemEntityMixin_1_14.java | 18 + .../monster/PillagerEntityMixin_1_14.java | 4 +- .../monster/RavagerEntityMixin_1_14.java | 4 +- .../monster/ShulkerEntityMixin_1_14.java | 4 +- .../monster/ZombiePigmanEntityMixin_1_14.java | 56 +++ .../passive/OcelotEntityMixin_1_14.java | 19 + .../passive/PandaEntity_MateGoalMixin.java | 2 +- .../entity/player/PlayerEntityMixin_1_14.java | 138 ++++++++ .../player/ServerPlayerEntityMixin_1_14.java | 264 ++++++++++++++ .../v1_14/world/ExplosionMixin_1_14.java | 136 ++++++++ .../dimension/DimensionTypeMixin_1_14.java | 8 +- .../java/io/izzel/arclight/server/Main.java | 8 +- .../resources/mixins.arclight.core.1_14.json | 13 + 70 files changed, 2573 insertions(+), 771 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/projectile/ProjectileItemEntityBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/TeleporterBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/dimension/DimensionTypeBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/ProjectileItemEntityMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/storage/ChunkLoaderMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/block/LilyPadBlockMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/LivingEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/boss/WitherEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/item/ItemEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/AbstractRaiderEntityMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/RavagerEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ShulkerEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ZombiePigmanEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/PlayerEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/ServerPlayerEntityMixin_1_15.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/item/crafting/SpecialRecipeMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/ExplosionMixin_1_15.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/LilyPadBlockMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/block/LilyPadBlockMixin_1_14.java (91%) create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/LivingEntityMixin_1_14.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/boss/WitherEntityMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/boss/WitherEntityMixin_1_14.java (98%) create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/item/ItemEntityMixin_1_14.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/PillagerEntityMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/PillagerEntityMixin_1_14.java (85%) rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/RavagerEntityMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/RavagerEntityMixin_1_14.java (87%) rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ShulkerEntityMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ShulkerEntityMixin_1_14.java (85%) create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ZombiePigmanEntityMixin_1_14.java create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/OcelotEntityMixin_1_14.java rename {arclight-common/src/main/java/io/izzel/arclight/common/mixin/core => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14}/entity/passive/PandaEntity_MateGoalMixin.java (94%) create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/PlayerEntityMixin_1_14.java create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/ServerPlayerEntityMixin_1_14.java create mode 100644 arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/ExplosionMixin_1_14.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/EntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/EntityBridge.java index 5a3a83e7..4be710d2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/EntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/EntityBridge.java @@ -52,4 +52,6 @@ public interface EntityBridge extends ICommandSourceBridge { void bridge$setRideCooldown(int rideCooldown); int bridge$getRideCooldown(); + + double bridge$getEyeHeight(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/LivingEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/LivingEntityBridge.java index 2ff983f5..6661c064 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/LivingEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/LivingEntityBridge.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.bridge.entity; +import net.minecraft.entity.LivingEntity; import net.minecraft.potion.Effect; import net.minecraft.potion.EffectInstance; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; @@ -18,6 +19,12 @@ public interface LivingEntityBridge extends EntityBridge { void bridge$setExpToDrop(int amount); + int bridge$getExpToDrop(); + + void bridge$dropExperience(); + + void bridge$createWitherRose(LivingEntity entity); + void bridge$pushHealReason(EntityRegainHealthEvent.RegainReason regainReason); void bridge$heal(float healAmount, EntityRegainHealthEvent.RegainReason regainReason); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/MobEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/MobEntityBridge.java index 650b49d6..a8d0c133 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/MobEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/MobEntityBridge.java @@ -16,6 +16,8 @@ public interface MobEntityBridge extends LivingEntityBridge { void bridge$setPersistenceRequired(boolean value); + void bridge$setAware(boolean aware); + interface Hack { ResourceLocation getLootTable(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/PlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/PlayerEntityBridge.java index 164c9be5..426c5038 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/PlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/PlayerEntityBridge.java @@ -1,11 +1,11 @@ package io.izzel.arclight.common.bridge.entity.player; import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.util.Unit; import net.minecraft.util.math.BlockPos; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; -import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; public interface PlayerEntityBridge extends LivingEntityBridge { @@ -13,6 +13,8 @@ public interface PlayerEntityBridge extends LivingEntityBridge { String bridge$getSpawnWorld(); + void bridge$setSpawnWorld(String world); + @Override CraftHumanEntity bridge$getBukkitEntity(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java index 44667cc7..04a41324 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java @@ -9,6 +9,8 @@ import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.event.player.PlayerTeleportEvent; +import java.util.Optional; + public interface ServerPlayerEntityBridge extends PlayerEntityBridge { @Override @@ -16,6 +18,8 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge { void bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause cause); + Optional bridge$getTeleportCause(); + BlockPos bridge$getSpawnPoint(ServerWorld world); boolean bridge$isMovementBlocked(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/projectile/ProjectileItemEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/projectile/ProjectileItemEntityBridge.java new file mode 100644 index 00000000..934ca538 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/projectile/ProjectileItemEntityBridge.java @@ -0,0 +1,11 @@ +package io.izzel.arclight.common.bridge.entity.projectile; + +import net.minecraft.item.Item; + +public interface ProjectileItemEntityBridge { + + interface Hack { + + Item getDefaultItem(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/ExplosionBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/ExplosionBridge.java index 1b003fc0..caedf4fb 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/ExplosionBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/ExplosionBridge.java @@ -14,4 +14,6 @@ public interface ExplosionBridge { Explosion.Mode bridge$getMode(); boolean bridge$wasCancelled(); + + float bridge$callBlockExplodeEvent(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/TeleporterBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/TeleporterBridge.java new file mode 100644 index 00000000..8f905516 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/TeleporterBridge.java @@ -0,0 +1,12 @@ +package io.izzel.arclight.common.bridge.world; + +import net.minecraft.block.pattern.BlockPattern; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; + +public interface TeleporterBridge { + + boolean bridge$makePortal(Entity entityIn, BlockPos pos, int createRadius); + + BlockPattern.PortalInfo bridge$placeInPortal(Entity p_222268_1_, BlockPos pos, float p_222268_2_, int searchRadius, boolean searchOnly); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/dimension/DimensionTypeBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/dimension/DimensionTypeBridge.java new file mode 100644 index 00000000..56d66c7b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/dimension/DimensionTypeBridge.java @@ -0,0 +1,8 @@ +package io.izzel.arclight.common.bridge.world.dimension; + +import net.minecraft.world.dimension.DimensionType; + +public interface DimensionTypeBridge { + + DimensionType bridge$getType(); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java index 5a46f2c3..582240ad 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/EntityMixin.java @@ -169,6 +169,13 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract float getEyeHeight(); @Shadow @Nullable public abstract Entity changeDimension(DimensionType destination); @Shadow public abstract boolean isRidingSameEntity(Entity entityIn); + @Shadow public boolean noClip; + @Shadow public abstract double getPosX(); + @Shadow public abstract double getPosY(); + @Shadow public abstract double getPosZ(); + @Shadow(remap = false) public abstract void revive(); + @Shadow public abstract Vec3d getPositionVec(); + @Shadow public abstract boolean isInvulnerable(); // @formatter:on private static final int CURRENT_LEVEL = 2; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/LivingEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/LivingEntityMixin.java index c53e8e1a..bde208ab 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/LivingEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/LivingEntityMixin.java @@ -1,9 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity; import com.google.common.base.Function; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; @@ -15,7 +12,6 @@ import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AbstractAttributeMap; import net.minecraft.entity.ai.attributes.IAttribute; import net.minecraft.entity.ai.attributes.IAttributeInstance; -import net.minecraft.entity.item.ExperienceOrbEntity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.passive.AnimalEntity; import net.minecraft.entity.passive.TameableEntity; @@ -29,7 +25,6 @@ import net.minecraft.nbt.FloatNBT; import net.minecraft.nbt.INBT; import net.minecraft.nbt.IntNBT; import net.minecraft.network.datasync.DataParameter; -import net.minecraft.particles.ParticleTypes; import net.minecraft.potion.Effect; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; @@ -39,13 +34,12 @@ import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSource; import net.minecraft.util.Hand; import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.GameRules; import net.minecraft.world.World; import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.event.entity.living.PotionEvent; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.craftbukkit.v.attribute.CraftAttributeMap; @@ -73,10 +67,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Iterator; -import java.util.List; -import java.util.Map; import java.util.Optional; import java.util.Random; @@ -99,18 +89,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow protected boolean dead; @Shadow public void remove(boolean keepData) { } @Shadow public abstract IAttributeInstance getAttribute(IAttribute attribute); - @Shadow @Final public Map activePotionsMap; - @Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect); - @Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply); @Shadow public boolean potionsNeedUpdate; - @Shadow protected abstract void updatePotionMetadata(); - @Shadow @Final private static DataParameter POTION_EFFECTS; - @Shadow @Final private static DataParameter HIDE_PARTICLES; @Shadow public abstract boolean removePotionEffect(Effect effectIn); - @Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn); - @Shadow protected abstract void onNewPotionEffect(EffectInstance id); @Shadow public abstract boolean clearActivePotions(); - @Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin); @Shadow @Final public static DataParameter HEALTH; @Shadow public abstract boolean isPotionActive(Effect potionIn); @Shadow public abstract boolean isSleeping(); @@ -162,6 +143,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public CombatTracker combatTracker; @Shadow public abstract ItemStack getHeldItemOffhand(); @Shadow public abstract Random getRNG(); + @Shadow public abstract Optional getBedPosition(); + @Shadow public abstract boolean addPotionEffect(EffectInstance effectInstanceIn); // @formatter:on public int expToDrop; @@ -198,8 +181,8 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } public int getExpReward() { - int exp = this.getExperiencePoints(this.attackingPlayer); if (!this.world.isRemote && (this.recentlyHit > 0 || this.isPlayer()) && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT)) { + int exp = this.getExperiencePoints(this.attackingPlayer); return ForgeEventFactory.getExperienceDrop((LivingEntity) (Object) this, this.attackingPlayer, exp); } else { return 0; @@ -217,37 +200,13 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } @Override - public boolean bridge$isForceDrops() { - return forceDrops; + public int bridge$getExpToDrop() { + return this.expToDrop; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected void onDeathUpdate() { - ++this.deathTime; - if (this.deathTime >= 20 && !this.removed) { - if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) { - int i = this.expToDrop; - while (i > 0) { - int j = ExperienceOrbEntity.getXPSplit(i); - i -= j; - this.world.addEntity(new ExperienceOrbEntity(this.world, this.posX, this.posY, this.posZ, j)); - } - this.expToDrop = 0; - } - - this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player - - for (int k = 0; k < 20; ++k) { - double d2 = this.rand.nextGaussian() * 0.02D; - double d0 = this.rand.nextGaussian() * 0.02D; - double d1 = this.rand.nextGaussian() * 0.02D; - this.world.addParticle(ParticleTypes.POOF, this.posX + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.posY + (double) (this.rand.nextFloat() * this.getHeight()), this.posZ + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1); - } - } + @Override + public boolean bridge$isForceDrops() { + return forceDrops; } @Inject(method = "readAdditional", at = @At("HEAD")) @@ -262,160 +221,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - private boolean isTickingEffects = false; - private List, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList(); - - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - protected void updatePotionEffects() { - this.isTickingEffects = true; - Iterator iterator = this.activePotionsMap.keySet().iterator(); - - try { - while (iterator.hasNext()) { - Effect effect = iterator.next(); - EffectInstance effectinstance = this.activePotionsMap.get(effect); - if (!effectinstance.tick((LivingEntity) (Object) this)) { - if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) { - - EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); - if (event.isCancelled()) { - continue; - } - - iterator.remove(); - this.onFinishedPotionEffect(effectinstance); - } - } else if (effectinstance.getDuration() % 600 == 0) { - this.onChangedPotionEffect(effectinstance, false); - } - } - } catch (ConcurrentModificationException ignored) { - } - - isTickingEffects = false; - for (Map.Entry, EntityPotionEffectEvent.Cause> e : effectsToProcess) { - Either either = e.getKey(); - EntityPotionEffectEvent.Cause cause = e.getValue(); - bridge$pushEffectCause(cause); - if (either.left().isPresent()) { - addPotionEffect(either.left().get()); - } else { - removePotionEffect(either.right().get()); - } - } - effectsToProcess.clear(); - - if (this.potionsNeedUpdate) { - if (!this.world.isRemote) { - this.updatePotionMetadata(); - } - - this.potionsNeedUpdate = false; - } - - int i = this.dataManager.get(POTION_EFFECTS); - boolean flag1 = this.dataManager.get(HIDE_PARTICLES); - if (i > 0) { - boolean flag; - if (this.isInvisible()) { - flag = this.rand.nextInt(15) == 0; - } else { - flag = this.rand.nextBoolean(); - } - - if (flag1) { - flag &= this.rand.nextInt(5) == 0; - } - - 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.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.posY + this.rand.nextDouble() * (double) this.getHeight(), this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2); - } - } - } - @Inject(method = "clearActivePotions", at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraftforge/eventbus/api/IEventBus;post(Lnet/minecraftforge/eventbus/api/Event;)Z")) public void arclight$clearReason(CallbackInfoReturnable cir) { arclight$action = EntityPotionEffectEvent.Action.CLEARED; } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public boolean addPotionEffect(EffectInstance effectInstanceIn) { - EntityPotionEffectEvent.Cause cause = arclight$cause == null ? EntityPotionEffectEvent.Cause.UNKNOWN : arclight$cause; - arclight$cause = null; - if (isTickingEffects) { - effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause)); - return true; - } - - if (!this.isPotionApplicable(effectInstanceIn)) { - return false; - } else { - EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion()); - - boolean override = false; - if (effectinstance != null) { - override = new EffectInstance(effectinstance).combine(effectInstanceIn); - } - - EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override); - if (event.isCancelled()) { - return false; - } - - MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn)); - if (effectinstance == null) { - this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn); - this.onNewPotionEffect(effectInstanceIn); - return true; - } else if (event.isOverride()) { - effectinstance.combine(effectInstanceIn); - this.onChangedPotionEffect(effectinstance, true); - return true; - } else { - return false; - } - } - } - - @SuppressWarnings("unused") // mock - public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) { - bridge$pushEffectCause(cause); - return removeActivePotionEffect(potioneffectin); - } - - @Inject(method = "removeActivePotionEffect", at = @At("HEAD")) - public void arclight$clearActive(Effect effect, CallbackInfoReturnable cir) { - EntityPotionEffectEvent.Cause cause = arclight$cause == null ? EntityPotionEffectEvent.Cause.UNKNOWN : arclight$cause; - arclight$cause = null; - if (isTickingEffects) { - effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause)); - cir.setReturnValue(null); - return; - } - - EffectInstance effectInstance = this.activePotionsMap.get(effect); - if (effectInstance == null) { - cir.setReturnValue(null); - return; - } - - EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause); - if (event.isCancelled()) { - cir.setReturnValue(null); - } - } - private transient EntityPotionEffectEvent.Action arclight$action; @Override @@ -669,6 +479,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt float absorptionModifier = absorption.apply((double) f).floatValue(); EntityDamageEvent event = CraftEventFactory.handleLivingEntityDamageEvent((LivingEntity) (Object) this, damagesource, originalDamage, hardHatModifier, blockingModifier, armorModifier, resistanceModifier, magicModifier, absorptionModifier, hardHat, blocking, armor, resistance, magic, absorption); + + if (damagesource.getTrueSource() instanceof PlayerEntity) { + ((PlayerEntity) damagesource.getTrueSource()).resetCooldown(); + } + if (event.isCancelled()) { return false; } @@ -877,20 +692,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - private transient boolean arclight$fallSuccess; - - @Inject(method = "fall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) - public void arclight$fall(float distance, float damageMultiplier, CallbackInfo ci) { - if (!arclight$fallSuccess) { - ci.cancel(); - } - } - - @Redirect(method = "fall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) - public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) { - return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount); - } - @Redirect(method = "applyArmorCalculations", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;damageArmor(F)V")) public void arclight$muteDamageArmor(LivingEntity livingEntity, float damage) { } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/MobEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/MobEntityMixin.java index 879e5655..bbe418ba 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/MobEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/MobEntityMixin.java @@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.entity; import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.MobEntityBridge; +import io.izzel.arclight.common.mod.ArclightMod; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -37,7 +38,6 @@ 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 io.izzel.arclight.common.mod.ArclightMod; import javax.annotation.Nullable; import java.util.concurrent.atomic.AtomicBoolean; @@ -66,6 +66,13 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt @Shadow public abstract boolean isAIDisabled(); // @formatter:on + public boolean aware; + + @Override + public void bridge$setAware(boolean aware) { + this.aware = aware; + } + @Inject(method = "setCanPickUpLoot", at = @At("HEAD")) public void arclight$setPickupLoot(boolean canPickup, CallbackInfo ci) { super.canPickUpLoot = canPickup; @@ -83,6 +90,7 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt @Inject(method = "", at = @At("RETURN")) private void arclight$init(EntityType type, World worldIn, CallbackInfo ci) { this.persistenceRequired = !this.canDespawn(0.0); + this.aware = true; } private transient AtomicBoolean arclight$targetSuccess; @@ -155,6 +163,18 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt arclight$fireEvent = fireEvent; } + @Inject(method = "writeAdditional", at = @At("HEAD")) + private void arclight$setAware(CompoundNBT compound, CallbackInfo ci) { + compound.putBoolean("Bukkit.Aware", this.aware); + } + + @Inject(method = "readAdditional", at = @At("HEAD")) + private void arclight$readAware(CompoundNBT compound, CallbackInfo ci) { + if (compound.contains("Bukkit.Aware")) { + this.aware = compound.getBoolean("Bukkit.Aware"); + } + } + @Redirect(method = "readAdditional", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;setCanPickUpLoot(Z)V")) public void arclight$setIfTrue(MobEntity mobEntity, boolean canPickup) { if (canPickup) mobEntity.setCanPickUpLoot(true); @@ -165,6 +185,14 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt return nbt.getBoolean(key) || this.persistenceRequired; } + @Inject(method = "updateEntityActionState", cancellable = true, at = @At("HEAD")) + private void arclight$unaware(CallbackInfo ci) { + if (!this.aware) { + ++this.idleTime; + ci.cancel(); + } + } + /** * @author IzzelAliz * @reason diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/ItemEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/ItemEntityMixin.java index c2131178..f408c555 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/ItemEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/ItemEntityMixin.java @@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.entity.item; import com.google.common.base.Preconditions; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; +import io.izzel.arclight.common.bridge.entity.player.PlayerInventoryBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import io.izzel.arclight.common.bridge.network.datasync.EntityDataManagerBridge; import io.izzel.arclight.common.mixin.core.entity.EntityMixin; @@ -23,10 +24,8 @@ 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 io.izzel.arclight.common.bridge.entity.player.PlayerInventoryBridge; import java.util.UUID; @@ -38,7 +37,6 @@ public abstract class ItemEntityMixin extends EntityMixin { @Shadow public int pickupDelay; @Shadow public abstract ItemStack getItem(); @Shadow private UUID owner; - @Shadow public int age; // @formatter:on @Inject(method = "func_213858_a", cancellable = true, at = @At("HEAD")) @@ -48,13 +46,6 @@ public abstract class ItemEntityMixin extends EntityMixin { } } - @Redirect(method = "func_213858_a", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V")) - private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) { - if (!stack.isEmpty()) { - itemEntity.setItem(stack); - } - } - @Inject(method = "attackEntityFrom", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/ItemEntity;markVelocityChanged()V")) private void arclight$damageNonLiving(DamageSource source, float amount, CallbackInfoReturnable cir) { if (CraftEventFactory.handleNonLivingEntityDamageEvent((ItemEntity) (Object) this, source, amount)) { @@ -109,7 +100,7 @@ public abstract class ItemEntityMixin extends EntityMixin { } else if (this.pickupDelay == 0) { this.pickupDelay = -1; } - if (this.pickupDelay == 0 && (this.owner == null || 6000 - this.age <= 200 || this.owner.equals(entity.getUniqueID())) && entity.inventory.addItemStackToInventory(itemstack)) { + if (this.pickupDelay == 0 && (this.owner == null /*|| 6000 - this.age <= 200*/ || this.owner.equals(entity.getUniqueID())) && entity.inventory.addItemStackToInventory(itemstack)) { entity.onItemPickup((ItemEntity) (Object) this, i); if (itemstack.isEmpty()) { this.remove(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/TNTEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/TNTEntityMixin.java index 85aab284..f04bd16c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/TNTEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/TNTEntityMixin.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity.item; +import io.izzel.arclight.api.ArclightVersion; import io.izzel.arclight.common.mixin.core.entity.EntityMixin; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -44,9 +45,11 @@ public abstract class TNTEntityMixin extends EntityMixin { */ @Overwrite public void tick() { - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; + if (ArclightVersion.lesserThan(ArclightVersion.v1_15)) { + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + } if (!this.hasNoGravity()) { this.setMotion(this.getMotion().add(0.0D, -0.04D, 0.0D)); } @@ -65,7 +68,9 @@ public abstract class TNTEntityMixin extends EntityMixin { this.remove(); } else { this.handleWaterMovement(); - this.world.addParticle(ParticleTypes.SMOKE, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D); + if (this.world.isRemote) { + this.world.addParticle(ParticleTypes.SMOKE, this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D); + } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/minecart/AbstractMinecartEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/minecart/AbstractMinecartEntityMixin.java index 25026fba..40b58c84 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/minecart/AbstractMinecartEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/item/minecart/AbstractMinecartEntityMixin.java @@ -160,9 +160,11 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin { this.setRotation(this.rotationYaw, this.rotationPitch); } } else { + /* this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; + */ if (!this.hasNoGravity()) { this.setMotion(this.getMotion().add(0.0, -0.04, 0.0)); } @@ -217,11 +219,14 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin { entity.startRiding((AbstractMinecartEntity) (Object) this); } } else { - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity).bridge$getBukkitEntity()); - Bukkit.getPluginManager().callEvent(collisionEvent); - if (!collisionEvent.isCancelled()) { - entity.applyEntityCollision((AbstractMinecartEntity) (Object) this); + if (!isRidingSameEntity(entity)) { + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, ((EntityBridge) entity).bridge$getBukkitEntity()); + Bukkit.getPluginManager().callEvent(collisionEvent); + if (collisionEvent.isCancelled()) { + continue; + } } + entity.applyEntityCollision((AbstractMinecartEntity) (Object) this); } } } @@ -273,12 +278,14 @@ public abstract class AbstractMinecartEntityMixin extends EntityMixin { return this.isBeingRidden() || !this.slowWhenEmpty; } - @Inject(method = "applyEntityCollision", at = @At(value = "FIELD", ordinal = 0, target = "Lnet/minecraft/entity/Entity;posX:D")) + @Inject(method = "applyEntityCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/minecart/AbstractMinecartEntity;isPassenger(Lnet/minecraft/entity/Entity;)Z")) private void arclight$vehicleCollide(Entity entityIn, CallbackInfo ci) { - VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), ((EntityBridge) entityIn).bridge$getBukkitEntity()); - Bukkit.getPluginManager().callEvent(collisionEvent); - if (collisionEvent.isCancelled()) { - ci.cancel(); + if (!this.isPassenger(entityIn)) { + VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent((Vehicle) this.getBukkitEntity(), ((EntityBridge) entityIn).bridge$getBukkitEntity()); + Bukkit.getPluginManager().callEvent(collisionEvent); + if (collisionEvent.isCancelled()) { + ci.cancel(); + } } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SilverfishEntity_SummonSilverfishGoalMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SilverfishEntity_SummonSilverfishGoalMixin.java index 064003ca..7abf67cd 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SilverfishEntity_SummonSilverfishGoalMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SilverfishEntity_SummonSilverfishGoalMixin.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity.monster; +import io.izzel.arclight.api.ArclightVersion; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -46,7 +47,11 @@ public abstract class SilverfishEntity_SummonSilverfishGoalMixin extends Goal { continue; } if (ForgeEventFactory.getMobGriefingEvent(world, this.silverfish)) { - world.destroyBlock(blockpos1, true); + if (ArclightVersion.atLeast(ArclightVersion.v1_15)) { + world.destroyBlock(blockpos1, true, this.silverfish); + } else { + world.destroyBlock(blockpos1, true); + } } else { world.setBlockState(blockpos1, ((SilverfishBlock) block).getMimickedBlock().getDefaultState(), 3); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SlimeEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SlimeEntityMixin.java index f1877c94..cbd02593 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SlimeEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/SlimeEntityMixin.java @@ -55,6 +55,7 @@ public abstract class SlimeEntityMixin extends MobEntityMixin { if (this.isNoDespawnRequired()) { entityslime.enablePersistence(); } + entityslime.setInvulnerable(this.isInvulnerable()); entityslime.setSlimeSize(i / 2, true); entityslime.setLocationAndAngles(this.posX + f, this.posY + 0.5, this.posZ + f2, this.rand.nextFloat() * 360.0f, 0.0f); slimes.add(entityslime); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ZombieVillagerEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ZombieVillagerEntityMixin.java index f4f9f96b..da94c98e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ZombieVillagerEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ZombieVillagerEntityMixin.java @@ -33,11 +33,11 @@ public abstract class ZombieVillagerEntityMixin extends ZombieEntityMixin { bridge$pushEffectCause(EntityPotionEffectEvent.Cause.CONVERSION); } - @Redirect(method = "func_213791_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombieVillagerEntity;remove()V")) + @Redirect(method = "cureZombie", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombieVillagerEntity;remove()V")) private void arclight$transformPre(ZombieVillagerEntity zombieVillagerEntity) { } - @Inject(method = "func_213791_a", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) + @Inject(method = "cureZombie", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) private void arclight$transform(ServerWorld world, CallbackInfo ci, VillagerEntity villagerEntity) { if (CraftEventFactory.callEntityTransformEvent((ZombieVillagerEntity)(Object)this, villagerEntity, EntityTransformEvent.TransformReason.CURED).isCancelled()) { ((ZombieVillager) getBukkitEntity()).setConversionTime(-1); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/OcelotEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/OcelotEntityMixin.java index 5d78c9b1..4ba16c24 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/OcelotEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/OcelotEntityMixin.java @@ -1,14 +1,9 @@ package io.izzel.arclight.common.mixin.core.entity.passive; -import io.izzel.arclight.common.bridge.world.WorldBridge; import net.minecraft.entity.passive.OcelotEntity; -import org.bukkit.event.entity.CreatureSpawnEvent; 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; @Mixin(OcelotEntity.class) public abstract class OcelotEntityMixin extends AnimalEntityMixin { @@ -27,9 +22,4 @@ public abstract class OcelotEntityMixin extends AnimalEntityMixin { public boolean canDespawn(double distanceToClosestPlayer) { return !this.isTrusting() /*&& this.ticksExisted > 2400*/; } - - @Inject(method = "func_213525_dW", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) - private void arclight$spawnBaby(CallbackInfo ci) { - ((WorldBridge) this.world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.OCELOT_BABY); - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntityMixin.java index ff97eea7..e06a3d35 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntityMixin.java @@ -15,7 +15,7 @@ import java.util.function.Predicate; @Mixin(PandaEntity.class) public abstract class PandaEntityMixin extends AnimalEntityMixin { - @Shadow @Final private static Predicate field_213607_bQ; + @Shadow @Final private static Predicate PANDA_ITEMS; /** * @author IzzelAliz @@ -23,7 +23,7 @@ public abstract class PandaEntityMixin extends AnimalEntityMixin { */ @Overwrite protected void updateEquipmentIfNeeded(ItemEntity itemEntity) { - boolean cancel = this.getItemStackFromSlot(EquipmentSlotType.MAINHAND).isEmpty() && field_213607_bQ.test(itemEntity); + boolean cancel = this.getItemStackFromSlot(EquipmentSlotType.MAINHAND).isEmpty() && PANDA_ITEMS.test(itemEntity); if (CraftEventFactory.callEntityPickupItemEvent((PandaEntity) (Object) this, itemEntity, 0, cancel).isCancelled()) { ItemStack itemstack = itemEntity.getItem(); this.setItemStackToSlot(EquipmentSlotType.MAINHAND, itemstack); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/SheepEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/SheepEntityMixin.java index 04bdb544..04fdb32d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/SheepEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/SheepEntityMixin.java @@ -37,7 +37,7 @@ public abstract class SheepEntityMixin extends AnimalEntityMixin { } } - @Inject(method = "func_213611_a", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) + @Inject(method = "createDyeColorCraftingInventory", locals = LocalCapture.CAPTURE_FAILHARD, at = @At("RETURN")) private static void arclight$resultInv(DyeColor p_213611_0_, DyeColor p_213611_1_, CallbackInfoReturnable cir, CraftingInventory craftingInventory) { ((CraftingInventoryBridge) craftingInventory).bridge$setResultInventory(new CraftResultInventory()); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/WolfEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/WolfEntityMixin.java index 534c162c..42ce239b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/WolfEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/WolfEntityMixin.java @@ -19,11 +19,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(WolfEntity.class) public abstract class WolfEntityMixin extends TameableEntityMixin { - @Shadow - public abstract void setAngry(boolean angry); - - @Shadow - public abstract boolean isAngry(); + // @formatter:off + @Shadow public abstract void setAngry(boolean angry); + @Shadow public abstract boolean isAngry(); + // @formatter:on @Override public boolean setGoalTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fire) { @@ -54,6 +53,11 @@ public abstract class WolfEntityMixin extends TameableEntityMixin { private void arclight$handledBy(SitGoal sitGoal, boolean sitting) { } + @Redirect(method = "setTamed", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/WolfEntity;setHealth(F)V")) + private void arclight$healToMax(WolfEntity wolfEntity, float health) { + wolfEntity.setHealth(wolfEntity.getMaxHealth()); + } + @Inject(method = "processInteract", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/passive/WolfEntity;heal(F)V")) private void arclight$healReason(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.EATING); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/PlayerEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/PlayerEntityMixin.java index 1a1c6f1c..6001d774 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/PlayerEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/PlayerEntityMixin.java @@ -1,14 +1,15 @@ package io.izzel.arclight.common.mixin.core.entity.player; import com.mojang.authlib.GameProfile; -import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.inventory.IInventoryBridge; +import io.izzel.arclight.common.bridge.util.DamageSourceBridge; import io.izzel.arclight.common.bridge.util.FoodStatsBridge; -import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge; +import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.CreatureAttribute; import net.minecraft.entity.Entity; @@ -23,6 +24,7 @@ import net.minecraft.entity.player.PlayerAbilities; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.EnderChestInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.item.ItemStack; @@ -35,14 +37,12 @@ import net.minecraft.scoreboard.Scoreboard; import net.minecraft.stats.Stat; import net.minecraft.stats.Stats; import net.minecraft.util.DamageSource; -import net.minecraft.util.Direction; import net.minecraft.util.FoodStats; import net.minecraft.util.Hand; import net.minecraft.util.HandSide; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvents; -import net.minecraft.util.Unit; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -53,18 +53,16 @@ import net.minecraft.world.server.ServerWorld; import net.minecraftforge.common.ForgeHooks; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; -import org.bukkit.block.Block; -import org.bukkit.craftbukkit.v.block.CraftBlock; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.craftbukkit.v.util.CraftVector; +import org.bukkit.entity.HumanEntity; 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.EntityPotionEffectEvent; import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.player.PlayerBedLeaveEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerVelocityEvent; import org.bukkit.scoreboard.Team; @@ -75,25 +73,18 @@ 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.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 io.izzel.arclight.common.bridge.util.DamageSourceBridge; -import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin; import java.util.List; -import java.util.Optional; @Mixin(PlayerEntity.class) public abstract class PlayerEntityMixin extends LivingEntityMixin implements PlayerEntityBridge { // @formatter:off - @Shadow public int sleepTimer; @Shadow public abstract String getScoreboardName(); - @Shadow public abstract Either trySleep(BlockPos at); - @Shadow public abstract void startSleeping(BlockPos p_213342_1_); @Shadow @Final public PlayerAbilities abilities; @Shadow public abstract float getCooledAttackStrength(float adjustTicks); @Shadow public abstract void resetCooldown(); @@ -104,7 +95,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla @Shadow public abstract void onEnchantmentCritical(Entity entityHit); @Shadow public abstract void addStat(ResourceLocation p_195067_1_, int p_195067_2_); @Shadow public abstract void addExhaustion(float exhaustion); - @Shadow private long field_223730_e; + @Shadow private long timeEntitySatOnShoulder; @Shadow public abstract void setRightShoulderEntity(CompoundNBT tag); @Shadow public abstract void setLeftShoulderEntity(CompoundNBT tag); @Shadow public abstract CompoundNBT getRightShoulderEntity(); @@ -123,6 +114,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla @Shadow protected FoodStats foodStats; @Shadow protected boolean isMovementBlocked() { return false; } @Shadow public abstract Scoreboard getWorldScoreboard(); + @Shadow protected EnderChestInventory enterChestInventory; // @formatter:on public boolean fauxSleeping; @@ -133,6 +125,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla private void arclight$init(World worldIn, GameProfile gameProfileIn, CallbackInfo ci) { oldLevel = -1; ((FoodStatsBridge) this.foodStats).bridge$setEntityHuman((PlayerEntity) (Object) this); + ((IInventoryBridge) this.enterChestInventory).setOwner(((HumanEntity) this.getBukkitEntity())); } @Override @@ -422,92 +415,9 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla } } - private boolean arclight$forceSleep = false; - private Object arclight$processSleep = null; - - public CraftHumanEntity getBukkitEntity() { - return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity(); - } - - private Either getBedResult(BlockPos at, Direction direction) { - arclight$processSleep = true; - Either either = this.trySleep(at); - arclight$processSleep = null; - return either; - } - - public Either sleep(BlockPos at, boolean force) { - arclight$forceSleep = force; - try { - return this.trySleep(at); - } finally { - arclight$forceSleep = false; - } - } - - @Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD")) - public void arclight$onSleep(BlockPos at, CallbackInfoReturnable> cir) { - if (arclight$processSleep == null) { - Either result = getBedResult(at, null); - - if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) { - cir.setReturnValue(result); - return; - } - if (arclight$forceSleep) { - result = Either.right(Unit.INSTANCE); - } - if (this.bridge$getBukkitEntity() instanceof Player) { - result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result); - if (result.left().isPresent()) { - cir.setReturnValue(result); - return; - } - } - - this.startSleeping(at); - this.sleepTimer = 0; - if (this.world instanceof ServerWorld) { - ((ServerWorld) this.world).updateAllPlayersSleepingFlag(); - } - cir.setReturnValue(Either.right(Unit.INSTANCE)); - } - } - - @Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V")) - public void arclight$preSleep(BlockPos at, CallbackInfoReturnable> cir) { - if (arclight$processSleep != null) { - cir.setReturnValue(Either.right(Unit.INSTANCE)); - } - } - - @Inject(method = "wakeUpPlayer", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I")) - private void arclight$wakeup(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci, Optional optional) { - if (this.getBukkitEntity() instanceof Player) { - final Player player = (Player) this.getBukkitEntity(); - final BlockPos blockposition2 = optional.orElse(null); - Block bed; - if (blockposition2 != null) { - bed = CraftBlock.at(this.world, blockposition2); - } else { - bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation()); - } - final PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, setSpawn); - Bukkit.getPluginManager().callEvent(event); - arclight$setSpawn = event.shouldSetSpawnLocation(); - } - } - - private boolean arclight$setSpawn; - - @ModifyVariable(method = "wakeUpPlayer", index = 3, name = "setSpawn", at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I")) - private boolean arclight$modifySpawn(boolean setSpawn) { - return arclight$setSpawn; - } - - @Inject(method = "setSpawnPoint(Lnet/minecraft/util/math/BlockPos;Z)V", at = @At("RETURN")) - private void arclight$updateSpawnpoint(BlockPos pos, boolean forced, CallbackInfo ci) { - this.spawnWorld = pos == null ? "" : this.world.worldInfo.getWorldName(); + @Override + public void bridge$setSpawnWorld(String world) { + this.spawnWorld = world; } @Redirect(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;setFlag(IZ)V")) @@ -523,7 +433,7 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla */ @Overwrite protected void spawnShoulderEntities() { - if (this.field_223730_e + 20L < this.world.getGameTime()) { + if (this.timeEntitySatOnShoulder + 20L < this.world.getGameTime()) { if (this.spawnEntityFromShoulder(this.getLeftShoulderEntity())) { this.setLeftShoulderEntity(new CompoundNBT()); } @@ -548,11 +458,6 @@ public abstract class PlayerEntityMixin extends LivingEntityMixin implements Pla return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity(); } - @Override - public Either bridge$trySleep(BlockPos at, boolean force) { - return sleep(at, force); - } - @Override public String bridge$getSpawnWorld() { return spawnWorld; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java index 656c2f7e..31a9737d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java @@ -1,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity.player; import com.google.common.collect.Lists; -import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; @@ -9,12 +8,8 @@ import io.izzel.arclight.common.bridge.inventory.container.ContainerBridge; import io.izzel.arclight.common.bridge.util.FoodStatsBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.mod.util.ChestBlockDoubleInventoryHacks; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.boss.WitherEntity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.passive.horse.AbstractHorseEntity; import net.minecraft.entity.player.PlayerEntity; @@ -24,7 +19,6 @@ import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.HorseInventoryContainer; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.item.crafting.RecipeBook; import net.minecraft.item.crafting.ServerRecipeBook; import net.minecraft.nbt.CompoundNBT; @@ -33,21 +27,14 @@ import net.minecraft.network.play.client.CClientSettingsPacket; import net.minecraft.network.play.server.SChangeGameStatePacket; import net.minecraft.network.play.server.SCombatPacket; import net.minecraft.network.play.server.SOpenHorseWindowPacket; -import net.minecraft.network.play.server.SPlayEntityEffectPacket; -import net.minecraft.network.play.server.SPlaySoundEventPacket; -import net.minecraft.network.play.server.SPlayerAbilitiesPacket; -import net.minecraft.network.play.server.SRespawnPacket; -import net.minecraft.network.play.server.SServerDifficultyPacket; import net.minecraft.network.play.server.SSetSlotPacket; import net.minecraft.network.play.server.SUpdateHealthPacket; -import net.minecraft.potion.EffectInstance; import net.minecraft.scoreboard.Score; import net.minecraft.scoreboard.ScoreCriteria; import net.minecraft.scoreboard.Scoreboard; import net.minecraft.scoreboard.Team; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerInteractionManager; -import net.minecraft.server.management.PlayerList; import net.minecraft.stats.Stat; import net.minecraft.stats.Stats; import net.minecraft.util.CombatTracker; @@ -55,7 +42,6 @@ import net.minecraft.util.DamageSource; import net.minecraft.util.FoodStats; import net.minecraft.util.HandSide; import net.minecraft.util.NonNullList; -import net.minecraft.util.Unit; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -67,9 +53,7 @@ import net.minecraft.util.text.event.HoverEvent; import net.minecraft.world.GameRules; import net.minecraft.world.GameType; import net.minecraft.world.World; -import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.WorldInfo; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -80,18 +64,14 @@ import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.event.CraftEventFactory; 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.event.entity.EntityPotionEffectEvent; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerChangedMainHandEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerLocaleChangeEvent; -import org.bukkit.event.player.PlayerPortalEvent; import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.inventory.MainHand; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -108,6 +88,7 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import java.util.Optional; import java.util.OptionalInt; import java.util.Random; import java.util.function.Consumer; @@ -125,11 +106,11 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen @Shadow public abstract void closeScreen(); @Shadow public abstract void setSpectatingEntity(Entity entityToSpectate); @Shadow public boolean invulnerableDimensionChange; - @Shadow public abstract ServerWorld func_71121_q(); + @Shadow public abstract ServerWorld getServerWorld(); @Shadow public boolean queuedEndExit; @Shadow private boolean seenCredits; @Shadow @Nullable private Vec3d enteredNetherPosition; - @Shadow protected abstract void func_213846_b(ServerWorld p_213846_1_); + @Shadow public abstract void func_213846_b(ServerWorld p_213846_1_); @Shadow public int lastExperience; @Shadow private float lastHealth; @Shadow private int lastFoodLevel; @@ -137,7 +118,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen @Shadow public abstract void getNextWindowId(); @Shadow public abstract void sendMessage(ITextComponent component); @Shadow public String language; - @Shadow public abstract void func_200619_a(ServerWorld p_200619_1_, double x, double y, double z, float yaw, float pitch); + @Shadow public abstract void teleport(ServerWorld p_200619_1_, double x, double y, double z, float yaw, float pitch); @Shadow public abstract void giveExperiencePoints(int p_195068_1_); // @formatter:on @@ -168,7 +149,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen public BlockPos getSpawnPoint(ServerWorld worldserver) { BlockPos blockposition = worldserver.getSpawnPoint(); if (worldserver.dimension.hasSkyLight() && worldserver.getWorldInfo().getGameType() != GameType.ADVENTURE) { - int i = Math.max(0, this.server.func_184108_a(worldserver)); + int i = Math.max(0, this.server.getSpawnRadius(worldserver)); int j = MathHelper.floor(worldserver.getWorldBorder().getClosestDistance(blockposition.getX(), blockposition.getZ())); if (j < i) { i = j; @@ -233,7 +214,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen CraftWorld cworld = (CraftWorld) Bukkit.getServer().getWorld(this.spawnWorld); if (cworld != null && this.getBedLocation() != null) { world = cworld.getHandle(); - position = PlayerEntity.func_213822_a(cworld.getHandle(), this.getBedLocation(), false).orElse(null); + position = PlayerEntity.checkBedValidRespawnPosition(cworld.getHandle(), this.getBedLocation(), false).orElse(null); } } if (world == null || position == null) { @@ -244,7 +225,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen this.setPosition(position.getX(), position.getY(), position.getZ()); } this.dimension = this.world.getDimension().getType(); - this.interactionManager.func_73080_a((ServerWorld) world); + this.interactionManager.setWorld((ServerWorld) world); } @Inject(method = "tick", at = @At("HEAD")) @@ -330,31 +311,23 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen this.connection.sendPacket(new SCombatPacket(this.getCombatTracker(), SCombatPacket.Event.ENTITY_DIED)); } this.spawnShoulderEntities(); + + this.bridge$dropExperience(); + if (!event.getKeepInventory()) { this.inventory.clear(); } this.setSpectatingEntity((ServerPlayerEntity) (Object) this); ((CraftScoreboardManager) Bukkit.getScoreboardManager()).getScoreboardScores(ScoreCriteria.DEATH_COUNT, this.getScoreboardName(), Score::incrementScore); + LivingEntity entityliving = this.getAttackingEntity(); if (entityliving != null) { this.addStat(Stats.ENTITY_KILLED_BY.get(entityliving.getType())); entityliving.awardKillScore((ServerPlayerEntity) (Object) this, this.scoreValue, damagesource); - if (!this.world.isRemote && entityliving instanceof WitherEntity) { - boolean flag3 = false; - if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, (ServerPlayerEntity) (Object) this)) { - BlockPos blockposition = new BlockPos(this.posX, this.posY, this.posZ); - BlockState iblockdata = Blocks.WITHER_ROSE.getDefaultState(); - if (this.world.getBlockState(blockposition).isAir() && iblockdata.isValidPosition(this.world, blockposition)) { - this.world.setBlockState(blockposition, iblockdata, 3); - flag3 = true; - } - } - if (!flag3) { - ItemEntity entityitem = new ItemEntity(this.world, this.posX, this.posY, this.posZ, new ItemStack(Items.WITHER_ROSE)); - this.world.addEntity(entityitem); - } - } + this.bridge$createWitherRose(entityliving); } + + this.world.setEntityState((ServerPlayerEntity) (Object) this, (byte) 3); this.addStat(Stats.DEATHS); this.takeStat(Stats.CUSTOM.get(Stats.TIME_SINCE_DEATH)); this.takeStat(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)); @@ -378,177 +351,6 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen cir.setReturnValue(((WorldBridge) this.world).bridge$isPvpMode()); } - /** - * @author IzzelAliz - * @reason - */ - @Nullable - @Overwrite - // todo DimensionType getType - public Entity changeDimension(DimensionType dimensionmanager) { - PlayerTeleportEvent.TeleportCause cause = arclight$cause == null ? PlayerTeleportEvent.TeleportCause.UNKNOWN : arclight$cause; - arclight$cause = null; - if (!net.minecraftforge.common.ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, dimensionmanager)) - return null; - if (this.isSleeping()) { - return (ServerPlayerEntity) (Object) this; - } - DimensionType dimensionmanager2 = this.dimension; - if (dimensionmanager2 == DimensionType.THE_END && dimensionmanager == DimensionType.OVERWORLD) { - this.invulnerableDimensionChange = true; - this.detach(); - this.func_71121_q().removePlayer((ServerPlayerEntity) (Object) this, true); - if (!this.queuedEndExit) { - this.queuedEndExit = true; - this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0f : 1.0f)); - this.seenCredits = true; - } - return (ServerPlayerEntity) (Object) this; - } - ServerWorld worldserver = this.server.func_71218_a(dimensionmanager2); - ServerWorld worldserver2 = this.server.func_71218_a(dimensionmanager); - WorldInfo worlddata = this.world.getWorldInfo(); - double d0 = this.posX; - double d2 = this.posY; - double d3 = this.posZ; - float f = this.rotationPitch; - float f2 = this.rotationYaw; - double d4 = 8.0; - float f3 = f2; - worldserver.getProfiler().startSection("moving"); - if (worldserver2 != null) { - if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_NETHER) { - this.enteredNetherPosition = new Vec3d(this.posX, this.posY, this.posZ); - d0 /= 8.0; - d3 /= 8.0; - } else if (dimensionmanager2 == DimensionType.THE_NETHER && dimensionmanager == DimensionType.OVERWORLD) { - d0 *= 8.0; - d3 *= 8.0; - } else if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_END) { - BlockPos blockposition = worldserver2.getSpawnCoordinate(); - d0 = blockposition.getX(); - d2 = blockposition.getY(); - d3 = blockposition.getZ(); - f2 = 90.0f; - f = 0.0f; - } - } - Location enter = this.getBukkitEntity().getLocation(); - Location exit = (worldserver2 == null) ? null : new Location(((WorldBridge) worldserver2).bridge$getWorld(), d0, d2, d3, f2, f); - PlayerPortalEvent event = new PlayerPortalEvent(this.getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(event); - if (event.isCancelled() || event.getTo() == null) { - return null; - } - exit = event.getTo(); - if (exit == null) { - return null; - } - PlayerTeleportEvent tpEvent = new PlayerTeleportEvent(this.getBukkitEntity(), enter, exit, cause); - Bukkit.getServer().getPluginManager().callEvent(tpEvent); - if (tpEvent.isCancelled() || tpEvent.getTo() == null) { - return null; - } - exit = tpEvent.getTo(); - if (exit == null) { - return null; - } - worldserver2 = ((CraftWorld) exit.getWorld()).getHandle(); - d0 = exit.getX(); - d2 = exit.getY(); - d3 = exit.getZ(); - f2 = exit.getYaw(); - f = exit.getPitch(); - this.invulnerableDimensionChange = true; - dimensionmanager = worldserver2.getDimension().getType(); - this.dimension = dimensionmanager; - net.minecraftforge.fml.network.NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this); - this.connection.sendPacket(new SRespawnPacket(worldserver2.dimension.getType(), this.world.getWorldInfo().getGenerator(), this.interactionManager.getGameType())); - this.connection.sendPacket(new SServerDifficultyPacket(this.world.getDifficulty(), this.world.getWorldInfo().isDifficultyLocked())); - PlayerList playerlist = this.server.getPlayerList(); - playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this); - worldserver.removePlayer((ServerPlayerEntity) (Object) this, true); - this.removed = false; - this.setLocationAndAngles(d0, d2, d3, f2, f); - worldserver.getProfiler().endSection(); - worldserver.getProfiler().startSection("placing"); - double d5 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minX() + 16.0); - double d6 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minZ() + 16.0); - double d7 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxX() - 16.0); - double d8 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxZ() - 16.0); - d0 = MathHelper.clamp(d0, d5, d7); - d3 = MathHelper.clamp(d3, d6, d8); - this.setLocationAndAngles(d0, d2, d3, f2, f); - if (dimensionmanager == DimensionType.THE_END) { - int i = MathHelper.floor(this.posX); - int j = MathHelper.floor(this.posY) - 1; - int k = MathHelper.floor(this.posZ); - boolean flag = true; - boolean flag2 = false; - BlockStateListPopulator blockList = new BlockStateListPopulator(worldserver2); - for (int l = -2; l <= 2; ++l) { - for (int i2 = -2; i2 <= 2; ++i2) { - for (int j2 = -1; j2 < 3; ++j2) { - int k2 = i + i2 * 1 + l * 0; - int l2 = j + j2; - int i3 = k + i2 * 0 - l * 1; - boolean flag3 = j2 < 0; - blockList.setBlockState(new BlockPos(k2, l2, i3), flag3 ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3); - } - } - } - org.bukkit.World bworld = ((WorldBridge) worldserver2).bridge$getWorld(); - PortalCreateEvent portalEvent = new PortalCreateEvent((List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM); - Bukkit.getPluginManager().callEvent(portalEvent); - if (!portalEvent.isCancelled()) { - blockList.updateList(); - } - this.setLocationAndAngles(i, j, k, f2, 0.0f); - this.setMotion(Vec3d.ZERO); - } else if (!worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3)) { - worldserver2.getDefaultTeleporter().makePortal((ServerPlayerEntity) (Object) this); - worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3); - } - worldserver.getProfiler().endSection(); - this.setWorld(worldserver2); - worldserver2.func_217447_b((ServerPlayerEntity) (Object) this); - this.func_213846_b(worldserver); - this.connection.setPlayerLocation(this.posX, this.posY, this.posZ, f2, f); - this.interactionManager.func_73080_a(worldserver2); - this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities)); - playerlist.func_72354_b((ServerPlayerEntity) (Object) this, worldserver2); - playerlist.sendInventory((ServerPlayerEntity) (Object) this); - for (EffectInstance mobeffect : this.getActivePotionEffects()) { - this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), mobeffect)); - } - this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false)); - this.lastExperience = -1; - this.lastHealth = -1.0f; - this.lastFoodLevel = -1; - PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent(this.getBukkitEntity(), ((WorldBridge) worldserver).bridge$getWorld()); - Bukkit.getPluginManager().callEvent(changeEvent); - net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensionmanager2, dimensionmanager); - return (ServerPlayerEntity) (Object) this; - } - - public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) { - bridge$pushChangeDimensionCause(cause); - return this.changeDimension(dimensionmanager); - } - - @Override - public Either sleep(BlockPos at, boolean force) { - return super.sleep(at, force).ifRight((p_213849_1_) -> { - this.addStat(Stats.SLEEP_IN_BED); - CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this); - }); - } - - @Inject(method = "wakeUpPlayer", cancellable = true, at = @At("HEAD")) - private void arclight$notWake(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci) { - if (!isSleeping()) ci.cancel(); - } - public int nextContainerCounter() { this.getNextWindowId(); return this.currentWindowId; @@ -677,21 +479,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen return listName; } - @Inject(method = "setElytraFlying", cancellable = true, at = @At("HEAD")) - private void arclight$beginGlide(CallbackInfo ci) { - if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, true).isCancelled()) { - ci.cancel(); - } - } - - @Inject(method = "clearElytraFlying", cancellable = true, at = @At("HEAD")) - private void arclight$endGlide(CallbackInfo ci) { - if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, false).isCancelled()) { - ci.cancel(); - } - } - - @Inject(method = "func_200619_a", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/ServerPlayerEntity;stopRiding()V")) + @Inject(method = "teleport", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/ServerPlayerEntity;stopRiding()V")) private void arclight$handleBy(ServerWorld world, double x, double y, double z, float yaw, float pitch, CallbackInfo ci) { PlayerTeleportEvent.TeleportCause cause = arclight$cause == null ? PlayerTeleportEvent.TeleportCause.UNKNOWN : arclight$cause; arclight$cause = null; @@ -701,7 +489,7 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen public void a(ServerWorld worldserver, double d0, double d1, double d2, float f, float f1, PlayerTeleportEvent.TeleportCause cause) { bridge$pushChangeDimensionCause(cause); - func_200619_a(worldserver, d0, d1, d2, f, f1); + teleport(worldserver, d0, d1, d2, f, f1); } public CraftPlayer getBukkitEntity() { @@ -721,8 +509,12 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen } @Override - public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) { - return a(dimensionType, cause); + public Optional bridge$getTeleportCause() { + try { + return Optional.ofNullable(arclight$cause); + } finally { + arclight$cause = null; + } } public long getPlayerTime() { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/DamagingProjectileEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/DamagingProjectileEntityMixin.java index c70b7322..2e3af0f4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/DamagingProjectileEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/DamagingProjectileEntityMixin.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity.projectile; +import io.izzel.arclight.common.bridge.entity.projectile.DamagingProjectileEntityBridge; import io.izzel.arclight.common.mixin.core.entity.EntityMixin; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -16,7 +17,6 @@ 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 io.izzel.arclight.common.bridge.entity.projectile.DamagingProjectileEntityBridge; @Mixin(DamagingProjectileEntity.class) public abstract class DamagingProjectileEntityMixin extends EntityMixin implements DamagingProjectileEntityBridge { @@ -26,6 +26,7 @@ public abstract class DamagingProjectileEntityMixin extends EntityMixin implemen @Shadow public double accelerationY; @Shadow public double accelerationZ; @Shadow public LivingEntity shootingEntity; + @Shadow protected void onImpact(RayTraceResult result) {} // @formatter:on public float bukkitYield; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/PotionEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/PotionEntityMixin.java index def8925d..6ce9ed20 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/PotionEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/PotionEntityMixin.java @@ -2,6 +2,9 @@ package io.izzel.arclight.common.mixin.core.entity.projectile; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.CampfireBlock; import net.minecraft.entity.AreaEffectCloudEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; @@ -11,7 +14,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.potion.Effect; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Potion; +import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityPotionEffectEvent; @@ -104,4 +109,18 @@ public abstract class PotionEntityMixin extends ThrowableEntityMixin { entity.remove(); } } + + @Inject(method = "extinguishFires", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;extinguishFire(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/Direction;)Z")) + private void arclight$entityChangeBlock(BlockPos pos, Direction direction, CallbackInfo ci) { + if (CraftEventFactory.callEntityChangeBlockEvent((PotionEntity) (Object) this, pos.offset(direction), Blocks.AIR.getDefaultState()).isCancelled()) { + ci.cancel(); + } + } + + @Inject(method = "extinguishFires", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;playEvent(Lnet/minecraft/entity/player/PlayerEntity;ILnet/minecraft/util/math/BlockPos;I)V")) + private void arclight$entityChangeBlock2(BlockPos pos, Direction p_184542_2_, CallbackInfo ci, BlockState state) { + if (CraftEventFactory.callEntityChangeBlockEvent((PotionEntity) (Object) this, pos, state.with(CampfireBlock.LIT, false)).isCancelled()) { + ci.cancel(); + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/ProjectileItemEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/ProjectileItemEntityMixin.java new file mode 100644 index 00000000..6f3f2d2f --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/ProjectileItemEntityMixin.java @@ -0,0 +1,44 @@ +package io.izzel.arclight.common.mixin.core.entity.projectile; + +import io.izzel.arclight.common.bridge.entity.projectile.ProjectileItemEntityBridge; +import net.minecraft.entity.projectile.ProjectileItemEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.util.Util; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Implements; +import org.spongepowered.asm.mixin.Interface; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(ProjectileItemEntity.class) +@Implements(@Interface(iface = ProjectileItemEntityBridge.Hack.class, prefix = "hack$")) +public abstract class ProjectileItemEntityMixin extends ThrowableEntityMixin { + + // @formatter:off + @Shadow protected abstract Item shadow$getDefaultItem(); + @Shadow @Final private static DataParameter ITEMSTACK_DATA; + // @formatter:on + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void setItem(ItemStack stack) { + if (stack.getItem() != this.shadow$getDefaultItem() || stack.hasTag()) { + this.getDataManager().set(ITEMSTACK_DATA, Util.make(stack.copy(), (itemStack) -> { + if (!itemStack.isEmpty()) { + itemStack.setCount(1); + } + })); + } + + } + + public Item hack$getDefaultItem() { + return this.shadow$getDefaultItem(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/SmallFireballEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/SmallFireballEntityMixin.java index 3a116681..e32cfada 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/SmallFireballEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/SmallFireballEntityMixin.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.core.entity.projectile; +import io.izzel.arclight.api.ArclightVersion; import io.izzel.arclight.common.bridge.entity.EntityBridge; import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; @@ -39,6 +40,9 @@ public abstract class SmallFireballEntityMixin extends DamagingProjectileEntityM */ @Overwrite protected void onImpact(RayTraceResult result) { + if (ArclightVersion.atLeast(ArclightVersion.v1_15)) { + super.onImpact(result); + } if (!this.world.isRemote) { if (result.getType() == RayTraceResult.Type.ENTITY) { Entity entity = ((EntityRayTraceResult) result).getEntity(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/WitherSkullEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/WitherSkullEntityMixin.java index 9c2e5b89..215602f1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/WitherSkullEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/projectile/WitherSkullEntityMixin.java @@ -22,7 +22,7 @@ public abstract class WitherSkullEntityMixin extends DamagingProjectileEntityMix @Inject(method = "onImpact", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;heal(F)V")) private void arclight$heal(RayTraceResult result, CallbackInfo ci) { - ((LivingEntityBridge) this.shootingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN); + ((LivingEntityBridge) this.shootingEntity).bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER); } @Inject(method = "onImpact", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;addPotionEffect(Lnet/minecraft/potion/EffectInstance;)Z")) 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 0d91d365..9666d2c6 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,7 +1,6 @@ package io.izzel.arclight.common.mixin.core.fluid; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.fluid.FlowingFluid; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.IFluidState; @@ -9,7 +8,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; -import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import org.bukkit.Bukkit; import org.bukkit.block.Block; @@ -20,7 +18,6 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.BlockFromToEvent; import org.bukkit.event.block.FluidLevelChangeEvent; 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; @@ -32,9 +29,6 @@ public abstract class FlowingFluidMixin { // @formatter:off @Shadow protected abstract boolean canFlow(IBlockReader worldIn, BlockPos fromPos, BlockState fromBlockState, Direction direction, BlockPos toPos, BlockState toBlockState, IFluidState toFluidState, Fluid fluidIn); - @Shadow protected abstract IFluidState calculateCorrectFlowingState(IWorldReader worldIn, BlockPos pos, BlockState blockStateIn); - @Shadow protected abstract int func_215667_a(World p_215667_1_, BlockPos p_215667_2_, IFluidState p_215667_3_, IFluidState p_215667_4_); - @Shadow protected abstract void flowAround(IWorld worldIn, BlockPos pos, IFluidState stateIn); // @formatter:on @Inject(method = "flowAround", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/fluid/FlowingFluid;flowInto(Lnet/minecraft/world/IWorld;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/Direction;Lnet/minecraft/fluid/IFluidState;)V")) @@ -59,35 +53,13 @@ public abstract class FlowingFluidMixin { } } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void tick(World worldIn, BlockPos pos, IFluidState state) { - if (!state.isSource()) { - IFluidState ifluidstate = this.calculateCorrectFlowingState(worldIn, pos, worldIn.getBlockState(pos)); - int i = this.func_215667_a(worldIn, pos, state, ifluidstate); - if (ifluidstate.isEmpty()) { - state = ifluidstate; - FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(worldIn, pos, Blocks.AIR.getDefaultState()); - if (event.isCancelled()) { - return; - } - worldIn.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), 3); - } else if (!ifluidstate.equals(state)) { - state = ifluidstate; - BlockState blockstate = ifluidstate.getBlockState(); - FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(worldIn, pos, blockstate); - if (event.isCancelled()) { - return; - } - worldIn.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), 2); - worldIn.getPendingFluidTicks().scheduleTick(pos, ifluidstate.getFluid(), i); - worldIn.notifyNeighborsOfStateChange(pos, blockstate.getBlock()); - } + @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) + private boolean arclight$fluidLevelChange(World world, BlockPos pos, BlockState newState, int flags) { + FluidLevelChangeEvent event = CraftEventFactory.callFluidLevelChangeEvent(world, pos, newState); + if (event.isCancelled()) { + return false; + } else { + return world.setBlockState(pos, ((CraftBlockData) event.getNewData()).getState(), flags); } - - this.flowAround(worldIn, pos, state); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/LavaFluidMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/LavaFluidMixin.java index dd54f675..b9a46f2d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/LavaFluidMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/fluid/LavaFluidMixin.java @@ -4,8 +4,10 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.LavaFluid; +import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.GameRules; +import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraftforge.event.ForgeEventFactory; @@ -13,6 +15,10 @@ import org.bukkit.craftbukkit.v.event.CraftEventFactory; 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.Random; @@ -77,4 +83,16 @@ public abstract class LavaFluidMixin { } } + + @Inject(method = "flowInto", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/IWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) + private void arclight$returnIfFail(IWorld worldIn, BlockPos pos, BlockState blockStateIn, Direction direction, IFluidState fluidStateIn, CallbackInfo ci) { + if (!arclight$success) ci.cancel(); + } + + private transient boolean arclight$success; + + @Redirect(method = "flowInto", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/IWorld;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z")) + private boolean arclight$blockFromTo(IWorld iWorld, BlockPos pos, BlockState newState, int flags) { + return arclight$success = CraftEventFactory.handleBlockFormEvent(iWorld.getWorld(), pos, newState, flags); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/inventory/EnderChestInventoryMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/inventory/EnderChestInventoryMixin.java index d2bd2920..6b93d717 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/inventory/EnderChestInventoryMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/inventory/EnderChestInventoryMixin.java @@ -8,6 +8,8 @@ import net.minecraft.inventory.IInventory; import net.minecraft.tileentity.EnderChestTileEntity; import org.bukkit.Location; import org.bukkit.craftbukkit.v.block.CraftBlock; +import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; +import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.InventoryHolder; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -39,6 +41,13 @@ public abstract class EnderChestInventoryMixin extends InventoryMixin implements return ((PlayerEntityBridge) owner).bridge$getBukkitEntity(); } + @Override + public void setOwner(InventoryHolder owner) { + if (owner instanceof HumanEntity) { + this.owner = ((CraftHumanEntity) owner).getHandle(); + } + } + @Override public Location getLocation() { return CraftBlock.at(this.associatedChest.getWorld(), this.associatedChest.getPos()).getLocation(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java index 756979e1..c76d04ee 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/ExplosionMixin.java @@ -5,9 +5,7 @@ import com.google.common.collect.Sets; import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.world.ExplosionBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; import net.minecraft.enchantment.ProtectionEnchantment; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; @@ -16,27 +14,17 @@ import net.minecraft.entity.item.TNTEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.DamagingProjectileEntity; import net.minecraft.fluid.IFluidState; -import net.minecraft.item.ItemStack; -import net.minecraft.particles.ParticleTypes; -import net.minecraft.tileentity.TileEntity; import net.minecraft.util.DamageSource; -import net.minecraft.util.SoundCategory; -import net.minecraft.util.SoundEvents; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.Explosion; import net.minecraft.world.World; -import net.minecraft.world.server.ServerWorld; -import net.minecraft.world.storage.loot.LootContext; -import net.minecraft.world.storage.loot.LootParameters; import org.bukkit.Bukkit; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.BlockExplodeEvent; -import org.bukkit.event.block.BlockIgniteEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -51,7 +39,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; @Mixin(Explosion.class) @@ -65,8 +52,6 @@ public abstract class ExplosionMixin implements ExplosionBridge { @Shadow @Final private double x; @Shadow @Final private double y; @Shadow @Final private double z; - @Shadow @Final private boolean causesFire; - @Shadow @Final private Random random; @Shadow @Final public Entity exploder; @Shadow public abstract DamageSource getDamageSource(); @Shadow @Final private Map playerKnockbackMap; @@ -76,8 +61,6 @@ public abstract class ExplosionMixin implements ExplosionBridge { @Accessor("mode") public abstract Explosion.Mode bridge$getMode(); // @formatter:on - public boolean wasCanceled = false; - @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;DDDFZLnet/minecraft/world/Explosion$Mode;)V", at = @At("RETURN")) public void arclight$adjustSize(World worldIn, Entity exploderIn, double xIn, double yIn, double zIn, float sizeIn, boolean causesFireIn, Explosion.Mode modeIn, CallbackInfo ci) { @@ -147,13 +130,12 @@ public abstract class ExplosionMixin implements ExplosionBridge { net.minecraftforge.event.ForgeEventFactory.onExplosionDetonate(this.world, (Explosion) (Object) this, list, f3); Vec3d vec3d = new Vec3d(this.x, this.y, this.z); - for (int k2 = 0; k2 < list.size(); ++k2) { - Entity entity = list.get(k2); + for (Entity entity : list) { if (!entity.isImmuneToExplosions()) { - double d12 = MathHelper.sqrt(entity.getDistanceSq(new Vec3d(this.x, this.y, this.z))) / f3; + double d12 = MathHelper.sqrt(entity.getDistanceSq(vec3d)) / f3; if (d12 <= 1.0D) { double d5 = entity.posX - this.x; - double d7 = entity.posY + (double) entity.getEyeHeight() - this.y; + double d7 = ((EntityBridge) entity).bridge$getEyeHeight() - this.y; double d9 = entity.posZ - this.z; double d13 = MathHelper.sqrt(d5 * d5 + d7 * d7 + d9 * d9); if (d13 != 0.0D) { @@ -190,81 +172,8 @@ public abstract class ExplosionMixin implements ExplosionBridge { } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void doExplosionB(boolean spawnParticles) { - this.world.playSound(null, this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F); - boolean flag = this.mode != Explosion.Mode.NONE; - if (!(this.size < 2.0F) && flag) { - this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); - } else { - this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); - } - - if (flag) { - - float yield = arclight$callBlockExplodeEvent(); - - if (Float.isNaN(yield)) { - this.wasCanceled = true; - return; - } - - for (BlockPos blockpos : this.affectedBlockPositions) { - BlockState blockstate = this.world.getBlockState(blockpos); - Block block = blockstate.getBlock(); - if (spawnParticles) { - double d0 = ((float) blockpos.getX() + this.world.rand.nextFloat()); - double d1 = ((float) blockpos.getY() + this.world.rand.nextFloat()); - double d2 = ((float) blockpos.getZ() + this.world.rand.nextFloat()); - double d3 = d0 - this.x; - double d4 = d1 - this.y; - double d5 = d2 - this.z; - double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5); - d3 = d3 / d6; - d4 = d4 / d6; - d5 = d5 / d6; - double d7 = 0.5D / (d6 / (double) this.size + 0.1D); - d7 = d7 * (double) (this.world.rand.nextFloat() * this.world.rand.nextFloat() + 0.3F); - d3 = d3 * d7; - d4 = d4 * d7; - d5 = d5 * d7; - this.world.addParticle(ParticleTypes.POOF, (d0 + this.x) / 2.0D, (d1 + this.y) / 2.0D, (d2 + this.z) / 2.0D, d3, d4, d5); - this.world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, d3, d4, d5); - } - - if (!blockstate.isAir(this.world, blockpos)) { - if (this.world instanceof ServerWorld && blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this)) { - TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null; - LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity); - if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) { - lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield); - } - - Block.spawnDrops(blockstate, lootcontext$builder); - } - - blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this); - } - } - } - - if (this.causesFire) { - for (BlockPos blockPos : this.affectedBlockPositions) { - if (this.world.getBlockState(blockPos).isAir(world, blockPos) && this.world.getBlockState(blockPos.down()).isOpaqueCube(this.world, blockPos.down()) && this.random.nextInt(3) == 0) { - BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), (Explosion) (Object) this); - if (!event.isCancelled()) { - this.world.setBlockState(blockPos, Blocks.FIRE.getDefaultState()); - } - } - } - } - } - - private float arclight$callBlockExplodeEvent() { + @Override + public float bridge$callBlockExplodeEvent() { org.bukkit.World world = ((WorldBridge) this.world).bridge$getWorld(); org.bukkit.entity.Entity exploder = this.exploder == null ? null : ((EntityBridge) this.exploder).bridge$getBukkitEntity(); Location location = new Location(world, this.x, this.y, this.z); @@ -272,7 +181,7 @@ public abstract class ExplosionMixin implements ExplosionBridge { for (int i = this.affectedBlockPositions.size() - 1; i >= 0; i--) { BlockPos blockPos = this.affectedBlockPositions.get(i); org.bukkit.block.Block block = world.getBlockAt(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - if (block.getType() != Material.AIR && block.getType() != Material.CAVE_AIR && block.getType() != Material.VOID_AIR) { + if (!block.getType().isAir()) { blockList.add(block); } } @@ -323,9 +232,4 @@ public abstract class ExplosionMixin implements ExplosionBridge { return null; } } - - @Override - public boolean bridge$wasCancelled() { - return wasCanceled; - } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/IBlockReaderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/IBlockReaderMixin.java index 7d819e3b..baff2349 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/IBlockReaderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/IBlockReaderMixin.java @@ -26,14 +26,14 @@ public interface IBlockReaderMixin extends IBlockReaderBridge { default BlockRayTraceResult rayTraceBlock(RayTraceContext context, BlockPos pos) { BlockState blockstate = this.getBlockState(pos); IFluidState ifluidstate = this.getFluidState(pos); - Vec3d vec3d = context.func_222253_b(); - Vec3d vec3d1 = context.func_222250_a(); + Vec3d vec3d = context.getStartVec(); + Vec3d vec3d1 = context.getStartVec(); VoxelShape voxelshape = context.getBlockShape(blockstate, (IBlockReader) this, pos); BlockRayTraceResult blockraytraceresult = this.rayTraceBlocks(vec3d, vec3d1, pos, voxelshape, blockstate); VoxelShape voxelshape1 = context.getFluidShape(ifluidstate, (IBlockReader) this, pos); BlockRayTraceResult blockraytraceresult1 = voxelshape1.rayTrace(vec3d, vec3d1, pos); - double d0 = blockraytraceresult == null ? Double.MAX_VALUE : context.func_222253_b().squareDistanceTo(blockraytraceresult.getHitVec()); - double d1 = blockraytraceresult1 == null ? Double.MAX_VALUE : context.func_222253_b().squareDistanceTo(blockraytraceresult1.getHitVec()); + double d0 = blockraytraceresult == null ? Double.MAX_VALUE : context.getStartVec().squareDistanceTo(blockraytraceresult.getHitVec()); + double d1 = blockraytraceresult1 == null ? Double.MAX_VALUE : context.getStartVec().squareDistanceTo(blockraytraceresult1.getHitVec()); return d0 <= d1 ? blockraytraceresult : blockraytraceresult1; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java index 015c180d..f0acaa60 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java @@ -1,9 +1,11 @@ package io.izzel.arclight.common.mixin.core.world; import io.izzel.arclight.common.bridge.entity.EntityBridge; +import io.izzel.arclight.common.bridge.world.TeleporterBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; import io.izzel.arclight.common.mod.util.ArclightBlockPopulator; import net.minecraft.block.BlockState; +import net.minecraft.block.pattern.BlockPattern; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Teleporter; @@ -21,7 +23,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; @Mixin(Teleporter.class) -public class TeleporterMixin { +public class TeleporterMixin implements TeleporterBridge { // @formatter:off @Shadow @Final protected ServerWorld world; @@ -56,4 +58,16 @@ public class TeleporterMixin { } arclight$populator = null; } + + @Override + public boolean bridge$makePortal(Entity entityIn, BlockPos pos, int createRadius) { + // todo + return false; + } + + @Override + public BlockPattern.PortalInfo bridge$placeInPortal(Entity p_222268_1_, BlockPos pos, float p_222268_2_, int searchRadius, boolean searchOnly) { + // todo + return null; + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TrackedEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TrackedEntityMixin.java index 2c7147ef..a2fee58e 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TrackedEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TrackedEntityMixin.java @@ -3,6 +3,7 @@ package io.izzel.arclight.common.mixin.core.world; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.MobEntity; import net.minecraft.entity.ai.attributes.AttributeMap; import net.minecraft.entity.ai.attributes.IAttributeInstance; import net.minecraft.entity.item.ItemFrameEntity; @@ -20,6 +21,7 @@ import net.minecraft.network.play.server.SEntityPacket; import net.minecraft.network.play.server.SEntityPropertiesPacket; import net.minecraft.network.play.server.SEntityTeleportPacket; import net.minecraft.network.play.server.SEntityVelocityPacket; +import net.minecraft.network.play.server.SMountEntityPacket; import net.minecraft.network.play.server.SPlayEntityEffectPacket; import net.minecraft.network.play.server.SSetPassengersPacket; import net.minecraft.network.play.server.SSpawnMobPacket; @@ -29,7 +31,6 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.TrackedEntity; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.MapData; -import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerVelocityEvent; @@ -76,7 +77,6 @@ public abstract class TrackedEntityMixin { @Shadow protected abstract void sendPacket(IPacket p_219451_1_); // @formatter:on - @Shadow @Final private static Logger LOGGER; private Set trackedPlayers; @Inject(method = "", at = @At("RETURN")) @@ -136,7 +136,7 @@ public abstract class TrackedEntityMixin { ++this.ticksSinceAbsoluteTeleport; int i = MathHelper.floor(this.trackedEntity.rotationYaw * 256.0f / 360.0f); int j = MathHelper.floor(this.trackedEntity.rotationPitch * 256.0f / 360.0f); - Vec3d vec3d = new Vec3d(this.trackedEntity.posX, this.trackedEntity.posY, this.trackedEntity.posZ).subtract(SEntityPacket.func_218744_a(this.encodedPosX, this.encodedPosY, this.encodedPosZ)); + Vec3d vec3d = this.trackedEntity.getPositionVec().subtract(SEntityPacket.func_218744_a(this.encodedPosX, this.encodedPosY, this.encodedPosZ)); boolean flag2 = vec3d.lengthSquared() >= 7.62939453125E-6; IPacket packet2 = null; boolean flag3 = flag2 || this.updateCounter % 60 == 0; @@ -266,6 +266,12 @@ public abstract class TrackedEntityMixin { if (this.trackedEntity.isPassenger()) { consumer.accept(new SSetPassengersPacket(this.trackedEntity.getRidingEntity())); } + if (this.trackedEntity instanceof MobEntity) { + MobEntity mobentity = (MobEntity) this.trackedEntity; + if (mobentity.getLeashed()) { + consumer.accept(new SMountEntityPacket(mobentity, mobentity.getLeashHolder())); + } + } } @Inject(method = "sendMetadata", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/TrackedEntity;sendPacket(Lnet/minecraft/network/IPacket;)V")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/storage/ChunkLoaderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/storage/ChunkLoaderMixin.java new file mode 100644 index 00000000..f23f2867 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/storage/ChunkLoaderMixin.java @@ -0,0 +1,17 @@ +package io.izzel.arclight.common.mixin.core.world.chunk.storage; + +import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge; +import net.minecraft.world.chunk.storage.ChunkLoader; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(ChunkLoader.class) +public class ChunkLoaderMixin { + + @ModifyArg(method = "updateChunkData", index = 0, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/gen/feature/structure/LegacyStructureDataUtil;func_215130_a(Lnet/minecraft/world/dimension/DimensionType;Lnet/minecraft/world/storage/DimensionSavedDataManager;)Lnet/minecraft/world/gen/feature/structure/LegacyStructureDataUtil;")) + private DimensionType arclight$dimType(DimensionType dim) { + return ((DimensionTypeBridge) dim).bridge$getType(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/block/LilyPadBlockMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/block/LilyPadBlockMixin_1_15.java new file mode 100644 index 00000000..62153816 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/block/LilyPadBlockMixin_1_15.java @@ -0,0 +1,24 @@ +package io.izzel.arclight.common.mixin.v1_15.block; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.LilyPadBlock; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +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.callback.CallbackInfo; + +@Mixin(LilyPadBlock.class) +public class LilyPadBlockMixin_1_15 { + + @Inject(method = "onEntityCollision", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;ZLnet/minecraft/entity/Entity;)Z")) + public void arclight$entityChangeBlock(BlockState state, World worldIn, BlockPos pos, Entity entityIn, CallbackInfo ci) { + if (CraftEventFactory.callEntityChangeBlockEvent(entityIn, pos, Blocks.AIR.getDefaultState()).isCancelled()) { + ci.cancel(); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/EntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/EntityMixin_1_15.java index 54401f09..9839f914 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/EntityMixin_1_15.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/EntityMixin_1_15.java @@ -7,6 +7,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.MobEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -21,14 +22,16 @@ import net.minecraftforge.common.util.ITeleporter; import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityPortalEvent; +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 java.util.Random; @Mixin(Entity.class) -public abstract class EntityMixin_1_15 { +public abstract class EntityMixin_1_15 implements EntityBridge { // @formatter:off @Shadow public World world; @@ -47,6 +50,12 @@ public abstract class EntityMixin_1_15 { @Shadow public abstract double getPosY(); @Shadow public abstract Direction getTeleportDirection(); @Shadow public abstract EntityType getType(); + @Shadow @Final protected EntityDataManager dataManager; + @Shadow public abstract boolean isInvisible(); + @Shadow @Final protected Random rand; + @Shadow public abstract float getWidth(); + @Shadow public abstract float getHeight(); + @Shadow public abstract double getPosYEye(); // @formatter:on /** @@ -156,4 +165,9 @@ public abstract class EntityMixin_1_15 { return null; } } + + @Override + public double bridge$getEyeHeight() { + return this.getPosYEye(); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/LivingEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/LivingEntityMixin_1_15.java new file mode 100644 index 00000000..823e37f5 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/LivingEntityMixin_1_15.java @@ -0,0 +1,274 @@ +package io.izzel.arclight.common.mixin.v1_15.entity; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.item.ExperienceOrbEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.potion.Effect; +import net.minecraft.potion.EffectInstance; +import net.minecraft.util.DamageSource; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.PotionEvent; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.EntityPotionEffectEvent; +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 javax.annotation.Nullable; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin_1_15 extends EntityMixin_1_15 implements LivingEntityBridge { + + // @formatter:off + @Shadow @Final private static DataParameter POTION_EFFECTS; + @Shadow @Final private static DataParameter HIDE_PARTICLES; + @Shadow @Final public Map activePotionsMap; + @Shadow public boolean potionsNeedUpdate; + @Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect); + @Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply); + @Shadow protected abstract void updatePotionMetadata(); + @Shadow public abstract boolean removePotionEffect(Effect effectIn); + @Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn); + @Shadow protected abstract void onNewPotionEffect(EffectInstance id); + @Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin); + @Shadow public int deathTime; + @Shadow protected abstract void createWitherRose(@Nullable LivingEntity p_226298_1_); + // @formatter:on + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + protected void onDeathUpdate() { + ++this.deathTime; + if (this.deathTime >= 20 && !this.removed) { + + this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player + + for (int k = 0; k < 20; ++k) { + double d2 = this.rand.nextGaussian() * 0.02D; + double d0 = this.rand.nextGaussian() * 0.02D; + double d1 = this.rand.nextGaussian() * 0.02D; + this.world.addParticle(ParticleTypes.POOF, this.getPosX() + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.getPosY() + (double) (this.rand.nextFloat() * this.getHeight()), this.getPosZ() + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1); + } + } + } + + @Redirect(method = "spawnDrops", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;dropExperience()V")) + private void arclight$dropLater(LivingEntity livingEntity) { + } + + @Inject(method = "spawnDrops", at = @At("RETURN")) + private void arclight$dropLast(DamageSource damageSourceIn, CallbackInfo ci) { + this.dropExperience(); + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + protected void dropExperience() { + // if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) { + if (true) { + int i = bridge$getExpToDrop(); + while (i > 0) { + int j = ExperienceOrbEntity.getXPSplit(i); + i -= j; + this.world.addEntity(new ExperienceOrbEntity(this.world, this.getPosX(), this.getPosY(), this.getPosZ(), j)); + } + bridge$setExpToDrop(0); + } + } + + private boolean isTickingEffects = false; + private List, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList(); + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + protected void updatePotionEffects() { + this.isTickingEffects = true; + Iterator iterator = this.activePotionsMap.keySet().iterator(); + + try { + while (iterator.hasNext()) { + Effect effect = iterator.next(); + EffectInstance effectinstance = this.activePotionsMap.get(effect); + if (!effectinstance.tick((LivingEntity) (Object) this, () -> { + onChangedPotionEffect(effectinstance, true); + })) { + if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) { + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, EntityPotionEffectEvent.Cause.EXPIRATION); + if (event.isCancelled()) { + continue; + } + + iterator.remove(); + this.onFinishedPotionEffect(effectinstance); + } + } else if (effectinstance.getDuration() % 600 == 0) { + this.onChangedPotionEffect(effectinstance, false); + } + } + } catch (ConcurrentModificationException ignored) { + } + + isTickingEffects = false; + for (Map.Entry, EntityPotionEffectEvent.Cause> e : effectsToProcess) { + Either either = e.getKey(); + EntityPotionEffectEvent.Cause cause = e.getValue(); + bridge$pushEffectCause(cause); + if (either.left().isPresent()) { + addPotionEffect(either.left().get()); + } else { + removePotionEffect(either.right().get()); + } + } + effectsToProcess.clear(); + + if (this.potionsNeedUpdate) { + if (!this.world.isRemote) { + this.updatePotionMetadata(); + } + + this.potionsNeedUpdate = false; + } + + int i = this.dataManager.get(POTION_EFFECTS); + boolean flag1 = this.dataManager.get(HIDE_PARTICLES); + if (i > 0) { + boolean flag; + if (this.isInvisible()) { + flag = this.rand.nextInt(15) == 0; + } else { + flag = this.rand.nextBoolean(); + } + + if (flag1) { + flag &= this.rand.nextInt(5) == 0; + } + + 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.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.getPosX() + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.getPosY() + this.rand.nextDouble() * (double) this.getHeight(), this.getPosZ() + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2); + } + } + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public boolean addPotionEffect(EffectInstance effectInstanceIn) { + EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); + if (isTickingEffects) { + effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause)); + return true; + } + + if (!this.isPotionApplicable(effectInstanceIn)) { + return false; + } else { + EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion()); + + boolean override = false; + if (effectinstance != null) { + override = new EffectInstance(effectinstance).combine(effectInstanceIn); + } + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override); + if (event.isCancelled()) { + return false; + } + + MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn)); + if (effectinstance == null) { + this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn); + this.onNewPotionEffect(effectInstanceIn); + return true; + } else if (event.isOverride()) { + effectinstance.combine(effectInstanceIn); + this.onChangedPotionEffect(effectinstance, true); + return true; + } else { + return false; + } + } + } + + @SuppressWarnings("unused") // mock + public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) { + bridge$pushEffectCause(cause); + return removeActivePotionEffect(potioneffectin); + } + + @Inject(method = "removeActivePotionEffect", at = @At("HEAD")) + public void arclight$clearActive(Effect effect, CallbackInfoReturnable cir) { + EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); + if (isTickingEffects) { + effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause)); + cir.setReturnValue(null); + return; + } + + EffectInstance effectInstance = this.activePotionsMap.get(effect); + if (effectInstance == null) { + cir.setReturnValue(null); + return; + } + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause); + if (event.isCancelled()) { + cir.setReturnValue(null); + } + } + + + private transient boolean arclight$fallSuccess; + + @Inject(method = "onLivingFall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + public void arclight$fall(float distance, float damageMultiplier, CallbackInfoReturnable cir) { + if (!arclight$fallSuccess) { + cir.setReturnValue(true); + } + } + + @Redirect(method = "onLivingFall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) { + return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount); + } + + @Override + public void bridge$dropExperience() { + this.dropExperience(); + } + + @Override + public void bridge$createWitherRose(LivingEntity entity) { + this.createWitherRose(entity); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/boss/WitherEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/boss/WitherEntityMixin_1_15.java new file mode 100644 index 00000000..f4f51cba --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/boss/WitherEntityMixin_1_15.java @@ -0,0 +1,177 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.boss; + +import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityPredicate; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.boss.WitherEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.Difficulty; +import net.minecraft.world.Explosion; +import net.minecraft.world.server.ServerBossInfo; +import net.minecraftforge.event.ForgeEventFactory; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.EntityRegainHealthEvent; +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 java.util.List; + +@Mixin(WitherEntity.class) +public abstract class WitherEntityMixin_1_15 extends CreatureEntityMixin { + + // @formatter:off + @Shadow public abstract int getInvulTime(); + @Shadow public abstract void setInvulTime(int time); + @Shadow @Final private int[] nextHeadUpdate; + @Shadow @Final private int[] idleHeadUpdates; + @Shadow protected abstract void launchWitherSkullToCoords(int p_82209_1_, double x, double y, double z, boolean invulnerable); + @Shadow public abstract int getWatchedTargetId(int head); + @Shadow public abstract void updateWatchedTargetId(int targetOffset, int newId); + @Shadow protected abstract void launchWitherSkullToEntity(int p_82216_1_, LivingEntity p_82216_2_); + @Shadow @Final private static EntityPredicate field_213798_bB; + @Shadow private int blockBreakCounter; + @Shadow @Final public ServerBossInfo bossInfo; + // @formatter:on + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + protected void updateAITasks() { + if (this.getInvulTime() > 0) { + int j1 = this.getInvulTime() - 1; + if (j1 <= 0) { + Explosion.Mode explosion$mode = ForgeEventFactory.getMobGriefingEvent(this.world, (WitherEntity) (Object) this) ? Explosion.Mode.DESTROY : Explosion.Mode.NONE; + ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + this.world.createExplosion((WitherEntity) (Object) this, this.posX, this.bridge$getEyeHeight(), this.posZ, event.getRadius(), event.getFire(), explosion$mode); + } + this.world.playBroadcastSound(1023, new BlockPos((WitherEntity) (Object) this), 0); + } + + this.setInvulTime(j1); + if (this.ticksExisted % 10 == 0) { + bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); + this.heal(10.0F); + } + + } else { + super.updateAITasks(); + + for (int i = 1; i < 3; ++i) { + if (this.ticksExisted >= this.nextHeadUpdate[i - 1]) { + this.nextHeadUpdate[i - 1] = this.ticksExisted + 10 + this.rand.nextInt(10); + if (this.world.getDifficulty() == Difficulty.NORMAL || this.world.getDifficulty() == Difficulty.HARD) { + int j3 = i - 1; + int k3 = this.idleHeadUpdates[i - 1]; + this.idleHeadUpdates[j3] = this.idleHeadUpdates[i - 1] + 1; + if (k3 > 15) { + float f = 10.0F; + float f1 = 5.0F; + double d0 = MathHelper.nextDouble(this.rand, this.posX - 10.0D, this.posX + 10.0D); + double d1 = MathHelper.nextDouble(this.rand, this.posY - 5.0D, this.posY + 5.0D); + double d2 = MathHelper.nextDouble(this.rand, this.posZ - 10.0D, this.posZ + 10.0D); + this.launchWitherSkullToCoords(i + 1, d0, d1, d2, true); + this.idleHeadUpdates[i - 1] = 0; + } + } + + int k1 = this.getWatchedTargetId(i); + if (k1 > 0) { + Entity entity = this.world.getEntityByID(k1); + if (entity != null && entity.isAlive() && !(this.getDistanceSq(entity) > 900.0D) && this.canEntityBeSeen(entity)) { + if (entity instanceof PlayerEntity && ((PlayerEntity) entity).abilities.disableDamage) { + this.updateWatchedTargetId(i, 0); + } else { + this.launchWitherSkullToEntity(i + 1, (LivingEntity) entity); + this.nextHeadUpdate[i - 1] = this.ticksExisted + 40 + this.rand.nextInt(20); + this.idleHeadUpdates[i - 1] = 0; + } + } else { + this.updateWatchedTargetId(i, 0); + } + } else { + List list = this.world.getTargettableEntitiesWithinAABB(LivingEntity.class, field_213798_bB, (WitherEntity) (Object) this, this.getBoundingBox().grow(20.0D, 8.0D, 20.0D)); + + for (int j2 = 0; j2 < 10 && !list.isEmpty(); ++j2) { + LivingEntity livingentity = list.get(this.rand.nextInt(list.size())); + if (livingentity != (Object) this && livingentity.isAlive() && this.canEntityBeSeen(livingentity)) { + if (livingentity instanceof PlayerEntity) { + if (!((PlayerEntity) livingentity).abilities.disableDamage) { + if (CraftEventFactory.callEntityTargetLivingEvent((WitherEntity) (Object) this, livingentity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) + continue; + this.updateWatchedTargetId(i, livingentity.getEntityId()); + } + } else { + if (CraftEventFactory.callEntityTargetLivingEvent((WitherEntity) (Object) this, livingentity, EntityTargetEvent.TargetReason.CLOSEST_ENTITY).isCancelled()) + continue; + this.updateWatchedTargetId(i, livingentity.getEntityId()); + } + break; + } + + list.remove(livingentity); + } + } + } + } + + if (this.getAttackTarget() != null) { + this.updateWatchedTargetId(0, this.getAttackTarget().getEntityId()); + } else { + this.updateWatchedTargetId(0, 0); + } + + if (this.blockBreakCounter > 0) { + --this.blockBreakCounter; + if (this.blockBreakCounter == 0 && ForgeEventFactory.getMobGriefingEvent(this.world, (WitherEntity) (Object) this)) { + int i1 = MathHelper.floor(this.posY); + int l1 = MathHelper.floor(this.posX); + int i2 = MathHelper.floor(this.posZ); + boolean flag = false; + + for (int k2 = -1; k2 <= 1; ++k2) { + for (int l2 = -1; l2 <= 1; ++l2) { + for (int j = 0; j <= 3; ++j) { + int i3 = l1 + k2; + int k = i1 + j; + int l = i2 + l2; + BlockPos blockpos = new BlockPos(i3, k, l); + BlockState blockstate = this.world.getBlockState(blockpos); + if (blockstate.canEntityDestroy(this.world, blockpos, (WitherEntity) (Object) this) && ForgeEventFactory.onEntityDestroyBlock((WitherEntity) (Object) this, blockpos, blockstate)) { + if (CraftEventFactory.callEntityChangeBlockEvent((WitherEntity) (Object) this, blockpos, Blocks.AIR.getDefaultState()).isCancelled()) { + continue; + } + flag = this.world.destroyBlock(blockpos, true, (WitherEntity) (Object) this) || flag; + } + } + } + } + + if (flag) { + this.world.playEvent(null, 1022, new BlockPos((WitherEntity) (Object) this), 0); + } + } + } + + if (this.ticksExisted % 20 == 0) { + bridge$pushHealReason(EntityRegainHealthEvent.RegainReason.REGEN); + this.heal(1.0F); + } + + this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/item/ItemEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/item/ItemEntityMixin_1_15.java new file mode 100644 index 00000000..1cfd4465 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/item/ItemEntityMixin_1_15.java @@ -0,0 +1,18 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.item; + +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ItemEntity.class) +public class ItemEntityMixin_1_15 { + + @Redirect(method = "func_226531_a_", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V")) + private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) { + if (!stack.isEmpty()) { + itemEntity.setItem(stack); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/AbstractRaiderEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/AbstractRaiderEntityMixin.java new file mode 100644 index 00000000..531bfe47 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/AbstractRaiderEntityMixin.java @@ -0,0 +1,24 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.monster; + +import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.AbstractRaiderEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.DamageSource; +import net.minecraft.world.raid.Raid; +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 org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +@Mixin(AbstractRaiderEntity.class) +public class AbstractRaiderEntityMixin { + + @Inject(method = "onDeath", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;addPotionEffect(Lnet/minecraft/potion/EffectInstance;)Z")) + private void arclight$raid(DamageSource cause, CallbackInfo ci, Entity entity, Raid raid, ItemStack itemStack, PlayerEntity playerEntity) { + ((PlayerEntityBridge) playerEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.PATROL_CAPTAIN); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/RavagerEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/RavagerEntityMixin_1_15.java new file mode 100644 index 00000000..01c77636 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/RavagerEntityMixin_1_15.java @@ -0,0 +1,22 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.monster; + +import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.RavagerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +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(RavagerEntity.class) +public abstract class RavagerEntityMixin_1_15 extends CreatureEntityMixin { + + @Redirect(method = "livingTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;ZLnet/minecraft/entity/Entity;)Z")) + private boolean arclight$entityChangeBlock(World world, BlockPos pos, boolean p_225521_2_, Entity entityIn) { + return !CraftEventFactory.callEntityChangeBlockEvent((RavagerEntity) (Object) this, pos, Blocks.AIR.getDefaultState()).isCancelled() + && world.destroyBlock(pos, p_225521_2_, entityIn); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ShulkerEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ShulkerEntityMixin_1_15.java new file mode 100644 index 00000000..b0195618 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ShulkerEntityMixin_1_15.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.monster; + +import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; +import net.minecraft.entity.monster.ShulkerEntity; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.world.server.ServerWorld; +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(ShulkerEntity.class) +public abstract class ShulkerEntityMixin_1_15 extends CreatureEntityMixin { + + @Inject(method = "notifyDataManagerChange", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/monster/ShulkerEntity;forceSetPosition(DDD)V")) + private void arclight$chunkCheck(DataParameter key, CallbackInfo ci) { + if (valid) ((ServerWorld) this.world).chunkCheck((ShulkerEntity) (Object) this); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ZombiePigmanEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ZombiePigmanEntityMixin_1_15.java new file mode 100644 index 00000000..6b284ac4 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/monster/ZombiePigmanEntityMixin_1_15.java @@ -0,0 +1,57 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.monster; + +import io.izzel.arclight.common.bridge.entity.EntityBridge; +import io.izzel.arclight.common.mixin.core.entity.monster.ZombieEntityMixin; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.monster.ZombiePigmanEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.DamageSource; +import org.bukkit.Bukkit; +import org.bukkit.entity.PigZombie; +import org.bukkit.event.entity.PigZombieAngerEvent; +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(ZombiePigmanEntity.class) +public abstract class ZombiePigmanEntityMixin_1_15 extends ZombieEntityMixin { + + // @formatter:off + @Shadow protected abstract boolean func_226547_i_(LivingEntity p_70835_1_); + @Shadow protected abstract int func_223336_ef(); + // @formatter:on + + public boolean attackEntityFrom(DamageSource damagesource, float f) { + if (this.isInvulnerableTo(damagesource)) { + return false; + } + Entity entity = damagesource.getTrueSource(); + boolean result = super.attackEntityFrom(damagesource, f); + if (result && entity instanceof PlayerEntity && !((PlayerEntity) entity).isCreative() && this.canEntityBeSeen(entity)) { + this.func_226547_i_((LivingEntity) entity); + } + return result; + } + + @Inject(method = "func_226547_i_", cancellable = true, at = @At("HEAD")) + private void arclight$anger(LivingEntity entity, CallbackInfoReturnable cir) { + PigZombieAngerEvent event = new PigZombieAngerEvent((PigZombie) this.getBukkitEntity(), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), this.func_223336_ef()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + cir.setReturnValue(false); + } else { + arclight$capture = event.getNewAnger(); + } + } + + private transient int arclight$capture; + + @Redirect(method = "func_226547_i_", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombiePigmanEntity;func_223336_ef()I")) + private int arclight$useAnger(ZombiePigmanEntity pigmanEntity) { + return arclight$capture; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/PlayerEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/PlayerEntityMixin_1_15.java new file mode 100644 index 00000000..3a443adb --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/PlayerEntityMixin_1_15.java @@ -0,0 +1,145 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.player; + +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; +import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin; +import net.minecraft.entity.player.PlayerAbilities; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Unit; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.server.ServerWorld; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v.block.CraftBlock; +import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerBedLeaveEvent; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerEntity.class) +public abstract class PlayerEntityMixin_1_15 extends LivingEntityMixin implements PlayerEntityBridge { + + // @formatter:off + @Shadow public abstract Either trySleep(BlockPos at); + @Shadow public abstract void startSleeping(BlockPos p_213342_1_); + @Shadow public int sleepTimer; + @Shadow @Final public PlayerAbilities abilities; + // @formatter:on + + @Shadow + public abstract void addStat(ResourceLocation stat); + + @Override + public CraftHumanEntity bridge$getBukkitEntity() { + return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity(); + } + + private boolean arclight$forceSleep = false; + private Object arclight$processSleep = null; + + private Either getBedResult(BlockPos at, Direction direction) { + arclight$processSleep = true; + Either either = this.trySleep(at); + arclight$processSleep = null; + return either; + } + + public Either sleep(BlockPos at, boolean force) { + arclight$forceSleep = force; + try { + return this.trySleep(at); + } finally { + arclight$forceSleep = false; + } + } + + @Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD")) + public void arclight$onSleep(BlockPos at, CallbackInfoReturnable> cir) { + if (arclight$processSleep == null) { + Either result = getBedResult(at, null); + + if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) { + cir.setReturnValue(result); + return; + } + if (arclight$forceSleep) { + result = Either.right(Unit.INSTANCE); + } + if (this.bridge$getBukkitEntity() instanceof Player) { + result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result); + if (result.left().isPresent()) { + cir.setReturnValue(result); + return; + } + } + + this.startSleeping(at); + this.sleepTimer = 0; + if (this.world instanceof ServerWorld) { + ((ServerWorld) this.world).updateAllPlayersSleepingFlag(); + } + cir.setReturnValue(Either.right(Unit.INSTANCE)); + } + } + + @Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V")) + public void arclight$preSleep(BlockPos at, CallbackInfoReturnable> cir) { + if (arclight$processSleep != null) { + cir.setReturnValue(Either.right(Unit.INSTANCE)); + } + } + + @Inject(method = "stopSleepInBed", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I")) + private void arclight$wakeup(boolean flag, boolean flag1, CallbackInfo ci) { + BlockPos blockPos = this.getBedPosition().orElse(null); + if (this.getBukkitEntity() instanceof Player) { + Player player = (Player) this.getBukkitEntity(); + Block bed; + if (blockPos != null) { + bed = CraftBlock.at(this.world, blockPos); + } else { + bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation()); + } + PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, true); + Bukkit.getPluginManager().callEvent(event); + } + } + + @Inject(method = "setSpawnPoint", remap = false, at = @At("RETURN")) + private void arclight$updateSpawnpoint(BlockPos pos, boolean p_226560_2_, boolean p_226560_3_, DimensionType dim, CallbackInfo ci) { + bridge$setSpawnWorld(pos == null ? "" : this.world.worldInfo.getWorldName()); + } + + @Inject(method = "startFallFlying", cancellable = true, at = @At("HEAD")) + private void arclight$startGlidingEvent(CallbackInfo ci) { + if (CraftEventFactory.callToggleGlideEvent((PlayerEntity) (Object) this, true).isCancelled()) { + this.setFlag(7, true); + this.setFlag(7, false); + ci.cancel(); + } + } + + @Inject(method = "stopFallFlying", cancellable = true, at = @At("HEAD")) + private void arclight$stopGlidingEvent(CallbackInfo ci) { + if (CraftEventFactory.callToggleGlideEvent((PlayerEntity) (Object) this, false).isCancelled()) { + ci.cancel(); + } + } + + @Override + public Either bridge$trySleep(BlockPos at, boolean force) { + return sleep(at, force); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/ServerPlayerEntityMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/ServerPlayerEntityMixin_1_15.java new file mode 100644 index 00000000..75ad8754 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/entity/player/ServerPlayerEntityMixin_1_15.java @@ -0,0 +1,326 @@ +package io.izzel.arclight.common.mixin.v1_15.entity.player; + +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; +import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.network.play.ServerPlayNetHandlerBridge; +import io.izzel.arclight.common.bridge.world.TeleporterBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge; +import io.izzel.arclight.common.bridge.world.server.ServerWorldBridge; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.block.Blocks; +import net.minecraft.block.pattern.BlockPattern; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.play.ServerPlayNetHandler; +import net.minecraft.network.play.server.SChangeGameStatePacket; +import net.minecraft.network.play.server.SPlayEntityEffectPacket; +import net.minecraft.network.play.server.SPlaySoundEventPacket; +import net.minecraft.network.play.server.SPlayerAbilitiesPacket; +import net.minecraft.network.play.server.SRespawnPacket; +import net.minecraft.network.play.server.SServerDifficultyPacket; +import net.minecraft.potion.EffectInstance; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.PlayerInteractionManager; +import net.minecraft.server.management.PlayerList; +import net.minecraft.stats.Stats; +import net.minecraft.util.Unit; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.Teleporter; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.WorldInfo; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.util.ITeleporter; +import net.minecraftforge.fml.hooks.BasicEventHooks; +import net.minecraftforge.fml.network.NetworkHooks; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.v.CraftWorld; +import org.bukkit.craftbukkit.v.entity.CraftPlayer; +import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.world.PortalCreateEvent; +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.List; + +@Mixin(ServerPlayerEntity.class) +public abstract class ServerPlayerEntityMixin_1_15 extends PlayerEntityMixin_1_15 implements ServerPlayerEntityBridge { + + // @formatter:off + @Shadow public boolean invulnerableDimensionChange; + @Shadow public abstract ServerWorld getServerWorld(); + @Shadow public boolean queuedEndExit; + @Shadow public ServerPlayNetHandler connection; + @Shadow private boolean seenCredits; + @Shadow @Final public MinecraftServer server; + @Shadow @Final public PlayerInteractionManager interactionManager; + @Shadow @Nullable private Vec3d enteredNetherPosition; + @Shadow public abstract void func_213846_b(ServerWorld p_213846_1_); + @Shadow public int lastExperience; + @Shadow private float lastHealth; + @Shadow private int lastFoodLevel; + // @formatter:on + + @Override + public CraftPlayer bridge$getBukkitEntity() { + return (CraftPlayer) ((InternalEntityBridge) this).internal$getBukkitEntity(); + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + @Nullable + public Entity changeDimension(DimensionType dim, ITeleporter teleporter) { + final DimensionType[] destination = {dim}; + if (this.isSleeping()) return (ServerPlayerEntity) (Object) this; + + if (!ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, destination[0])) return null; + + PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN); + // this.invulnerableDimensionChange = true; + DimensionType dimensiontype = this.dimension; + if (((DimensionTypeBridge) dimensiontype).bridge$getType() == DimensionType.THE_END && ((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.OVERWORLD && teleporter instanceof Teleporter) { //Forge: Fix non-vanilla teleporters triggering end credits + this.invulnerableDimensionChange = true; + this.detach(); + this.getServerWorld().removePlayer((ServerPlayerEntity) (Object) this, true); //Forge: The player entity is cloned so keep the data until after cloning calls copyFrom + if (!this.queuedEndExit) { + this.queuedEndExit = true; + this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0F : 1.0F)); + this.seenCredits = true; + } + + return (ServerPlayerEntity) (Object) this; + } else { + ServerWorld serverworld = this.server.getWorld(dimensiontype); + // this.dimension = destination; + final ServerWorld[] serverworld1 = {this.server.getWorld(destination[0])}; + + /* + WorldInfo worldinfo = serverworld1.getWorldInfo(); + NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this); + this.connection.sendPacket(new SRespawnPacket(destination, WorldInfo.byHashing(worldinfo.getSeed()), worldinfo.getGenerator(), this.interactionManager.getGameType())); + this.connection.sendPacket(new SServerDifficultyPacket(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked())); + PlayerList playerlist = this.server.getPlayerList(); + playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this); + serverworld.removeEntity((ServerPlayerEntity) (Object) this, true); //Forge: the player entity is moved to the new world, NOT cloned. So keep the data alive with no matching invalidate call. + this.revive(); + */ + final PlayerList[] playerlist = new PlayerList[1]; + + Entity e = teleporter.placeEntity((ServerPlayerEntity) (Object) this, serverworld, serverworld1[0], this.rotationYaw, spawnPortal -> {//Forge: Start vanilla logic + double d0 = this.getPosX(); + double d1 = this.getPosY(); + double d2 = this.getPosZ(); + float f = this.rotationPitch; + float f1 = this.rotationYaw; + double d3 = 8.0D; + float f2 = f1; + serverworld.getProfiler().startSection("moving"); + + if (serverworld1[0] != null) { + double moveFactor = serverworld.getDimension().getMovementFactor() / serverworld1[0].getDimension().getMovementFactor(); + d0 *= moveFactor; + d2 *= moveFactor; + if (dimensiontype == DimensionType.OVERWORLD && destination[0] == DimensionType.THE_NETHER) { + this.enteredNetherPosition = this.getPositionVec(); + } else if (dimensiontype == DimensionType.OVERWORLD && destination[0] == DimensionType.THE_END) { + BlockPos blockpos = serverworld1[0].getSpawnCoordinate(); + d0 = blockpos.getX(); + d1 = blockpos.getY(); + d2 = blockpos.getZ(); + f1 = 90.0F; + f = 0.0F; + } + } + + Location enter = this.getBukkitEntity().getLocation(); + Location exit = (serverworld1[0] == null) ? null : new Location(((ServerWorldBridge) serverworld1[0]).bridge$getWorld(), d0, d1, d2, f1, f); + PlayerPortalEvent event = new PlayerPortalEvent((Player) this.getBukkitEntity(), enter, exit, cause, 128, true, ((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.THE_END ? 0 : 16); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null) { + return null; + } + + exit = event.getTo(); + if (exit == null) { + return null; + } + serverworld1[0] = ((CraftWorld) exit.getWorld()).getHandle(); + d0 = exit.getX(); + d1 = exit.getY(); + d2 = exit.getZ(); + + // this.setLocationAndAngles(d0, d1, d2, f1, f); + serverworld.getProfiler().endSection(); + serverworld.getProfiler().startSection("placing"); + double d7 = Math.max(-2.9999872E7D, serverworld1[0].getWorldBorder().minX() + 16.0D); + double d4 = Math.max(-2.9999872E7D, serverworld1[0].getWorldBorder().minZ() + 16.0D); + double d5 = Math.min(2.9999872E7D, serverworld1[0].getWorldBorder().maxX() - 16.0D); + double d6 = Math.min(2.9999872E7D, serverworld1[0].getWorldBorder().maxZ() - 16.0D); + d0 = MathHelper.clamp(d0, d7, d5); + d2 = MathHelper.clamp(d2, d4, d6); + // this.setLocationAndAngles(d0, d1, d2, f1, f); + + Vec3d exitVelocity = Vec3d.ZERO; + BlockPos exitPosition = new BlockPos(d0, d1, d2); + + if (((DimensionTypeBridge) destination[0]).bridge$getType() == DimensionType.THE_END) { + int i = exitPosition.getX(); + int j = exitPosition.getY() - 1; + int k = exitPosition.getZ(); + + if (event.getCanCreatePortal()) { + + BlockStateListPopulator blockList = new BlockStateListPopulator(serverworld1[0]); + + for (int j1 = -2; j1 <= 2; ++j1) { + for (int k1 = -2; k1 <= 2; ++k1) { + for (int l1 = -1; l1 < 3; ++l1) { + int i2 = i + k1 * 1 + j1 * 0; + int j2 = j + l1; + int k2 = k + k1 * 0 - j1 * 1; + boolean flag = l1 < 0; + blockList.setBlockState(new BlockPos(i2, j2, k2), flag ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3); + } + } + } + + org.bukkit.World bworld = ((ServerWorldBridge) serverworld1[0]).bridge$getWorld(); + PortalCreateEvent portalEvent = new PortalCreateEvent((List) (List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM); + + Bukkit.getPluginManager().callEvent(portalEvent); + if (!portalEvent.isCancelled()) { + blockList.updateList(); + } + } + + // this.setLocationAndAngles(i, j, k, f1, 0.0F); + exit.setX(i); + exit.setY(j); + exit.setZ(k); + // this.setMotion(Vec3d.ZERO); + exitVelocity = Vec3d.ZERO; + } else { + BlockPattern.PortalInfo portalInfo = ((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$placeInPortal((ServerPlayerEntity) (Object) this, exitPosition, f2, event.getSearchRadius(), true); + if (spawnPortal && portalInfo == null && event.getCanCreatePortal()) { + if (((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$makePortal((ServerPlayerEntity) (Object) this, exitPosition, event.getCreationRadius())) { + // serverworld1.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f2); + portalInfo = ((TeleporterBridge) serverworld1[0].getDefaultTeleporter()).bridge$placeInPortal((ServerPlayerEntity) (Object) this, exitPosition, f2, event.getSearchRadius(), true); + } + } + if (portalInfo == null) { + return null; + } + + exitVelocity = portalInfo.motion; + exit.setX(portalInfo.pos.getX()); + exit.setY(portalInfo.pos.getY()); + exit.setZ(portalInfo.pos.getZ()); + exit.setYaw(f2 + (float) portalInfo.rotation); + } + + serverworld.getProfiler().endSection(); + + final PlayerTeleportEvent tpEvent = new PlayerTeleportEvent((Player) this.getBukkitEntity(), enter, exit, cause); + Bukkit.getServer().getPluginManager().callEvent(tpEvent); + if (tpEvent.isCancelled() || tpEvent.getTo() == null) { + return null; + } + exit = tpEvent.getTo(); + if (exit == null) { + return null; + } + serverworld1[0] = ((CraftWorld) exit.getWorld()).getHandle(); + this.invulnerableDimensionChange = true; + + destination[0] = serverworld1[0].getDimension().getType(); + this.dimension = destination[0]; + + WorldInfo worldinfo = serverworld1[0].getWorldInfo(); + NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this); + this.connection.sendPacket(new SRespawnPacket(destination[0], WorldInfo.byHashing(worldinfo.getSeed()), worldinfo.getGenerator(), this.interactionManager.getGameType())); + this.connection.sendPacket(new SServerDifficultyPacket(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked())); + + playerlist[0] = this.server.getPlayerList(); + playerlist[0].updatePermissionLevel((ServerPlayerEntity) (Object) this); + + serverworld.removeEntity((ServerPlayerEntity) (Object) this, true); //Forge: the player entity is moved to the new world, NOT cloned. So keep the data alive with no matching invalidate call. + this.revive(); + + this.setMotion(exitVelocity); + + this.setWorld(serverworld1[0]); + serverworld1[0].addDuringPortalTeleport((ServerPlayerEntity) (Object) this); + this.func_213846_b(serverworld); + + // this.connection.setPlayerLocation(this.getPosX(), this.getPosY(), this.getPosZ(), f1, f); + ((ServerPlayNetHandlerBridge) this.connection).bridge$teleport(exit); + this.connection.captureCurrentPosition(); + + return (ServerPlayerEntity) (Object) this;//forge: this is part of the ITeleporter patch + });//Forge: End vanilla logic + 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.interactionManager.setWorld(serverworld1[0]); + this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities)); + playerlist[0].sendWorldInfo((ServerPlayerEntity) (Object) this, serverworld1[0]); + playerlist[0].sendInventory((ServerPlayerEntity) (Object) this); + + for (EffectInstance effectinstance : this.getActivePotionEffects()) { + this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), effectinstance)); + } + + this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false)); + this.lastExperience = -1; + this.lastHealth = -1.0F; + this.lastFoodLevel = -1; + BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensiontype, destination[0]); + + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent((Player) this.getBukkitEntity(), ((WorldBridge) serverworld).bridge$getWorld()); + Bukkit.getPluginManager().callEvent(changeEvent); + return (ServerPlayerEntity) (Object) this; + } + } + + public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) { + bridge$pushChangeDimensionCause(cause); + return this.changeDimension(dimensionmanager); + } + + @Override + public Either sleep(BlockPos at, boolean force) { + return super.sleep(at, force).ifRight((p_213849_1_) -> { + this.addStat(Stats.SLEEP_IN_BED); + CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this); + }); + } + + @Inject(method = "stopSleepInBed", cancellable = true, at = @At("HEAD")) + private void arclight$notWake(boolean flag, boolean flag1, CallbackInfo ci) { + if (!isSleeping()) ci.cancel(); + } + + @Override + public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) { + return a(dimensionType, cause); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/item/crafting/SpecialRecipeMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/item/crafting/SpecialRecipeMixin.java new file mode 100644 index 00000000..d9bc8f9c --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/item/crafting/SpecialRecipeMixin.java @@ -0,0 +1,15 @@ +package io.izzel.arclight.common.mixin.v1_15.item.crafting; + +import io.izzel.arclight.common.bridge.item.crafting.IRecipeBridge; +import net.minecraft.item.crafting.SpecialRecipe; +import org.bukkit.inventory.Recipe; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(SpecialRecipe.class) +public class SpecialRecipeMixin implements IRecipeBridge { + + @Override + public Recipe bridge$toBukkitRecipe() { + return new org.bukkit.craftbukkit.v.inventory.CraftComplexRecipe((SpecialRecipe) (Object) this); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/ExplosionMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/ExplosionMixin_1_15.java new file mode 100644 index 00000000..c561698d --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/ExplosionMixin_1_15.java @@ -0,0 +1,139 @@ +package io.izzel.arclight.common.mixin.v1_15.world; + +import com.mojang.datafixers.util.Pair; +import io.izzel.arclight.common.bridge.world.ExplosionBridge; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.loot.LootContext; +import net.minecraft.world.storage.loot.LootParameters; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.block.BlockIgniteEvent; +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.callback.CallbackInfo; + +import java.util.Collections; +import java.util.List; +import java.util.Random; + +@Mixin(Explosion.class) +public abstract class ExplosionMixin_1_15 implements ExplosionBridge { + + // @formatter:off + @Shadow @Final private World world; + @Shadow @Final private Explosion.Mode mode; + @Shadow @Mutable @Final private float size; + @Shadow @Final private List affectedBlockPositions; + @Shadow @Final private double x; + @Shadow @Final private double y; + @Shadow @Final private double z; + @Shadow @Final private boolean causesFire; + @Shadow @Final private Random random; + @Shadow @Final public Entity exploder; + @Shadow private static void func_229976_a_(ObjectArrayList> p_229976_0_, ItemStack p_229976_1_, BlockPos p_229976_2_) { } + @Accessor("exploder") public abstract Entity bridge$getExploder(); + @Accessor("size") public abstract float bridge$getSize(); + @Accessor("size") public abstract void bridge$setSize(float size); + @Accessor("mode") public abstract Explosion.Mode bridge$getMode(); + // @formatter:on + + public boolean wasCanceled = false; + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void doExplosionB(boolean spawnParticles) { + if (this.world.isRemote) { + this.world.playSound(this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F, false); + } + + boolean flag = this.mode != Explosion.Mode.NONE; + if (spawnParticles) { + if (!(this.size < 2.0F) && flag) { + this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } else { + this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } + } + + if (flag) { + ObjectArrayList> objectarraylist = new ObjectArrayList<>(); + Collections.shuffle(this.affectedBlockPositions, this.world.rand); + + float yield = this.bridge$callBlockExplodeEvent(); + + if (Float.isNaN(yield)) { + this.wasCanceled = true; + return; + } + + for (BlockPos blockpos : this.affectedBlockPositions) { + BlockState blockstate = this.world.getBlockState(blockpos); + Block block = blockstate.getBlock(); + if (!blockstate.isAir(this.world, blockpos)) { + BlockPos blockpos1 = blockpos.toImmutable(); + this.world.getProfiler().startSection("explosion_blocks"); + if (blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this) && this.world instanceof ServerWorld) { + TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null; + LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity).withNullableParameter(LootParameters.THIS_ENTITY, this.exploder); + if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) { + lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield); + } + + blockstate.getDrops(lootcontext$builder).forEach((p_229977_2_) -> { + func_229976_a_(objectarraylist, p_229977_2_, blockpos1); + }); + } + + blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this); + this.world.getProfiler().endSection(); + } + } + + for (Pair pair : objectarraylist) { + Block.spawnAsEntity(this.world, pair.getSecond(), pair.getFirst()); + } + } + + if (this.causesFire) { + for (BlockPos blockpos2 : this.affectedBlockPositions) { + if (this.random.nextInt(3) == 0 && this.world.getBlockState(blockpos2).isAir() && this.world.getBlockState(blockpos2.down()).isOpaqueCube(this.world, blockpos2.down())) { + BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockpos2.getX(), blockpos2.getY(), blockpos2.getZ(), (Explosion) (Object) this); + if (!event.isCancelled()) { + this.world.setBlockState(blockpos2, Blocks.FIRE.getDefaultState()); + } + } + } + } + } + + @Inject(method = "func_229976_a_", cancellable = true, at = @At("HEAD")) + private static void arclight$fix(ObjectArrayList> p_229976_0_, ItemStack stack, BlockPos p_229976_2_, CallbackInfo ci) { + if (stack.isEmpty()) ci.cancel(); + } + + @Override + public boolean bridge$wasCancelled() { + return wasCanceled; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/dimension/DimensionTypeMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/dimension/DimensionTypeMixin_1_15.java index e93447b8..649ac136 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/dimension/DimensionTypeMixin_1_15.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/dimension/DimensionTypeMixin_1_15.java @@ -1,5 +1,6 @@ package io.izzel.arclight.common.mixin.v1_15.world.dimension; +import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge; import net.minecraft.world.World; import net.minecraft.world.biome.IBiomeMagnifier; import net.minecraft.world.dimension.Dimension; @@ -9,7 +10,7 @@ import org.spongepowered.asm.mixin.Mixin; import java.util.function.BiFunction; @Mixin(DimensionType.class) -public class DimensionTypeMixin_1_15 { +public class DimensionTypeMixin_1_15 implements DimensionTypeBridge { protected void arclight$constructor(int idIn, String suffixIn, String directoryIn, BiFunction p_i49935_4_, boolean p_i49935_5_, IBiomeMagnifier p_i225789_6_) { throw new RuntimeException(); @@ -25,4 +26,9 @@ public class DimensionTypeMixin_1_15 { public DimensionType getType() { return (type == null) ? (DimensionType) (Object) this : type; } + + @Override + public DimensionType bridge$getType() { + return getType(); + } } diff --git a/arclight-common/src/main/resources/mixins.arclight.core.1_15.json b/arclight-common/src/main/resources/mixins.arclight.core.1_15.json index 8fe01316..183261ef 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.1_15.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.1_15.json @@ -28,6 +28,7 @@ "block.KelpTopBlockMixin_1_15", "block.LeavesBlockMixin_1_15", "block.LeverBlockMixin_1_15", + "block.LilyPadBlockMixin_1_15", "block.MushroomBlockMixin_1_15", "block.NetherPortalBlockMixin_1_15", "block.NetherWartBlockMixin_1_15", @@ -49,10 +50,20 @@ "command.impl.TimeCommandMixin", "enchantment.FrostWalkerEnchantmentMixin_1_15", "entity.EntityMixin_1_15", + "entity.LivingEntityMixin_1_15", + "entity.boss.WitherEntityMixin_1_15", "entity.item.ArmorStandEntityMixin_1_15", + "entity.item.ItemEntityMixin_1_15", + "entity.monster.AbstractRaiderEntityMixin", + "entity.monster.RavagerEntityMixin_1_15", + "entity.monster.ShulkerEntityMixin_1_15", "entity.passive.BeeEntity_AngerGoalMixin", "entity.passive.BeeEntity_FindPollinationTargetGoalMixin", "entity.passive.BeeEntityMixin", + "entity.player.PlayerEntityMixin_1_15", + "entity.player.ServerPlayerEntityMixin_1_15", + "item.crafting.SpecialRecipeMixin", + "world.ExplosionMixin_1_15", "world.biome.BiomeContainerMixin", "world.chunk.ChunkMixin_1_15", "world.dimension.DimensionTypeMixin_1_15", diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index 0f5323b5..42d63204 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -48,7 +48,6 @@ "block.IceBlockMixin", "block.JukeBoxBlockMixin", "block.LecternBlockMixin", - "block.LilyPadBlockMixin", "block.MagmaBlockMixin", "block.NetherPortalBlock_SizeMixin", "block.NetherPortalBlockMixin", @@ -79,9 +78,7 @@ "command.arguments.EntitySelectorParserMixin", "command.impl.EffectCommandMixin", "command.impl.SummonCommandMixin", - "command.impl.TeleportCommandMixin", "enchantment.DamageEnchantmentMixin", - "enchantment.FrostWalkerEnchantmentMixin", "entity.AgeableEntityMixin", "entity.AreaEffectCloudEntityMixin", "entity.CreatureEntityMixin", @@ -109,7 +106,6 @@ "entity.ai.goal.TargetGoalMixin", "entity.ai.goal.TemptGoalMixin", "entity.ai.goal.TriggerSkeletonTrapGoalMixin", - "entity.boss.WitherEntityMixin", "entity.boss.dragon.EnderDragonEntityMixin", "entity.boss.dragon.phase.PhaseManagerMixin", "entity.effect.LightningBoltEntityMixin", @@ -147,9 +143,6 @@ "entity.monster.IllusionerEntity_BlindnessSpellGoalMixin", "entity.monster.IllusionerEntity_MirrorSpellGoalMixin", "entity.monster.PhantomEntity_AttackPlayerGoalMixin", - "entity.monster.PillagerEntityMixin", - "entity.monster.RavagerEntityMixin", - "entity.monster.ShulkerEntityMixin", "entity.monster.SilverfishEntity_HideInStoneGoalMixin", "entity.monster.SilverfishEntity_SummonSilverfishGoalMixin", "entity.monster.SlimeEntityMixin", @@ -175,7 +168,6 @@ "entity.passive.IronGolemEntityMixin", "entity.passive.MooshroomEntityMixin", "entity.passive.OcelotEntityMixin", - "entity.passive.PandaEntity_MateGoalMixin", "entity.passive.PandaEntity_RevengeGoalMixin", "entity.passive.PandaEntityMixin", "entity.passive.ParrotEntityMixin", @@ -206,6 +198,7 @@ "entity.projectile.FishingBobberEntityMixin", "entity.projectile.LlamaSpitEntityMixin", "entity.projectile.PotionEntityMixin", + "entity.projectile.ProjectileItemEntityMixin", "entity.projectile.ShulkerBulletEntityMixin", "entity.projectile.SmallFireballEntityMixin", "entity.projectile.SpectralArrowEntityMixin", @@ -344,9 +337,9 @@ "world.TrackedEntityMixin", "world.WorldMixin", "world.chunk.ChunkMixin", + "world.chunk.storage.ChunkLoaderMixin", "world.chunk.storage.RegionFileCacheMixin", "world.dimension.DimensionMixin", - "world.dimension.DimensionTypeMixin", "world.gen.WorldGenRegionMixin", "world.gen.feature.structure.SwampHutPieceMixin", "world.raid.RaidManagerMixin", diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/LilyPadBlockMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/block/LilyPadBlockMixin_1_14.java similarity index 91% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/LilyPadBlockMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/block/LilyPadBlockMixin_1_14.java index 018b67a8..0a1f4859 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/LilyPadBlockMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/block/LilyPadBlockMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.block; +package io.izzel.arclight.impl.mixin.v1_14.block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LilyPadBlock.class) -public class LilyPadBlockMixin { +public class LilyPadBlockMixin_1_14 { @Inject(method = "onEntityCollision", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;Z)Z")) public void arclight$entityChangeBlock(BlockState state, World worldIn, BlockPos pos, Entity entityIn, CallbackInfo ci) { diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/EntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/EntityMixin_1_14.java index 48164e53..97035951 100644 --- a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/EntityMixin_1_14.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/EntityMixin_1_14.java @@ -8,6 +8,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.MobEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.server.MinecraftServer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -21,14 +22,16 @@ import net.minecraftforge.common.ForgeHooks; import org.bukkit.Location; import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.event.entity.EntityPortalEvent; +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 java.util.Random; @Mixin(Entity.class) -public abstract class EntityMixin_1_14 { +public abstract class EntityMixin_1_14 implements EntityBridge { // @formatter:off @Shadow public World world; @@ -45,6 +48,12 @@ public abstract class EntityMixin_1_14 { @Shadow public abstract void detach(); @Shadow public abstract EntityType getType(); @Shadow public abstract void remove(boolean keepData); + @Shadow @Final protected EntityDataManager dataManager; + @Shadow public abstract boolean isInvisible(); + @Shadow @Final protected Random rand; + @Shadow public abstract float getWidth(); + @Shadow public abstract float getHeight(); + @Shadow public abstract float getEyeHeight(); // @formatter:on /** @@ -143,4 +152,9 @@ public abstract class EntityMixin_1_14 { return null; } } + + @Override + public double bridge$getEyeHeight() { + return this.posY + (double) this.getEyeHeight(); + } } diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/LivingEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/LivingEntityMixin_1_14.java new file mode 100644 index 00000000..4adb9a5f --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/LivingEntityMixin_1_14.java @@ -0,0 +1,278 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.boss.WitherEntity; +import net.minecraft.entity.item.ExperienceOrbEntity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.network.datasync.DataParameter; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.potion.Effect; +import net.minecraft.potion.EffectInstance; +import net.minecraft.util.DamageSource; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameRules; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.PotionEvent; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.EntityPotionEffectEvent; +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 javax.annotation.Nullable; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +@Mixin(LivingEntity.class) +public abstract class LivingEntityMixin_1_14 extends EntityMixin_1_14 implements LivingEntityBridge { + + // @formatter:off + @Shadow @Final private static DataParameter POTION_EFFECTS; + @Shadow @Final private static DataParameter HIDE_PARTICLES; + @Shadow @Final public Map activePotionsMap; + @Shadow public boolean potionsNeedUpdate; + @Shadow protected abstract void onFinishedPotionEffect(EffectInstance effect); + @Shadow protected abstract void onChangedPotionEffect(EffectInstance id, boolean reapply); + @Shadow protected abstract void updatePotionMetadata(); + @Shadow public abstract boolean removePotionEffect(Effect effectIn); + @Shadow public abstract boolean isPotionApplicable(EffectInstance potioneffectIn); + @Shadow protected abstract void onNewPotionEffect(EffectInstance id); + @Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin); + @Shadow public int deathTime; + @Shadow protected abstract boolean isPlayer(); + @Shadow protected int recentlyHit; + @Shadow protected abstract boolean canDropLoot(); + // @formatter:on + + /** + * @author IzzelAliz + * @reason + */ + @SuppressWarnings("ConstantConditions") + @Overwrite + protected void onDeathUpdate() { + ++this.deathTime; + if (this.deathTime >= 20 && !this.removed) { + + if (!this.world.isRemote && (this.isPlayer() || this.recentlyHit > 0 && this.canDropLoot() && this.world.getGameRules().getBoolean(GameRules.DO_MOB_LOOT))) { + int i = this.bridge$getExpToDrop(); + while (i > 0) { + int j = ExperienceOrbEntity.getXPSplit(i); + i -= j; + this.world.addEntity(new ExperienceOrbEntity(this.world, this.posX, this.posY, this.posZ, j)); + } + this.bridge$setExpToDrop(0); + } + + this.remove((Object) this instanceof ServerPlayerEntity); //Forge keep data until we revive player + + for (int k = 0; k < 20; ++k) { + double d2 = this.rand.nextGaussian() * 0.02D; + double d0 = this.rand.nextGaussian() * 0.02D; + double d1 = this.rand.nextGaussian() * 0.02D; + this.world.addParticle(ParticleTypes.POOF, this.posX + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), this.posY + (double) (this.rand.nextFloat() * this.getHeight()), this.posZ + (double) (this.rand.nextFloat() * this.getWidth() * 2.0F) - (double) this.getWidth(), d2, d0, d1); + } + } + } + + private boolean isTickingEffects = false; + private List, EntityPotionEffectEvent.Cause>> effectsToProcess = Lists.newArrayList(); + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + protected void updatePotionEffects() { + this.isTickingEffects = true; + Iterator iterator = this.activePotionsMap.keySet().iterator(); + + try { + while (iterator.hasNext()) { + Effect effect = iterator.next(); + EffectInstance effectinstance = this.activePotionsMap.get(effect); + if (!effectinstance.tick((LivingEntity) (Object) this)) { + if (!this.world.isRemote && !MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionExpiryEvent((LivingEntity) (Object) this, effectinstance))) { + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); + if (event.isCancelled()) { + continue; + } + + iterator.remove(); + this.onFinishedPotionEffect(effectinstance); + } + } else if (effectinstance.getDuration() % 600 == 0) { + this.onChangedPotionEffect(effectinstance, false); + } + } + } catch (ConcurrentModificationException ignored) { + } + + isTickingEffects = false; + for (Map.Entry, EntityPotionEffectEvent.Cause> e : effectsToProcess) { + Either either = e.getKey(); + EntityPotionEffectEvent.Cause cause = e.getValue(); + bridge$pushEffectCause(cause); + if (either.left().isPresent()) { + addPotionEffect(either.left().get()); + } else { + removePotionEffect(either.right().get()); + } + } + effectsToProcess.clear(); + + if (this.potionsNeedUpdate) { + if (!this.world.isRemote) { + this.updatePotionMetadata(); + } + + this.potionsNeedUpdate = false; + } + + int i = this.dataManager.get(POTION_EFFECTS); + boolean flag1 = this.dataManager.get(HIDE_PARTICLES); + if (i > 0) { + boolean flag; + if (this.isInvisible()) { + flag = this.rand.nextInt(15) == 0; + } else { + flag = this.rand.nextBoolean(); + } + + if (flag1) { + flag &= this.rand.nextInt(5) == 0; + } + + 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.world.addParticle(flag1 ? ParticleTypes.AMBIENT_ENTITY_EFFECT : ParticleTypes.ENTITY_EFFECT, this.posX + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), this.posY + this.rand.nextDouble() * (double) this.getHeight(), this.posZ + (this.rand.nextDouble() - 0.5D) * (double) this.getWidth(), d0, d1, d2); + } + } + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public boolean addPotionEffect(EffectInstance effectInstanceIn) { + EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); + if (isTickingEffects) { + effectsToProcess.add(Maps.immutableEntry(Either.left(effectInstanceIn), cause)); + return true; + } + + if (!this.isPotionApplicable(effectInstanceIn)) { + return false; + } else { + EffectInstance effectinstance = this.activePotionsMap.get(effectInstanceIn.getPotion()); + + boolean override = false; + if (effectinstance != null) { + override = new EffectInstance(effectinstance).combine(effectInstanceIn); + } + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn, cause, override); + if (event.isCancelled()) { + return false; + } + + MinecraftForge.EVENT_BUS.post(new PotionEvent.PotionAddedEvent((LivingEntity) (Object) this, effectinstance, effectInstanceIn)); + if (effectinstance == null) { + this.activePotionsMap.put(effectInstanceIn.getPotion(), effectInstanceIn); + this.onNewPotionEffect(effectInstanceIn); + return true; + } else if (event.isOverride()) { + effectinstance.combine(effectInstanceIn); + this.onChangedPotionEffect(effectinstance, true); + return true; + } else { + return false; + } + } + } + + @SuppressWarnings("unused") // mock + public EffectInstance c(@Nullable Effect potioneffectin, EntityPotionEffectEvent.Cause cause) { + bridge$pushEffectCause(cause); + return removeActivePotionEffect(potioneffectin); + } + + @Inject(method = "removeActivePotionEffect", at = @At("HEAD")) + public void arclight$clearActive(Effect effect, CallbackInfoReturnable cir) { + EntityPotionEffectEvent.Cause cause = bridge$getEffectCause().orElse(EntityPotionEffectEvent.Cause.UNKNOWN); + if (isTickingEffects) { + effectsToProcess.add(Maps.immutableEntry(Either.right(effect), cause)); + cir.setReturnValue(null); + return; + } + + EffectInstance effectInstance = this.activePotionsMap.get(effect); + if (effectInstance == null) { + cir.setReturnValue(null); + return; + } + + EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent((LivingEntity) (Object) this, effectInstance, null, cause); + if (event.isCancelled()) { + cir.setReturnValue(null); + } + } + + private transient boolean arclight$fallSuccess; + + @Inject(method = "fall", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + public void arclight$fall(float distance, float damageMultiplier, CallbackInfo ci) { + if (!arclight$fallSuccess) { + ci.cancel(); + } + } + + @Redirect(method = "fall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + public boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount) { + return arclight$fallSuccess = livingEntity.attackEntityFrom(source, amount); + } + + @Override + public void bridge$dropExperience() { + } + + @Override + public void bridge$createWitherRose(LivingEntity entity) { + if (!this.world.isRemote && entity instanceof WitherEntity) { + boolean flag3 = false; + if (net.minecraftforge.event.ForgeEventFactory.getMobGriefingEvent(this.world, (ServerPlayerEntity) (Object) this)) { + BlockPos blockposition = new BlockPos(this.posX, this.posY, this.posZ); + BlockState iblockdata = Blocks.WITHER_ROSE.getDefaultState(); + if (this.world.getBlockState(blockposition).isAir() && iblockdata.isValidPosition(this.world, blockposition)) { + this.world.setBlockState(blockposition, iblockdata, 3); + flag3 = true; + } + } + if (!flag3) { + ItemEntity entityitem = new ItemEntity(this.world, this.posX, this.posY, this.posZ, new ItemStack(Items.WITHER_ROSE)); + this.world.addEntity(entityitem); + } + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/boss/WitherEntityMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/boss/WitherEntityMixin_1_14.java similarity index 98% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/boss/WitherEntityMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/boss/WitherEntityMixin_1_14.java index 9b2c12c3..994b2537 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/boss/WitherEntityMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/boss/WitherEntityMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.entity.boss; +package io.izzel.arclight.impl.mixin.v1_14.entity.boss; import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; import net.minecraft.block.BlockState; @@ -27,7 +27,7 @@ import org.spongepowered.asm.mixin.Shadow; import java.util.List; @Mixin(WitherEntity.class) -public abstract class WitherEntityMixin extends CreatureEntityMixin { +public abstract class WitherEntityMixin_1_14 extends CreatureEntityMixin { // @formatter:off @Shadow public abstract int getInvulTime(); diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/item/ItemEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/item/ItemEntityMixin_1_14.java new file mode 100644 index 00000000..94ff0c9c --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/item/ItemEntityMixin_1_14.java @@ -0,0 +1,18 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity.item; + +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(ItemEntity.class) +public class ItemEntityMixin_1_14 { + + @Redirect(method = "func_213858_a", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/entity/item/ItemEntity;setItem(Lnet/minecraft/item/ItemStack;)V")) + private static void arclight$setNonEmpty(ItemEntity itemEntity, ItemStack stack) { + if (!stack.isEmpty()) { + itemEntity.setItem(stack); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/PillagerEntityMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/PillagerEntityMixin_1_14.java similarity index 85% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/PillagerEntityMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/PillagerEntityMixin_1_14.java index 2ea26dc5..04778722 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/PillagerEntityMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/PillagerEntityMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.entity.monster; +package io.izzel.arclight.impl.mixin.v1_14.entity.monster; import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; import net.minecraft.entity.monster.PillagerEntity; @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(PillagerEntity.class) -public abstract class PillagerEntityMixin extends CreatureEntityMixin { +public abstract class PillagerEntityMixin_1_14 extends CreatureEntityMixin { // @formatter:off @Shadow public abstract Inventory getInventory(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/RavagerEntityMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/RavagerEntityMixin_1_14.java similarity index 87% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/RavagerEntityMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/RavagerEntityMixin_1_14.java index c3e3c0bf..028e28d8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/RavagerEntityMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/RavagerEntityMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.entity.monster; +package io.izzel.arclight.impl.mixin.v1_14.entity.monster; import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; import net.minecraft.block.Blocks; @@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(RavagerEntity.class) -public abstract class RavagerEntityMixin extends CreatureEntityMixin { +public abstract class RavagerEntityMixin_1_14 extends CreatureEntityMixin { @Redirect(method = "livingTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;destroyBlock(Lnet/minecraft/util/math/BlockPos;Z)Z")) private boolean arclight$entityChangeBlock(World world, BlockPos pos, boolean dropBlock) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ShulkerEntityMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ShulkerEntityMixin_1_14.java similarity index 85% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ShulkerEntityMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ShulkerEntityMixin_1_14.java index a2aa2740..9c50bc1c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/monster/ShulkerEntityMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ShulkerEntityMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.entity.monster; +package io.izzel.arclight.impl.mixin.v1_14.entity.monster; import io.izzel.arclight.common.mixin.core.entity.CreatureEntityMixin; import net.minecraft.entity.monster.ShulkerEntity; @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ShulkerEntity.class) -public abstract class ShulkerEntityMixin extends CreatureEntityMixin { +public abstract class ShulkerEntityMixin_1_14 extends CreatureEntityMixin { @Inject(method = "notifyDataManagerChange", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/monster/ShulkerEntity;prevPosX:D")) private void arclight$chunkCheck(DataParameter key, CallbackInfo ci) { diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ZombiePigmanEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ZombiePigmanEntityMixin_1_14.java new file mode 100644 index 00000000..841f8fac --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/monster/ZombiePigmanEntityMixin_1_14.java @@ -0,0 +1,56 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity.monster; + +import io.izzel.arclight.common.bridge.entity.EntityBridge; +import io.izzel.arclight.common.mixin.core.entity.monster.ZombieEntityMixin; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.ZombiePigmanEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.DamageSource; +import org.bukkit.Bukkit; +import org.bukkit.entity.PigZombie; +import org.bukkit.event.entity.PigZombieAngerEvent; +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(ZombiePigmanEntity.class) +public abstract class ZombiePigmanEntityMixin_1_14 extends ZombieEntityMixin { + + // @formatter:off + @Shadow protected abstract boolean becomeAngryAt(Entity p_70835_1_); + @Shadow protected abstract int func_223336_ef(); + // @formatter:on + + public boolean attackEntityFrom(DamageSource damagesource, float f) { + if (this.isInvulnerableTo(damagesource)) { + return false; + } + Entity entity = damagesource.getTrueSource(); + boolean result = super.attackEntityFrom(damagesource, f); + if (result && entity instanceof PlayerEntity && !((PlayerEntity) entity).isCreative() && this.canEntityBeSeen(entity)) { + this.becomeAngryAt(entity); + } + return result; + } + + @Inject(method = "becomeAngryAt", cancellable = true, at = @At("HEAD")) + private void arclight$anger(Entity entity, CallbackInfoReturnable cir) { + PigZombieAngerEvent event = new PigZombieAngerEvent((PigZombie) this.getBukkitEntity(), (entity == null) ? null : ((EntityBridge) entity).bridge$getBukkitEntity(), this.func_223336_ef()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + cir.setReturnValue(false); + } else { + arclight$capture = event.getNewAnger(); + } + } + + private transient int arclight$capture; + + @Redirect(method = "becomeAngryAt", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/monster/ZombiePigmanEntity;func_223336_ef()I")) + private int arclight$useAnger(ZombiePigmanEntity pigmanEntity) { + return arclight$capture; + } +} diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/OcelotEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/OcelotEntityMixin_1_14.java new file mode 100644 index 00000000..be15cd24 --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/OcelotEntityMixin_1_14.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity.passive; + +import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.impl.mixin.v1_14.entity.EntityMixin_1_14; +import net.minecraft.entity.passive.OcelotEntity; +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.CallbackInfo; + +@Mixin(OcelotEntity.class) +public abstract class OcelotEntityMixin_1_14 extends EntityMixin_1_14 { + + @Inject(method = "func_213525_dW", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + private void arclight$spawnBaby(CallbackInfo ci) { + ((WorldBridge) this.world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.OCELOT_BABY); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntity_MateGoalMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/PandaEntity_MateGoalMixin.java similarity index 94% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntity_MateGoalMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/PandaEntity_MateGoalMixin.java index ce1677b2..d2d09ec9 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/passive/PandaEntity_MateGoalMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/passive/PandaEntity_MateGoalMixin.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.entity.passive; +package io.izzel.arclight.impl.mixin.v1_14.entity.passive; import io.izzel.arclight.common.bridge.entity.MobEntityBridge; import net.minecraft.entity.passive.PandaEntity; diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/PlayerEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/PlayerEntityMixin_1_14.java new file mode 100644 index 00000000..cfb29703 --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/PlayerEntityMixin_1_14.java @@ -0,0 +1,138 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity.player; + +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; +import io.izzel.arclight.common.bridge.entity.player.PlayerEntityBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.mixin.core.entity.LivingEntityMixin; +import net.minecraft.entity.player.PlayerAbilities; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Unit; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v.block.CraftBlock; +import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerBedLeaveEvent; +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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import java.util.Optional; + +@Mixin(PlayerEntity.class) +public abstract class PlayerEntityMixin_1_14 extends LivingEntityMixin implements PlayerEntityBridge { + + // @formatter:off + @Shadow public abstract Either trySleep(BlockPos at); + @Shadow public abstract void startSleeping(BlockPos p_213342_1_); + @Shadow public int sleepTimer; + @Shadow public abstract void addStat(ResourceLocation stat); + @Shadow @Final public PlayerAbilities abilities; + // @formatter:on + + @Override + public CraftHumanEntity bridge$getBukkitEntity() { + return (CraftHumanEntity) ((InternalEntityBridge) this).internal$getBukkitEntity(); + } + + private boolean arclight$forceSleep = false; + private Object arclight$processSleep = null; + + private Either getBedResult(BlockPos at, Direction direction) { + arclight$processSleep = true; + Either either = this.trySleep(at); + arclight$processSleep = null; + return either; + } + + public Either sleep(BlockPos at, boolean force) { + arclight$forceSleep = force; + try { + return this.trySleep(at); + } finally { + arclight$forceSleep = false; + } + } + + @Inject(method = "trySleep", cancellable = true, at = @At(value = "HEAD")) + public void arclight$onSleep(BlockPos at, CallbackInfoReturnable> cir) { + if (arclight$processSleep == null) { + Either result = getBedResult(at, null); + + if (result.left().orElse(null) == PlayerEntity.SleepResult.OTHER_PROBLEM) { + cir.setReturnValue(result); + return; + } + if (arclight$forceSleep) { + result = Either.right(Unit.INSTANCE); + } + if (this.bridge$getBukkitEntity() instanceof Player) { + result = CraftEventFactory.callPlayerBedEnterEvent((PlayerEntity) (Object) this, at, result); + if (result.left().isPresent()) { + cir.setReturnValue(result); + return; + } + } + + this.startSleeping(at); + this.sleepTimer = 0; + if (this.world instanceof ServerWorld) { + ((ServerWorld) this.world).updateAllPlayersSleepingFlag(); + } + cir.setReturnValue(Either.right(Unit.INSTANCE)); + } + } + + @Inject(method = "trySleep", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerEntity;startSleeping(Lnet/minecraft/util/math/BlockPos;)V")) + public void arclight$preSleep(BlockPos at, CallbackInfoReturnable> cir) { + if (arclight$processSleep != null) { + cir.setReturnValue(Either.right(Unit.INSTANCE)); + } + } + + @Inject(method = "wakeUpPlayer", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "FIELD", target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I")) + private void arclight$wakeup(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci, Optional optional) { + if (this.getBukkitEntity() instanceof Player) { + Player player = (Player) this.getBukkitEntity(); + BlockPos blockposition2 = optional.orElse(null); + Block bed; + if (blockposition2 != null) { + bed = CraftBlock.at(this.world, blockposition2); + } else { + bed = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(player.getLocation()); + } + PlayerBedLeaveEvent event = new PlayerBedLeaveEvent(player, bed, setSpawn); + Bukkit.getPluginManager().callEvent(event); + arclight$setSpawn = event.shouldSetSpawnLocation(); + } + } + + private boolean arclight$setSpawn; + + @ModifyVariable(method = "wakeUpPlayer", index = 3, name = "setSpawn", at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/entity/player/PlayerEntity;sleepTimer:I")) + private boolean arclight$modifySpawn(boolean setSpawn) { + return arclight$setSpawn; + } + + @Inject(method = "setSpawnPoint(Lnet/minecraft/util/math/BlockPos;Z)V", at = @At("RETURN")) + private void arclight$updateSpawnpoint(BlockPos pos, boolean forced, CallbackInfo ci) { + bridge$setSpawnWorld(pos == null ? "" : this.world.worldInfo.getWorldName()); + } + + @Override + public Either bridge$trySleep(BlockPos at, boolean force) { + return sleep(at, force); + } +} diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/ServerPlayerEntityMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/ServerPlayerEntityMixin_1_14.java new file mode 100644 index 00000000..16459823 --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/entity/player/ServerPlayerEntityMixin_1_14.java @@ -0,0 +1,264 @@ +package io.izzel.arclight.impl.mixin.v1_14.entity.player; + +import com.mojang.datafixers.util.Either; +import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; +import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge; +import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.play.ServerPlayNetHandler; +import net.minecraft.network.play.server.SChangeGameStatePacket; +import net.minecraft.network.play.server.SPlayEntityEffectPacket; +import net.minecraft.network.play.server.SPlaySoundEventPacket; +import net.minecraft.network.play.server.SPlayerAbilitiesPacket; +import net.minecraft.network.play.server.SRespawnPacket; +import net.minecraft.network.play.server.SServerDifficultyPacket; +import net.minecraft.potion.EffectInstance; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.management.PlayerInteractionManager; +import net.minecraft.server.management.PlayerList; +import net.minecraft.stats.Stats; +import net.minecraft.util.Unit; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.WorldInfo; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v.CraftWorld; +import org.bukkit.craftbukkit.v.entity.CraftPlayer; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.craftbukkit.v.util.BlockStateListPopulator; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerPortalEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.world.PortalCreateEvent; +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.List; + +@Mixin(ServerPlayerEntity.class) +public abstract class ServerPlayerEntityMixin_1_14 extends PlayerEntityMixin_1_14 implements ServerPlayerEntityBridge { + + // @formatter:off + @Shadow public boolean invulnerableDimensionChange; + @Shadow public abstract ServerWorld func_71121_q(); + @Shadow public boolean queuedEndExit; + @Shadow public ServerPlayNetHandler connection; + @Shadow private boolean seenCredits; + @Shadow @Final public MinecraftServer server; + @Shadow @Final public PlayerInteractionManager interactionManager; + @Shadow @Nullable private Vec3d enteredNetherPosition; + @Shadow public abstract void func_213846_b(ServerWorld p_213846_1_); + @Shadow public int lastExperience; + @Shadow private float lastHealth; + @Shadow private int lastFoodLevel; + // @formatter:on + + @Override + public CraftPlayer bridge$getBukkitEntity() { + return (CraftPlayer) ((InternalEntityBridge) this).internal$getBukkitEntity(); + } + + /** + * @author IzzelAliz + * @reason + */ + @Nullable + @Overwrite + public Entity changeDimension(DimensionType dimensionmanager) { + PlayerTeleportEvent.TeleportCause cause = bridge$getTeleportCause().orElse(PlayerTeleportEvent.TeleportCause.UNKNOWN); + if (!net.minecraftforge.common.ForgeHooks.onTravelToDimension((ServerPlayerEntity) (Object) this, dimensionmanager)) + return null; + if (this.isSleeping()) { + return (ServerPlayerEntity) (Object) this; + } + DimensionType dimensionmanager2 = this.dimension; + if (((DimensionTypeBridge) dimensionmanager2).bridge$getType() == DimensionType.THE_END && ((DimensionTypeBridge) dimensionmanager).bridge$getType() == DimensionType.OVERWORLD) { + this.invulnerableDimensionChange = true; + this.detach(); + this.func_71121_q().removePlayer((ServerPlayerEntity) (Object) this, true); + if (!this.queuedEndExit) { + this.queuedEndExit = true; + this.connection.sendPacket(new SChangeGameStatePacket(4, this.seenCredits ? 0.0f : 1.0f)); + this.seenCredits = true; + } + return (ServerPlayerEntity) (Object) this; + } + ServerWorld worldserver = this.server.func_71218_a(dimensionmanager2); + ServerWorld worldserver2 = this.server.func_71218_a(dimensionmanager); + WorldInfo worlddata = this.world.getWorldInfo(); + double d0 = this.posX; + double d2 = this.posY; + double d3 = this.posZ; + float f = this.rotationPitch; + float f2 = this.rotationYaw; + double d4 = 8.0; + float f3 = f2; + worldserver.getProfiler().startSection("moving"); + if (worldserver2 != null) { + if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_NETHER) { + this.enteredNetherPosition = new Vec3d(this.posX, this.posY, this.posZ); + d0 /= 8.0; + d3 /= 8.0; + } else if (dimensionmanager2 == DimensionType.THE_NETHER && dimensionmanager == DimensionType.OVERWORLD) { + d0 *= 8.0; + d3 *= 8.0; + } else if (dimensionmanager2 == DimensionType.OVERWORLD && dimensionmanager == DimensionType.THE_END) { + BlockPos blockposition = worldserver2.getSpawnCoordinate(); + d0 = blockposition.getX(); + d2 = blockposition.getY(); + d3 = blockposition.getZ(); + f2 = 90.0f; + f = 0.0f; + } + } + Location enter = this.getBukkitEntity().getLocation(); + Location exit = (worldserver2 == null) ? null : new Location(((WorldBridge) worldserver2).bridge$getWorld(), d0, d2, d3, f2, f); + PlayerPortalEvent event = new PlayerPortalEvent((Player) this.getBukkitEntity(), enter, exit, cause); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null) { + return null; + } + exit = event.getTo(); + if (exit == null) { + return null; + } + PlayerTeleportEvent tpEvent = new PlayerTeleportEvent((Player) this.getBukkitEntity(), enter, exit, cause); + Bukkit.getServer().getPluginManager().callEvent(tpEvent); + if (tpEvent.isCancelled() || tpEvent.getTo() == null) { + return null; + } + exit = tpEvent.getTo(); + if (exit == null) { + return null; + } + worldserver2 = ((CraftWorld) exit.getWorld()).getHandle(); + d0 = exit.getX(); + d2 = exit.getY(); + d3 = exit.getZ(); + f2 = exit.getYaw(); + f = exit.getPitch(); + this.invulnerableDimensionChange = true; + dimensionmanager = worldserver2.getDimension().getType(); + this.dimension = dimensionmanager; + net.minecraftforge.fml.network.NetworkHooks.sendDimensionDataPacket(this.connection.netManager, (ServerPlayerEntity) (Object) this); + this.connection.sendPacket(new SRespawnPacket(worldserver2.dimension.getType(), this.world.getWorldInfo().getGenerator(), this.interactionManager.getGameType())); + this.connection.sendPacket(new SServerDifficultyPacket(this.world.getDifficulty(), this.world.getWorldInfo().isDifficultyLocked())); + PlayerList playerlist = this.server.getPlayerList(); + playerlist.updatePermissionLevel((ServerPlayerEntity) (Object) this); + worldserver.removePlayer((ServerPlayerEntity) (Object) this, true); + this.removed = false; + this.setLocationAndAngles(d0, d2, d3, f2, f); + worldserver.getProfiler().endSection(); + worldserver.getProfiler().startSection("placing"); + double d5 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minX() + 16.0); + double d6 = Math.min(-2.9999872E7, worldserver2.getWorldBorder().minZ() + 16.0); + double d7 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxX() - 16.0); + double d8 = Math.min(2.9999872E7, worldserver2.getWorldBorder().maxZ() - 16.0); + d0 = MathHelper.clamp(d0, d5, d7); + d3 = MathHelper.clamp(d3, d6, d8); + this.setLocationAndAngles(d0, d2, d3, f2, f); + if (((DimensionTypeBridge) dimensionmanager).bridge$getType() == DimensionType.THE_END) { + int i = MathHelper.floor(this.posX); + int j = MathHelper.floor(this.posY) - 1; + int k = MathHelper.floor(this.posZ); + boolean flag = true; + boolean flag2 = false; + BlockStateListPopulator blockList = new BlockStateListPopulator(worldserver2); + for (int l = -2; l <= 2; ++l) { + for (int i2 = -2; i2 <= 2; ++i2) { + for (int j2 = -1; j2 < 3; ++j2) { + int k2 = i + i2 * 1 + l * 0; + int l2 = j + j2; + int i3 = k + i2 * 0 - l * 1; + boolean flag3 = j2 < 0; + blockList.setBlockState(new BlockPos(k2, l2, i3), flag3 ? Blocks.OBSIDIAN.getDefaultState() : Blocks.AIR.getDefaultState(), 3); + } + } + } + org.bukkit.World bworld = ((WorldBridge) worldserver2).bridge$getWorld(); + PortalCreateEvent portalEvent = new PortalCreateEvent((List) blockList.getList(), bworld, this.getBukkitEntity(), PortalCreateEvent.CreateReason.END_PLATFORM); + Bukkit.getPluginManager().callEvent(portalEvent); + if (!portalEvent.isCancelled()) { + blockList.updateList(); + } + this.setLocationAndAngles(i, j, k, f2, 0.0f); + this.setMotion(Vec3d.ZERO); + } else if (!worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3)) { + worldserver2.getDefaultTeleporter().makePortal((ServerPlayerEntity) (Object) this); + worldserver2.getDefaultTeleporter().placeInPortal((ServerPlayerEntity) (Object) this, f3); + } + worldserver.getProfiler().endSection(); + this.setWorld(worldserver2); + worldserver2.func_217447_b((ServerPlayerEntity) (Object) this); + this.func_213846_b(worldserver); + this.connection.setPlayerLocation(this.posX, this.posY, this.posZ, f2, f); + this.interactionManager.func_73080_a(worldserver2); + this.connection.sendPacket(new SPlayerAbilitiesPacket(this.abilities)); + playerlist.func_72354_b((ServerPlayerEntity) (Object) this, worldserver2); + playerlist.sendInventory((ServerPlayerEntity) (Object) this); + for (EffectInstance mobeffect : this.getActivePotionEffects()) { + this.connection.sendPacket(new SPlayEntityEffectPacket(this.getEntityId(), mobeffect)); + } + this.connection.sendPacket(new SPlaySoundEventPacket(1032, BlockPos.ZERO, 0, false)); + this.lastExperience = -1; + this.lastHealth = -1.0f; + this.lastFoodLevel = -1; + PlayerChangedWorldEvent changeEvent = new PlayerChangedWorldEvent((Player) this.getBukkitEntity(), ((WorldBridge) worldserver).bridge$getWorld()); + Bukkit.getPluginManager().callEvent(changeEvent); + net.minecraftforge.fml.hooks.BasicEventHooks.firePlayerChangedDimensionEvent((ServerPlayerEntity) (Object) this, dimensionmanager2, dimensionmanager); + return (ServerPlayerEntity) (Object) this; + } + + public Entity a(DimensionType dimensionmanager, final PlayerTeleportEvent.TeleportCause cause) { + bridge$pushChangeDimensionCause(cause); + return this.changeDimension(dimensionmanager); + } + + @Override + public Either sleep(BlockPos at, boolean force) { + return super.sleep(at, force).ifRight((p_213849_1_) -> { + this.addStat(Stats.SLEEP_IN_BED); + CriteriaTriggers.SLEPT_IN_BED.trigger((ServerPlayerEntity) (Object) this); + }); + } + + @Inject(method = "wakeUpPlayer", cancellable = true, at = @At("HEAD")) + private void arclight$notWake(boolean immediately, boolean updateWorldFlag, boolean setSpawn, CallbackInfo ci) { + if (!isSleeping()) ci.cancel(); + } + + @Override + public Entity bridge$changeDimension(DimensionType dimensionType, PlayerTeleportEvent.TeleportCause cause) { + return a(dimensionType, cause); + } + + @Inject(method = "setElytraFlying", cancellable = true, at = @At("HEAD")) + private void arclight$beginGlide(CallbackInfo ci) { + if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, true).isCancelled()) { + ci.cancel(); + } + } + + @Inject(method = "clearElytraFlying", cancellable = true, at = @At("HEAD")) + private void arclight$endGlide(CallbackInfo ci) { + if (CraftEventFactory.callToggleGlideEvent((ServerPlayerEntity) (Object) this, false).isCancelled()) { + ci.cancel(); + } + } +} diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/ExplosionMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/ExplosionMixin_1_14.java new file mode 100644 index 00000000..721ff934 --- /dev/null +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/ExplosionMixin_1_14.java @@ -0,0 +1,136 @@ +package io.izzel.arclight.impl.mixin.v1_14.world; + +import io.izzel.arclight.common.bridge.world.ExplosionBridge; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.Explosion; +import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.storage.loot.LootContext; +import net.minecraft.world.storage.loot.LootParameters; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.block.BlockIgniteEvent; +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 java.util.List; +import java.util.Random; + +@Mixin(Explosion.class) +public abstract class ExplosionMixin_1_14 implements ExplosionBridge { + + // @formatter:off + @Shadow @Final private World world; + @Shadow @Final private Explosion.Mode mode; + @Shadow @Mutable @Final private float size; + @Shadow @Final private List affectedBlockPositions; + @Shadow @Final private double x; + @Shadow @Final private double y; + @Shadow @Final private double z; + @Shadow @Final private boolean causesFire; + @Shadow @Final private Random random; + @Accessor("exploder") public abstract Entity bridge$getExploder(); + @Accessor("size") public abstract float bridge$getSize(); + @Accessor("size") public abstract void bridge$setSize(float size); + @Accessor("mode") public abstract Explosion.Mode bridge$getMode(); + // @formatter:on + + public boolean wasCanceled = false; + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void doExplosionB(boolean spawnParticles) { + if (world.isRemote) { + this.world.playSound(this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F, false); + } + boolean flag = this.mode != Explosion.Mode.NONE; + + if (spawnParticles) { + if (!(this.size < 2.0F) && flag) { + this.world.addParticle(ParticleTypes.EXPLOSION_EMITTER, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } else { + this.world.addParticle(ParticleTypes.EXPLOSION, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D); + } + } + + if (flag) { + + float yield = this.bridge$callBlockExplodeEvent(); + + if (Float.isNaN(yield)) { + this.wasCanceled = true; + return; + } + + for (BlockPos blockpos : this.affectedBlockPositions) { + BlockState blockstate = this.world.getBlockState(blockpos); + Block block = blockstate.getBlock(); + if (spawnParticles) { + double d0 = ((float) blockpos.getX() + this.world.rand.nextFloat()); + double d1 = ((float) blockpos.getY() + this.world.rand.nextFloat()); + double d2 = ((float) blockpos.getZ() + this.world.rand.nextFloat()); + double d3 = d0 - this.x; + double d4 = d1 - this.y; + double d5 = d2 - this.z; + double d6 = MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5); + d3 = d3 / d6; + d4 = d4 / d6; + d5 = d5 / d6; + double d7 = 0.5D / (d6 / (double) this.size + 0.1D); + d7 = d7 * (double) (this.world.rand.nextFloat() * this.world.rand.nextFloat() + 0.3F); + d3 = d3 * d7; + d4 = d4 * d7; + d5 = d5 * d7; + this.world.addParticle(ParticleTypes.POOF, (d0 + this.x) / 2.0D, (d1 + this.y) / 2.0D, (d2 + this.z) / 2.0D, d3, d4, d5); + this.world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, d3, d4, d5); + } + + if (!blockstate.isAir(this.world, blockpos)) { + if (this.world instanceof ServerWorld && blockstate.canDropFromExplosion(this.world, blockpos, (Explosion) (Object) this)) { + TileEntity tileentity = blockstate.hasTileEntity() ? this.world.getTileEntity(blockpos) : null; + LootContext.Builder lootcontext$builder = (new LootContext.Builder((ServerWorld) this.world)).withRandom(this.world.rand).withParameter(LootParameters.POSITION, blockpos).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, tileentity); + if (this.mode == Explosion.Mode.DESTROY || yield < 1.0F) { + lootcontext$builder.withParameter(LootParameters.EXPLOSION_RADIUS, 1.0F / yield); + } + + Block.spawnDrops(blockstate, lootcontext$builder); + } + + blockstate.onBlockExploded(this.world, blockpos, (Explosion) (Object) this); + } + } + } + + if (this.causesFire) { + for (BlockPos blockPos : this.affectedBlockPositions) { + if (this.world.getBlockState(blockPos).isAir(world, blockPos) && this.world.getBlockState(blockPos.down()).isOpaqueCube(this.world, blockPos.down()) && this.random.nextInt(3) == 0) { + BlockIgniteEvent event = CraftEventFactory.callBlockIgniteEvent(this.world, blockPos.getX(), blockPos.getY(), blockPos.getZ(), (Explosion) (Object) this); + if (!event.isCancelled()) { + this.world.setBlockState(blockPos, Blocks.FIRE.getDefaultState()); + } + } + } + } + } + + @Override + public boolean bridge$wasCancelled() { + return wasCanceled; + } +} diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/dimension/DimensionTypeMixin_1_14.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/dimension/DimensionTypeMixin_1_14.java index bb3d16ea..91f3636a 100644 --- a/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/dimension/DimensionTypeMixin_1_14.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/dimension/DimensionTypeMixin_1_14.java @@ -1,5 +1,6 @@ package io.izzel.arclight.impl.mixin.v1_14.world.dimension; +import io.izzel.arclight.common.bridge.world.dimension.DimensionTypeBridge; import net.minecraft.world.World; import net.minecraft.world.dimension.Dimension; import net.minecraft.world.dimension.DimensionType; @@ -8,7 +9,7 @@ import org.spongepowered.asm.mixin.Mixin; import java.util.function.BiFunction; @Mixin(DimensionType.class) -public class DimensionTypeMixin_1_14 { +public class DimensionTypeMixin_1_14 implements DimensionTypeBridge { protected void arclight$constructor(int idIn, String suffixIn, String directoryIn, BiFunction p_i49935_4_, boolean p_i49935_5_) { throw new RuntimeException(); @@ -24,4 +25,9 @@ public class DimensionTypeMixin_1_14 { public DimensionType getType() { return (type == null) ? (DimensionType) (Object) this : type; } + + @Override + public DimensionType bridge$getType() { + return getType(); + } } diff --git a/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java index 1227657c..25887648 100644 --- a/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/server/Main.java @@ -1,9 +1,10 @@ package io.izzel.arclight.server; -import io.izzel.arclight.api.Unsafe; -import io.izzel.arclight.forgeinstaller.ForgeInstaller; -import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper; +import io.izzel.arclight.api.ArclightVersion; import io.izzel.arclight.api.EnumHelper; +import io.izzel.arclight.api.Unsafe; +import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper; +import io.izzel.arclight.forgeinstaller.ForgeInstaller; import net.minecraftforge.server.ServerMain; import org.apache.logging.log4j.LogManager; @@ -29,6 +30,7 @@ public class Main { System.setProperty("log4j.jul.LoggerAdapter", "io.izzel.arclight.common.mod.util.ArclightLoggerAdapter"); LogManager.getLogger("Arclight").info("Loading mappings ..."); Objects.requireNonNull(ArclightRemapper.INSTANCE); + ArclightVersion.setVersion(ArclightVersion.v1_14); ServerMain.main(args); } catch (Exception e) { e.printStackTrace(); diff --git a/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json b/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json index aa5686b2..8ef68821 100644 --- a/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json +++ b/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json @@ -29,6 +29,7 @@ "block.KelpTopBlockMixin_1_14", "block.LeavesBlockMixin_1_14", "block.LeverBlockMixin_1_14", + "block.LilyPadBlockMixin_1_14", "block.MushroomBlockMixin_1_14", "block.NetherPortalBlockMixin_1_14", "block.NetherWartBlockMixin_1_14", @@ -48,7 +49,19 @@ "command.impl.TeleportCommandMixin_1_14", "enchantment.FrostWalkerEnchantmentMixin_1_14", "entity.EntityMixin_1_14", + "entity.LivingEntityMixin_1_14", + "entity.boss.WitherEntityMixin_1_14", "entity.item.ArmorStandEntityMixin_1_14", + "entity.item.ItemEntityMixin_1_14", + "entity.monster.PillagerEntityMixin_1_14", + "entity.monster.RavagerEntityMixin_1_14", + "entity.monster.ShulkerEntityMixin_1_14", + "entity.monster.ZombiePigmanEntityMixin_1_14", + "entity.passive.OcelotEntityMixin_1_14", + "entity.passive.PandaEntity_MateGoalMixin", + "entity.player.PlayerEntityMixin_1_14", + "entity.player.ServerPlayerEntityMixin_1_14", + "world.ExplosionMixin_1_14", "world.chunk.ChunkMixin_1_14", "world.dimension.DimensionTypeMixin_1_14", "world.server.TicketManagerMixin_1_14"