diff --git a/arclight-common/build.gradle b/arclight-common/build.gradle index 00b906f7..f9ef997f 100644 --- a/arclight-common/build.gradle +++ b/arclight-common/build.gradle @@ -36,7 +36,7 @@ arclight { sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' minecraft { - mappings channel: 'snapshot', version: "20200813-1.16.1" + mappings channel: 'snapshot', version: "20200820-1.16.1" accessTransformer = project.file('src/main/resources/META-INF/accesstransformer.cfg') } 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..a48dfc42 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 @@ -3,7 +3,7 @@ package io.izzel.arclight.common.bridge.entity; import io.izzel.arclight.common.bridge.command.ICommandSourceBridge; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.server.ServerWorld; import org.bukkit.craftbukkit.v.entity.CraftEntity; import org.bukkit.projectiles.ProjectileSource; @@ -11,7 +11,7 @@ import java.util.List; public interface EntityBridge extends ICommandSourceBridge { - Entity bridge$teleportTo(DimensionType type, BlockPos blockPos); + Entity bridge$teleportTo(ServerWorld world, BlockPos blockPos); void bridge$setOnFire(int tick, boolean callEvent); @@ -52,4 +52,6 @@ public interface EntityBridge extends ICommandSourceBridge { void bridge$setRideCooldown(int rideCooldown); int bridge$getRideCooldown(); + + boolean bridge$canCollideWith(Entity entity); } 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 a8d0c133..5b1eaf55 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 @@ -3,11 +3,14 @@ package io.izzel.arclight.common.bridge.entity; import net.minecraft.entity.LivingEntity; import net.minecraft.util.ResourceLocation; import org.bukkit.event.entity.EntityTargetEvent; +import org.bukkit.event.entity.EntityTransformEvent; public interface MobEntityBridge extends LivingEntityBridge { void bridge$pushGoalTargetReason(EntityTargetEvent.TargetReason reason, boolean fireEvent); + void bridge$pushTransformReason(EntityTransformEvent.TransformReason transformReason); + boolean bridge$setGoalTarget(LivingEntity livingEntity, EntityTargetEvent.TargetReason reason, boolean fireEvent); ResourceLocation bridge$getLootTable(); 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 index 8f905516..914ea5ed 100644 --- 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 @@ -1,12 +1,14 @@ package io.izzel.arclight.common.bridge.world; -import net.minecraft.block.pattern.BlockPattern; import net.minecraft.entity.Entity; +import net.minecraft.util.TeleportationRepositioner; import net.minecraft.util.math.BlockPos; +import java.util.Optional; + 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); + Optional bridge$findPortal(BlockPos pos, int searchRadius); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java index d5a7e8f0..0ecf7d37 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java @@ -1,7 +1,9 @@ package io.izzel.arclight.common.bridge.world; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.RegistryKey; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.DimensionType; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.generator.ChunkGenerator; @@ -34,4 +36,6 @@ public interface WorldBridge extends IWorldWriterBridge, IWorldBridge { long bridge$ticksPerWaterSpawns(); long bridge$ticksPerAmbientSpawns(); + + RegistryKey bridge$getTypeKey(); } 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 de14f30f..ed05e89b 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 @@ -1,17 +1,21 @@ package io.izzel.arclight.common.mixin.core.entity; +import io.izzel.arclight.common.bridge.block.PortalInfoBridge; import io.izzel.arclight.common.bridge.command.ICommandSourceBridge; import io.izzel.arclight.common.bridge.entity.EntityBridge; import io.izzel.arclight.common.bridge.entity.InternalEntityBridge; import io.izzel.arclight.common.bridge.entity.LivingEntityBridge; import io.izzel.arclight.common.bridge.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.entity.player.ServerPlayerEntityBridge; +import io.izzel.arclight.common.bridge.world.TeleporterBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; -import io.izzel.arclight.common.bridge.world.storage.SaveHandlerBridge; import io.izzel.arclight.common.mod.util.ArclightCaptures; -import net.minecraft.block.pattern.BlockPattern; +import net.minecraft.block.BlockState; +import net.minecraft.block.PortalInfo; +import net.minecraft.block.PortalSize; import net.minecraft.command.CommandSource; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntitySize; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.MobEntity; @@ -27,21 +31,23 @@ import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.scoreboard.Team; import net.minecraft.server.MinecraftServer; +import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.DamageSource; import net.minecraft.util.Direction; import net.minecraft.util.SoundEvent; +import net.minecraft.util.TeleportationRepositioner; 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.util.math.vector.Vector3d; import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.DimensionType; import net.minecraft.world.World; -import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.border.WorldBorder; import net.minecraft.world.gen.Heightmap; import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.common.ForgeHooks; -import net.minecraftforge.common.util.ITeleporter; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.block.BlockFace; import org.bukkit.command.CommandSender; @@ -50,6 +56,7 @@ import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.entity.CraftEntity; import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.craftbukkit.v.event.CraftPortalEvent; import org.bukkit.entity.Hanging; import org.bukkit.entity.Vehicle; import org.bukkit.event.entity.EntityAirChangeEvent; @@ -81,6 +88,7 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Random; import java.util.UUID; @@ -90,11 +98,8 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, // @formatter:off @Shadow public float rotationYaw; - @Shadow public double posX; - @Shadow public double posY; @Shadow public World world; @Shadow protected int rideCooldown; - @Shadow public double posZ; @Shadow public float rotationPitch; @Shadow public int fire; @Shadow public abstract Pose getPose(); @@ -104,7 +109,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract boolean attackEntityFrom(DamageSource source, float amount); @Shadow public abstract void setFire(int p_70015_1_); @Shadow public boolean collidedHorizontally; - @Shadow protected abstract Vec3d getAllowedMovement(Vec3d p_213306_1_); + @Shadow protected abstract Vector3d getAllowedMovement(Vector3d p_213306_1_); @Shadow public abstract void remove(); @Shadow public int ticksExisted; @Shadow public void setWorld(World p_70029_1_) { } @@ -112,14 +117,13 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow @Final public List passengers; @Shadow @Nullable public abstract Entity getControllingPassenger(); @Shadow public abstract boolean isSwimming(); - @Shadow public DimensionType dimension; @Shadow public abstract boolean isAlive(); @Shadow public abstract void detach(); @Shadow @Final protected EntityDataManager dataManager; @Shadow @Final private static DataParameter AIR; @Shadow @Deprecated public boolean removed; @Shadow @Nullable public abstract MinecraftServer getServer(); - @Shadow public abstract Vec3d getMotion(); + @Shadow public abstract Vector3d getMotion(); @Shadow public abstract EntityType getType(); @Shadow(remap = false) public abstract void remove(boolean keepData); @Shadow @Final protected Random rand; @@ -137,7 +141,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow(remap = false) public abstract Collection captureDrops(); @Shadow(remap = false) public abstract Collection captureDrops(Collection value); @Shadow public abstract BlockPos getPosition(); - @Shadow public boolean onGround; + @Shadow protected boolean onGround; @Shadow public abstract boolean isInWater(); @Shadow public abstract boolean isPassenger(); @Shadow public float fallDistance; @@ -145,7 +149,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public float distanceWalkedModified; @Shadow public float prevDistanceWalkedModified; @Shadow public abstract boolean isOnSameTeam(Entity entityIn); - @Shadow public abstract void setMotion(Vec3d motionIn); + @Shadow public abstract void setMotion(Vector3d motionIn); @Shadow public abstract double getDistanceSq(Entity entityIn); @Shadow protected UUID entityUniqueID; @Shadow protected abstract void markVelocityChanged(); @@ -160,11 +164,10 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract boolean hasNoGravity(); @Shadow protected abstract void doBlockCollisions(); @Shadow public float prevRotationYaw; - @Shadow public abstract boolean handleWaterMovement(); @Shadow public abstract boolean isBeingRidden(); @Shadow public abstract boolean isPassenger(Entity entityIn); @Shadow public abstract void setMotion(double x, double y, double z); - @Shadow public abstract void move(MoverType typeIn, Vec3d pos); + @Shadow public abstract void move(MoverType typeIn, Vector3d pos); @Shadow @Nullable public abstract Entity getRidingEntity(); @Shadow @Nullable public abstract Team getTeam(); @Shadow public abstract void extinguish(); @@ -172,18 +175,22 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Shadow public abstract void setLocationAndAngles(double x, double y, double z, float yaw, float pitch); @Shadow public abstract int getEntityId(); @Shadow @Nullable public abstract ITextComponent getCustomName(); - @Shadow protected abstract void applyEnchantments(LivingEntity entityLivingBaseIn, Entity entityIn); - @Shadow @Nullable public abstract Entity changeDimension(DimensionType destination); + @Shadow public abstract void applyEnchantments(LivingEntity entityLivingBaseIn, Entity entityIn); + @Shadow @Nullable public abstract Entity changeDimension(ServerWorld world); @Shadow public abstract boolean isRidingSameEntity(Entity entityIn); @Shadow public abstract boolean isInvulnerable(); @Shadow public abstract double getPosX(); @Shadow public abstract double getPosZ(); - @Shadow public abstract Vec3d getLastPortalVec(); @Shadow public abstract double getPosY(); - @Shadow public abstract Direction getTeleportDirection(); @Shadow public abstract double getPosYEye(); - @Shadow public abstract Vec3d getPositionVec(); + @Shadow public abstract Vector3d getPositionVec(); @Shadow(remap = false) public abstract void revive(); + @Shadow public abstract boolean canBePushed(); + @Shadow protected abstract void setDead(); + @Shadow protected abstract Optional func_241830_a(ServerWorld p_241830_1_, BlockPos p_241830_2_, boolean p_241830_3_); + @Shadow protected BlockPos field_242271_ac; + @Shadow protected abstract Vector3d func_241839_a(Direction.Axis p_241839_1_, TeleportationRepositioner.Result p_241839_2_); + @Shadow public abstract EntitySize getSize(Pose poseIn); // @formatter:on private static final int CURRENT_LEVEL = 2; @@ -236,7 +243,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, } public boolean isChunkLoaded() { - return world.chunkExists((int) Math.floor(posX) >> 4, (int) Math.floor(posY) >> 4); + return world.chunkExists((int) Math.floor(getPosX()) >> 4, (int) Math.floor(getPosZ()) >> 4); } @Override @@ -265,7 +272,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, if (yaw == Float.POSITIVE_INFINITY || yaw == Float.NEGATIVE_INFINITY) { if (((Object) this) instanceof PlayerEntity) { Bukkit.getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid yaw"); - ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Are you hacking?)"); // 专业防抄袭 + ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite yaw (Are you hacking?)"); } this.rotationYaw = 0; callbackInfo.cancel(); @@ -280,7 +287,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, if (pitch == Float.POSITIVE_INFINITY || pitch == Float.NEGATIVE_INFINITY) { if (((Object) this) instanceof PlayerEntity) { Bukkit.getLogger().warning(this.getScoreboardName() + " was caught trying to crash the server with an invalid pitch"); - ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Are you hacking?)"); // 专业防抄袭 + ((CraftPlayer) this.getBukkitEntity()).kickPlayer("Infinite pitch (Are you hacking?)"); } this.rotationPitch = 0; callbackInfo.cancel(); @@ -395,17 +402,30 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, } @Inject(method = "move", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/block/Block;onEntityWalk(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/entity/Entity;)V")) - private void arclight$resetBlockWalk(MoverType typeIn, Vec3d pos, CallbackInfo ci) { + private void arclight$resetBlockWalk(MoverType typeIn, Vector3d pos, CallbackInfo ci) { ArclightCaptures.captureDamageEventBlock(null); } - @Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setFire(I)V")) - public void arclight$move$EntityCombustEvent(Entity entity, int seconds) { - EntityCombustEvent event = new EntityCombustByBlockEvent(null, getBukkitEntity(), 8); - Bukkit.getPluginManager().callEvent(event); + @Inject(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;canTriggerWalking()Z")) + private void arclight$move$blockCollide(MoverType typeIn, Vector3d pos, CallbackInfo ci) { + if (collidedHorizontally && this.bridge$getBukkitEntity() instanceof Vehicle) { + Vehicle vehicle = (Vehicle) this.bridge$getBukkitEntity(); + org.bukkit.block.Block block = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(MathHelper.floor(this.getPosX()), MathHelper.floor(this.getPosY()), MathHelper.floor(this.getPosZ())); + Vector3d vec3d = this.getAllowedMovement(pos); + if (pos.x > vec3d.x) { + block = block.getRelative(BlockFace.EAST); + } else if (vec3d.x < vec3d.x) { + block = block.getRelative(BlockFace.WEST); + } else if (pos.z > vec3d.z) { + block = block.getRelative(BlockFace.SOUTH); + } else if (pos.z < vec3d.z) { + block = block.getRelative(BlockFace.NORTH); + } - if (!event.isCancelled()) { - this.setFire(event.getDuration()); + if (block.getType() != org.bukkit.Material.AIR) { + VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, block); + Bukkit.getPluginManager().callEvent(event); + } } } @@ -436,7 +456,16 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Inject(method = "setPositionAndRotation", at = @At("RETURN")) private void arclight$loadChunk(double x, double y, double z, float yaw, float pitch, CallbackInfo ci) { - this.world.getChunk((int)Math.floor(this.posX) >> 4, (int)Math.floor(this.posZ) >> 4); + this.world.getChunk((int) Math.floor(this.getPosX()) >> 4, (int) Math.floor(this.getPosZ()) >> 4); + } + + public boolean canCollideWith(Entity entity) { + return this.canBePushed(); + } + + @Override + public boolean bridge$canCollideWith(Entity entity) { + return canCollideWith(entity); } @Inject(method = "writeUnlessRemoved", cancellable = true, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/entity/Entity;getEntityString()Ljava/lang/String;")) @@ -459,8 +488,8 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, @Inject(method = "writeWithoutTypeId", at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, target = "Lnet/minecraft/nbt/CompoundNBT;putUniqueId(Ljava/lang/String;Ljava/util/UUID;)V")) public void arclight$writeWithoutTypeId$CraftBukkitNBT(CompoundNBT compound, CallbackInfoReturnable cir) { - compound.putLong("WorldUUIDLeast", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID(((ServerWorld) this.world)).getLeastSignificantBits()); - compound.putLong("WorldUUIDMost", ((SaveHandlerBridge) (((ServerWorld) this.world).getSaveHandler())).bridge$getUUID(((ServerWorld) this.world)).getMostSignificantBits()); + compound.putLong("WorldUUIDLeast", ((WorldBridge) this.world).bridge$getWorld().getUID().getLeastSignificantBits()); + compound.putLong("WorldUUIDMost", ((WorldBridge) this.world).bridge$getWorld().getUID().getMostSignificantBits()); compound.putInt("Bukkit.updateLevel", CURRENT_LEVEL); compound.putInt("Spigot.ticksLived", this.ticksExisted); } @@ -507,7 +536,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, } if (bworld == null) { - bworld = ((WorldBridge) ((CraftServer) server).getServer().getWorld(DimensionType.OVERWORLD)).bridge$getWorld(); + bworld = ((WorldBridge) ((CraftServer) server).getServer().getWorld(World.OVERWORLD)).bridge$getWorld(); } setWorld(bworld == null ? null : ((CraftWorld) bworld).getHandle()); @@ -544,7 +573,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, cir.setReturnValue(true); } - @Redirect(method = "stopRiding()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;removePassenger(Lnet/minecraft/entity/Entity;)V")) + @Redirect(method = "dismount", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;removePassenger(Lnet/minecraft/entity/Entity;)V")) public void arclight$stopRiding$CraftBukkitPatch(Entity entity, Entity passenger) { if (!((EntityBridge) entity).bridge$removePassenger(passenger)) { this.ridingEntity = entity; @@ -644,7 +673,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, return true; // CraftBukkit } - @Inject(method = "updatePortal", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;changeDimension(Lnet/minecraft/world/dimension/DimensionType;)Lnet/minecraft/entity/Entity;")) + @Inject(method = "updatePortal", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;changeDimension(Lnet/minecraft/world/server/ServerWorld;)Lnet/minecraft/entity/Entity;")) public void arclight$changeDimension(CallbackInfo ci) { if (this instanceof ServerPlayerEntityBridge) { ((ServerPlayerEntityBridge) this).bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause.NETHER_PORTAL); @@ -677,7 +706,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, // CraftBukkit end } - @Redirect(method = "onStruckByLightning", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setFire(I)V")) + @Redirect(method = "func_241841_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setFire(I)V")) public void arclight$onStruckByLightning$EntityCombustByEntityEvent0(Entity entity, int seconds) { final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); final org.bukkit.entity.Entity stormBukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); @@ -691,7 +720,7 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, // CraftBukkit end } - @Redirect(method = "onStruckByLightning", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + @Redirect(method = "func_241841_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) public boolean arclight$onStruckByLightning$EntityCombustByEntityEvent1(Entity entity, DamageSource source, float amount) { final org.bukkit.entity.Entity thisBukkitEntity = this.getBukkitEntity(); final org.bukkit.entity.Entity stormBukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); @@ -737,37 +766,14 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, } } - public Entity teleportTo(DimensionType type, BlockPos blockPos) { + public Entity teleportTo(ServerWorld world, BlockPos blockPos) { arclight$tpPos = blockPos; - return changeDimension(type); + return changeDimension(world); } @Override - public Entity bridge$teleportTo(DimensionType type, BlockPos blockPos) { - return teleportTo(type, blockPos); - } - - @Inject(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;canTriggerWalking()Z")) - private void arclight$move$blockCollide(MoverType typeIn, Vec3d pos, CallbackInfo ci) { - if (collidedHorizontally && this.bridge$getBukkitEntity() instanceof Vehicle) { - Vehicle vehicle = (Vehicle) this.bridge$getBukkitEntity(); - org.bukkit.block.Block block = ((WorldBridge) this.world).bridge$getWorld().getBlockAt(MathHelper.floor(this.getPosX()), MathHelper.floor(this.getPosY()), MathHelper.floor(this.getPosZ())); - Vec3d vec3d = this.getAllowedMovement(pos); - if (pos.x > vec3d.x) { - block = block.getRelative(BlockFace.EAST); - } else if (vec3d.x < vec3d.x) { - block = block.getRelative(BlockFace.WEST); - } else if (pos.z > vec3d.z) { - block = block.getRelative(BlockFace.SOUTH); - } else if (pos.z < vec3d.z) { - block = block.getRelative(BlockFace.NORTH); - } - - if (block.getType() != org.bukkit.Material.AIR) { - VehicleBlockCollisionEvent event = new VehicleBlockCollisionEvent(vehicle, block); - Bukkit.getPluginManager().callEvent(event); - } - } + public Entity bridge$teleportTo(ServerWorld world, BlockPos blockPos) { + return teleportTo(world, blockPos); } /** @@ -776,107 +782,135 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, */ @Overwrite(remap = false) @Nullable - public Entity changeDimension(DimensionType destination, ITeleporter teleporter) { - BlockPos location = ((InternalEntityBridge) this).internal$capturedPos(); - if (!ForgeHooks.onTravelToDimension((Entity) (Object) this, destination)) return null; - if (!this.world.isRemote && !this.removed) { + public Entity changeDimension(ServerWorld server, net.minecraftforge.common.util.ITeleporter teleporter) { + if (this.world instanceof ServerWorld && !this.removed) { this.world.getProfiler().startSection("changeDimension"); - MinecraftServer minecraftserver = this.getServer(); - DimensionType dimensiontype = this.dimension; - ServerWorld serverworld = minecraftserver.getWorld(dimensiontype); - ServerWorld[] serverworld1 = new ServerWorld[]{minecraftserver.getWorld(destination)}; - - if (serverworld1 == null) { + if (server == null) { return null; } - //this.dimension = destination; - //this.detach(); this.world.getProfiler().startSection("reposition"); - Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, serverworld, serverworld1[0], this.rotationYaw, spawnPortal -> { //Forge: Start vanilla logic - Vec3d vec3d = this.getMotion(); - float f = 0.0F; - BlockPos blockpos = location; - if (blockpos == null) { - if (dimensiontype == DimensionType.THE_END && destination == DimensionType.OVERWORLD) { - EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent((Entity) (Object) this, serverworld1[0], serverworld1[0].getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, serverworld1[0].getSpawnPoint()), 0); - if (event == null) { - return null; - } - serverworld1[0] = ((CraftWorld) event.getTo().getWorld()).getHandle(); - blockpos = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); - //blockpos = serverworld1[0].getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, serverworld1[0].getSpawnPoint()); - } else if (destination == DimensionType.THE_END) { - EntityPortalEvent event = CraftEventFactory.callEntityPortalEvent((Entity) (Object) this, serverworld1[0], (serverworld1[0].getSpawnCoordinate() != null) ? serverworld1[0].getSpawnCoordinate() : serverworld1[0].getSpawnPoint(), 0); - if (event == null) { - return null; - } - serverworld1[0] = ((CraftWorld) event.getTo().getWorld()).getHandle(); - blockpos = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); - //blockpos = serverworld1[0].getSpawnCoordinate(); - } else { - double movementFactor = serverworld.getDimension().getMovementFactor() / serverworld1[0].getDimension().getMovementFactor(); - double d0 = this.getPosX() * movementFactor; - double d1 = this.getPosZ() * movementFactor; - - double d3 = Math.min(-2.9999872E7D, serverworld1[0].getWorldBorder().minX() + 16.0D); - double d4 = Math.min(-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, d3, d5); - d1 = MathHelper.clamp(d1, d4, d6); - Vec3d vec3d1 = this.getLastPortalVec(); - blockpos = new BlockPos(d0, this.getPosY(), d1); - - EntityPortalEvent event2 = CraftEventFactory.callEntityPortalEvent((Entity) (Object) this, serverworld1[0], blockpos, 128); - if (event2 == null) { - return null; - } - serverworld1[0] = ((CraftWorld) event2.getTo().getWorld()).getHandle(); - blockpos = new BlockPos(event2.getTo().getX(), event2.getTo().getY(), event2.getTo().getZ()); - int searchRadius = event2.getSearchRadius(); - // todo 实现 radius - - if (spawnPortal) { - BlockPattern.PortalInfo blockpattern$portalinfo = serverworld1[0].getDefaultTeleporter().placeInExistingPortal(blockpos, vec3d, this.getTeleportDirection(), vec3d1.x, vec3d1.y, (Object) this instanceof PlayerEntity); - if (blockpattern$portalinfo == null) { - return null; - } - - blockpos = new BlockPos(blockpattern$portalinfo.pos); - vec3d = blockpattern$portalinfo.motion; - f = (float) blockpattern$portalinfo.rotation; - } - } - } - - this.dimension = destination; + PortalInfo portalinfo = this.func_241829_a(server); + if (portalinfo == null) { + return null; + } else { + server = ((PortalInfoBridge) portalinfo).bridge$getWorld(); this.detach(); + Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerWorld) this.world, server, this.rotationYaw, spawnPortal -> { //Forge: Start vanilla logic + this.world.getProfiler().endStartSection("reloading"); + ServerWorld world = ((PortalInfoBridge) portalinfo).bridge$getWorld(); + Entity entity = this.getType().create(world); + if (entity != null) { + entity.copyDataFromOld((Entity) (Object) this); + entity.setLocationAndAngles(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.field_242960_c, entity.rotationPitch); + entity.setMotion(portalinfo.motion); + world.addFromAnotherDimension(entity); + if (((WorldBridge) world).bridge$getTypeKey() == DimensionType.THE_END) { + ArclightCaptures.captureEndPortalEntity((Entity) (Object) this, spawnPortal); + ServerWorld.func_241121_a_(world); + } - this.world.getProfiler().endStartSection("reloading"); - Entity entity = this.getType().create(serverworld1[0]); - if (entity != null) { - entity.copyDataFromOld((Entity) (Object) this); - entity.moveToBlockPosAndAngles(blockpos, entity.rotationYaw + f, entity.rotationPitch); - entity.setMotion(vec3d); - serverworld1[0].addFromAnotherDimension(entity); - - ((InternalEntityBridge) this).internal$getBukkitEntity().setHandle(entity); - ((EntityBridge) entity).bridge$setBukkitEntity(((InternalEntityBridge) this).internal$getBukkitEntity()); - if ((Object) this instanceof MobEntity) { - ((MobEntity) (Object) this).clearLeashed(true, false); + this.getBukkitEntity().setHandle(entity); + ((EntityBridge) entity).bridge$setBukkitEntity(this.bridge$getBukkitEntity()); + if ((Object) this instanceof MobEntity) { + ((MobEntity) (Object) this).clearLeashed(true, false); + } } - } - return entity; - });//Forge: End vanilla logic + return entity; + }); //Forge: End vanilla logic - this.remove(false); - this.world.getProfiler().endSection(); - serverworld.resetUpdateEntityTick(); - serverworld1[0].resetUpdateEntityTick(); - this.world.getProfiler().endSection(); - return transportedEntity; + this.setDead(); + this.world.getProfiler().endSection(); + ((ServerWorld) this.world).resetUpdateEntityTick(); + server.resetUpdateEntityTick(); + this.world.getProfiler().endSection(); + return transportedEntity; + } } else { return null; } } + + /** + * @author IzzelAliz + * @reason + */ + @Nullable + @Overwrite + protected PortalInfo func_241829_a(ServerWorld world) { + if (world == null) { + return null; + } + boolean flag = ((WorldBridge) this.world).bridge$getTypeKey() == DimensionType.THE_END && ((WorldBridge) world).bridge$getTypeKey() == DimensionType.OVERWORLD; + boolean flag1 = ((WorldBridge) world).bridge$getTypeKey() == DimensionType.THE_END; + if (!flag && !flag1) { + boolean flag2 = ((WorldBridge) world).bridge$getTypeKey() == DimensionType.THE_NETHER; + if (this.world.getDimensionKey() != World.THE_NETHER && !flag2) { + return null; + } else { + WorldBorder worldborder = world.getWorldBorder(); + double d0 = Math.max(-2.9999872E7D, worldborder.minX() + 16.0D); + double d1 = Math.max(-2.9999872E7D, worldborder.minZ() + 16.0D); + double d2 = Math.min(2.9999872E7D, worldborder.maxX() - 16.0D); + double d3 = Math.min(2.9999872E7D, worldborder.maxZ() - 16.0D); + double d4 = DimensionType.func_242715_a(this.world.func_230315_m_(), world.func_230315_m_()); + BlockPos blockpos1 = new BlockPos(MathHelper.clamp(this.getPosX() * d4, d0, d2), this.getPosY(), MathHelper.clamp(this.getPosZ() * d4, d1, d3)); + + CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, blockpos1, PlayerTeleportEvent.TeleportCause.NETHER_PORTAL, flag2 ? 16 : 128, 16); + if (event == null) { + return null; + } + ServerWorld worldFinal = world = ((CraftWorld) event.getTo().getWorld()).getHandle(); + blockpos1 = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + + return this.a(world, blockpos1, flag2, event.getSearchRadius(), event.getCanCreatePortal(), event.getCreationRadius()).map((p_242275_2_) -> { + BlockState blockstate = this.world.getBlockState(this.field_242271_ac); + Direction.Axis direction$axis; + Vector3d vector3d; + if (blockstate.hasProperty(BlockStateProperties.HORIZONTAL_AXIS)) { + direction$axis = blockstate.get(BlockStateProperties.HORIZONTAL_AXIS); + TeleportationRepositioner.Result teleportationrepositioner$result = TeleportationRepositioner.func_243676_a(this.field_242271_ac, direction$axis, 21, Direction.Axis.Y, 21, (p_242276_2_) -> { + return this.world.getBlockState(p_242276_2_) == blockstate; + }); + vector3d = this.func_241839_a(direction$axis, teleportationrepositioner$result); + } else { + direction$axis = Direction.Axis.X; + vector3d = new Vector3d(0.5D, 0.0D, 0.0D); + } + + return PortalSize.func_242963_a(worldFinal, p_242275_2_, direction$axis, vector3d, this.getSize(this.getPose()), this.getMotion(), this.rotationYaw, this.rotationPitch); + }).orElse(null); + } + } else { + BlockPos blockpos; + if (flag1) { + blockpos = ServerWorld.field_241108_a_; + } else { + blockpos = world.getHeight(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, world.getSpawnPoint()); + } + + CraftPortalEvent event = this.callPortalEvent((Entity) (Object) this, world, blockpos, PlayerTeleportEvent.TeleportCause.END_PORTAL, 0, 0); + if (event == null) { + return null; + } + blockpos = new BlockPos(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); + + return new PortalInfo(new Vector3d((double) blockpos.getX() + 0.5D, blockpos.getY(), (double) blockpos.getZ() + 0.5D), this.getMotion(), this.rotationYaw, this.rotationPitch); + } + } + + protected CraftPortalEvent callPortalEvent(Entity entity, ServerWorld exitWorldServer, BlockPos exitPosition, PlayerTeleportEvent.TeleportCause cause, int searchRadius, int creationRadius) { + CraftEntity bukkitEntity = ((EntityBridge) entity).bridge$getBukkitEntity(); + Location enter = bukkitEntity.getLocation(); + Location exit = new Location(((WorldBridge) exitWorldServer).bridge$getWorld(), exitPosition.getX(), exitPosition.getY(), exitPosition.getZ()); + EntityPortalEvent event = new EntityPortalEvent(bukkitEntity, enter, exit, searchRadius); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled() || event.getTo() == null || event.getTo().getWorld() == null || !entity.isAlive()) { + return null; + } + return new CraftPortalEvent(event); + } + + protected Optional a(ServerWorld serverWorld, BlockPos pos, boolean flag, int searchRadius, boolean canCreatePortal, int createRadius) { + return ((TeleporterBridge) serverWorld.getDefaultTeleporter()).bridge$findPortal(pos, searchRadius); + } } 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 eee8e87a..380b3d9f 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 @@ -7,14 +7,15 @@ 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; +import io.izzel.arclight.mixin.Eject; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; -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.ai.attributes.Attribute; +import net.minecraft.entity.ai.attributes.AttributeModifierManager; +import net.minecraft.entity.ai.attributes.Attributes; +import net.minecraft.entity.ai.attributes.ModifiableAttributeInstance; import net.minecraft.entity.item.ExperienceOrbEntity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.passive.AnimalEntity; @@ -75,11 +76,14 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import javax.annotation.Nullable; import java.util.Collection; import java.util.ConcurrentModificationException; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Random; +import java.util.Set; +import java.util.UUID; @SuppressWarnings({"ConstantConditions", "Guava"}) @Mixin(LivingEntity.class) @@ -99,7 +103,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public int deathTime; @Shadow protected boolean dead; @Shadow(remap = false) public void remove(boolean keepData) { } - @Shadow public abstract IAttributeInstance getAttribute(IAttribute attribute); + @Shadow public abstract ModifiableAttributeInstance getAttribute(Attribute attribute); @Shadow public boolean potionsNeedUpdate; @Shadow public abstract boolean removePotionEffect(Effect effectIn); @Shadow public abstract boolean clearActivePotions(); @@ -119,7 +123,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow public float attackedAtYaw; @Shadow public abstract void setRevengeTarget(@Nullable LivingEntity livingBase); @Shadow protected abstract void markVelocityChanged(); - @Shadow public abstract void knockBack(Entity entityIn, float strength, double xRatio, double zRatio); @Shadow @Nullable protected abstract SoundEvent getDeathSound(); @Shadow protected abstract float getSoundVolume(); @Shadow protected abstract float getSoundPitch(); @@ -132,10 +135,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow @Nullable public abstract EffectInstance getActivePotionEffect(Effect potionIn); @Shadow protected abstract float applyPotionDamageCalculations(DamageSource source, float damage); @Shadow public abstract float getAbsorptionAmount(); - @Shadow protected abstract void damageArmor(float damage); @Shadow public abstract void setAbsorptionAmount(float amount); @Shadow public abstract CombatTracker getCombatTracker(); - @Shadow private AbstractAttributeMap attributes; + @Shadow @Final private AttributeModifierManager attributes; @Shadow public abstract boolean isOnLadder(); @Shadow protected ItemStack activeItemStack; @Shadow public abstract void onItemPickup(Entity entityIn, int quantity); @@ -164,6 +166,10 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt @Shadow protected abstract void onNewPotionEffect(EffectInstance id); @Shadow @Nullable public abstract EffectInstance removeActivePotionEffect(@Nullable Effect potioneffectin); @Shadow protected abstract void createWitherRose(@Nullable LivingEntity p_226298_1_); + @Shadow public abstract double getAttributeValue(Attribute attribute); + @Shadow public abstract void applyKnockback(float strength, double ratioX, double ratioZ); + @Shadow protected abstract void damageArmor(DamageSource damageSource, float damage); + @Shadow protected abstract void playEquipSound(ItemStack stack); // @formatter:on public int expToDrop; @@ -172,11 +178,19 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt public CraftAttributeMap craftAttributes; public boolean collides; public boolean canPickUpLoot; + public Set collidableExemptions = new HashSet<>(); + + @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;setHealth(F)V")) + private void arclight$muteHealth(LivingEntity entity, float health) { + // do nothing + } @Inject(method = "", at = @At("RETURN")) private void arclight$init(EntityType type, World worldIn, CallbackInfo ci) { this.maxAirTicks = 300; this.collides = true; + this.craftAttributes = new CraftAttributeMap(this.attributes); + this.dataManager.set(HEALTH, (float) this.getAttributeValue(Attributes.MAX_HEALTH)); } /** @@ -375,19 +389,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - - 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); + @Eject(method = "onLivingFall", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;attackEntityFrom(Lnet/minecraft/util/DamageSource;F)Z")) + private boolean arclight$fall(LivingEntity livingEntity, DamageSource source, float amount, CallbackInfoReturnable cir) { + boolean ret = livingEntity.attackEntityFrom(source, amount); + cir.setReturnValue(ret); + return ret; } @Override @@ -395,16 +401,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt return canPickUpLoot; } - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;getMaxHealth()F")) - public float arclight$muteHealth(LivingEntity livingEntity) { - return 0; - } - - @Redirect(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;setHealth(F)V")) - public void arclight$muteHealth2(LivingEntity livingEntity, float health) { - this.dataManager.set(HEALTH, (float) this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).getValue()); - } - @Override public float getBukkitYaw() { return getRotationYawHead(); @@ -444,9 +440,9 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt if (compound.contains("Bukkit.MaxHealth")) { INBT nbtbase = compound.get("Bukkit.MaxHealth"); if (nbtbase.getId() == 5) { - this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(((FloatNBT) nbtbase).getDouble()); + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatNBT) nbtbase).getDouble()); } else if (nbtbase.getId() == 3) { - this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(((IntNBT) nbtbase).getDouble()); + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntNBT) nbtbase).getDouble()); } } } @@ -567,7 +563,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt if ((Object) this instanceof AnimalEntity) { ((AnimalEntity) (Object) this).resetInLove(); if ((Object) this instanceof TameableEntity) { - ((TameableEntity) (Object) this).getAISit().setSitting(false); + ((TameableEntity) (Object) this).func_233687_w_(false); } } @@ -620,15 +616,15 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } if (entity1 != null) { - double d1 = entity1.posX - this.posX; + double d1 = entity1.getPosX() - this.getPosX(); double d0; - for (d0 = entity1.posZ - this.posZ; d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D) { + for (d0 = entity1.getPosZ() - this.getPosZ(); d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D) { d1 = (Math.random() - Math.random()) * 0.01D; } this.attackedAtYaw = (float) (MathHelper.atan2(d0, d1) * (double) (180F / (float) Math.PI) - (double) this.rotationYaw); - this.knockBack(entity1, 0.4F, d1, d0); + this.applyKnockback(0.4F, d1, d0); } else { this.attackedAtYaw = (float) ((int) (Math.random() * 2.0D) * 180); } @@ -751,7 +747,7 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt // Apply damage to armor if (!damagesource.isUnblockable()) { float armorDamage = (float) (event.getDamage() + event.getDamage(EntityDamageEvent.DamageModifier.BLOCKING) + event.getDamage(EntityDamageEvent.DamageModifier.HARD_HAT)); - this.damageArmor(armorDamage); + this.damageArmor(damagesource, armorDamage); } // Apply blocking code // PAIL: steal from above @@ -927,14 +923,16 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt this.addPotionEffect(new EffectInstance(Effects.REGENERATION, 900, 1)); bridge$pushEffectCause(EntityPotionEffectEvent.Cause.TOTEM); this.addPotionEffect(new EffectInstance(Effects.ABSORPTION, 100, 1)); + bridge$pushEffectCause(EntityPotionEffectEvent.Cause.TOTEM); + this.addPotionEffect(new EffectInstance(Effects.FIRE_RESISTANCE, 800, 1)); this.world.setEntityState((Entity) (Object) this, (byte) 35); } return !event.isCancelled(); } } - @Redirect(method = "applyArmorCalculations", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;damageArmor(F)V")) - public void arclight$muteDamageArmor(LivingEntity livingEntity, float damage) { + @Redirect(method = "applyArmorCalculations", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;damageArmor(Lnet/minecraft/util/DamageSource;F)V")) + public void arclight$muteDamageArmor(LivingEntity entity, DamageSource damageSource, float damage) { } @Redirect(method = "applyPotionDamageCalculations", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;isPotionActive(Lnet/minecraft/potion/Effect;)Z")) @@ -942,13 +940,6 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt return false; } - @Inject(method = "getAttributes", at = @At("RETURN")) - public void arclight$initializeCraftAttr(CallbackInfoReturnable cir) { - if (this.craftAttributes == null) { - this.craftAttributes = new CraftAttributeMap(this.attributes); - } - } - @Redirect(method = "travel", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;setFlag(IZ)V")) public void arclight$stopGlide(LivingEntity livingEntity, int flag, boolean set) { if (set != livingEntity.getFlag(flag) && !CraftEventFactory.callToggleGlideEvent(livingEntity, set).isCancelled()) { @@ -981,6 +972,11 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt return this.isAlive() && !this.isOnLadder() && this.collides; } + @Override + public boolean canCollideWith(Entity entity) { + return this.canBePushed() && this.collides != this.collidableExemptions.contains(entity.getUniqueID()); + } + private transient ItemStack arclight$consumePost; @Inject(method = "onItemUseFinish", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, @@ -1001,25 +997,33 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt } } - @Redirect(method = "onItemUseFinish", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;onItemUseFinish(Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/item/ItemStack;")) - public ItemStack arclight$useEventItem(ItemStack itemStack, World worldIn, LivingEntity entityLiving) { - if (arclight$consumePost != null) itemStack = arclight$consumePost; - arclight$consumePost = null; + @Eject(method = "onItemUseFinish", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;onItemUseFinish(Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/item/ItemStack;")) + private ItemStack arclight$itemConsume(ItemStack itemStack, World worldIn, LivingEntity entityLiving, CallbackInfo ci) { + if (this instanceof ServerPlayerEntityBridge) { + final org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(itemStack); + final PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + ((ServerPlayerEntityBridge) this).bridge$getBukkitEntity().updateInventory(); + ((ServerPlayerEntityBridge) this).bridge$getBukkitEntity().updateScaledHealth(); + ci.cancel(); + return null; + } else if (!craftItem.equals(event.getItem())) { + return CraftItemStack.asNMSCopy(event.getItem()).onItemUseFinish(worldIn, entityLiving); + } + } return itemStack.onItemUseFinish(worldIn, entityLiving); } - @Inject(method = "attemptTeleport", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, - at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/entity/LivingEntity;setPositionAndUpdate(DDD)V")) - public void arclight$entityTeleport(double d0, double d1, double d2, boolean flag, CallbackInfoReturnable cir, double d3, double d4, double d5) { - EntityTeleportEvent event = new EntityTeleportEvent(getBukkitEntity(), new Location(((WorldBridge) this.world).bridge$getWorld(), d3, d4, d5), - new Location(((WorldBridge) this.world).bridge$getWorld(), this.posX, this.posY, this.posZ)); + @Eject(method = "attemptTeleport", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/entity/LivingEntity;setPositionAndUpdate(DDD)V")) + private void arclight$entityTeleport(LivingEntity entity, double x, double y, double z, CallbackInfoReturnable cir) { + EntityTeleportEvent event = new EntityTeleportEvent(getBukkitEntity(), new Location(((WorldBridge) this.world).bridge$getWorld(), this.getPosX(), this.getPosY(), this.getPosZ()), + new Location(((WorldBridge) this.world).bridge$getWorld(), x, y, z)); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - this.posX = event.getTo().getX(); - this.posY = event.getTo().getY(); - this.posZ = event.getTo().getZ(); + this.setPositionAndUpdate(event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()); } else { - this.setPositionAndUpdate(d3, d4, d5); + this.setPositionAndUpdate(this.getPosX(), this.getPosY(), this.getPosZ()); cir.setReturnValue(false); } } @@ -1031,6 +1035,13 @@ public abstract class LivingEntityMixin extends EntityMixin implements LivingEnt return drops == null ? livingEntity.captureDrops(value) : drops; } + @Inject(method = "canEntityBeSeen", cancellable = true, at = @At("HEAD")) + private void arclight$seeNoEvil(Entity entityIn, CallbackInfoReturnable cir) { + if (this.world != entityIn.world) { + cir.setReturnValue(false); + } + } + @Inject(method = "applyFoodEffects", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;addPotionEffect(Lnet/minecraft/potion/EffectInstance;)Z")) public void arclight$foodEffectCause(ItemStack p_213349_1_, World p_213349_2_, LivingEntity livingEntity, CallbackInfo ci) { ((LivingEntityBridge) livingEntity).bridge$pushEffectCause(EntityPotionEffectEvent.Cause.FOOD); 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 ffa1d7b1..fd796d6a 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,7 +3,9 @@ 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.bridge.world.WorldBridge; import io.izzel.arclight.common.mod.ArclightMod; +import io.izzel.arclight.mixin.Eject; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -15,6 +17,7 @@ import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.play.server.SMountEntityPacket; +import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; @@ -23,9 +26,11 @@ import org.apache.logging.log4j.Level; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityCombustByEntityEvent; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.event.entity.EntityTransformEvent; import org.bukkit.event.entity.EntityUnleashEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; @@ -54,8 +59,7 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt @Shadow protected abstract ResourceLocation shadow$getLootTable(); @Shadow public static EquipmentSlotType getSlotForItemStack(ItemStack stack) { return null; } @Shadow public abstract ItemStack getItemStackFromSlot(EquipmentSlotType slotIn); - @Shadow protected abstract boolean shouldExchangeEquipment(ItemStack candidate, ItemStack existing, EquipmentSlotType p_208003_3_); - @Shadow protected abstract boolean canEquipItem(ItemStack stack); + @Shadow public abstract boolean canEquipItem(ItemStack stack); @Shadow protected abstract float getDropChance(EquipmentSlotType slotIn); @Shadow public abstract void setItemStackToSlot(EquipmentSlotType slotIn, ItemStack stack); @Shadow @Final public float[] inventoryHandsDropChances; @@ -64,6 +68,9 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt @Shadow public abstract boolean isNoDespawnRequired(); @Shadow protected void updateAITasks() { } @Shadow public abstract boolean isAIDisabled(); + @Shadow protected abstract boolean shouldExchangeEquipment(ItemStack candidate, ItemStack existing); + @Shadow protected abstract void func_233657_b_(EquipmentSlotType p_233657_1_, ItemStack p_233657_2_); + @Shadow @Nullable public abstract T func_233656_b_(EntityType p_233656_1_, boolean p_233656_2_); // @formatter:on public boolean aware; @@ -193,38 +200,41 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt } } + @Inject(method = "updateEquipmentIfNeeded", at = @At("HEAD")) + private void arclight$captureItemEntity(ItemEntity itemEntity, CallbackInfo ci) { + arclight$item = itemEntity; + } + + private transient ItemEntity arclight$item; + /** * @author IzzelAliz * @reason */ @Overwrite - protected void updateEquipmentIfNeeded(ItemEntity itemEntity) { - ItemStack itemstack = itemEntity.getItem(); - EquipmentSlotType equipmentslottype = getSlotForItemStack(itemstack); - ItemStack itemstack1 = this.getItemStackFromSlot(equipmentslottype); - boolean flag = this.shouldExchangeEquipment(itemstack, itemstack1, equipmentslottype); - boolean canPickup = flag && this.canEquipItem(itemstack); - canPickup = !CraftEventFactory.callEntityPickupItemEvent((Entity) (Object) this, itemEntity, 0, !canPickup).isCancelled(); + public boolean func_233665_g_(ItemStack p_233665_1_) { + ItemEntity itemEntity = arclight$item; + arclight$item = null; + EquipmentSlotType equipmentslottype = getSlotForItemStack(p_233665_1_); + ItemStack itemstack = this.getItemStackFromSlot(equipmentslottype); + boolean flag = this.shouldExchangeEquipment(p_233665_1_, itemstack); + boolean canPickup = flag && this.canEquipItem(p_233665_1_); + if (itemEntity != null) { + canPickup = !CraftEventFactory.callEntityPickupItemEvent((MobEntity) (Object) this, itemEntity, 0, !canPickup).isCancelled(); + } if (canPickup) { double d0 = this.getDropChance(equipmentslottype); - if (!itemstack1.isEmpty() && (double) (this.rand.nextFloat() - 0.1F) < d0) { + if (!itemstack.isEmpty() && (double) Math.max(this.rand.nextFloat() - 0.1F, 0.0F) < d0) { forceDrops = true; - this.entityDropItem(itemstack1); + this.entityDropItem(itemstack); forceDrops = false; } - this.setItemStackToSlot(equipmentslottype, itemstack); - switch (equipmentslottype.getSlotType()) { - case HAND: - this.inventoryHandsDropChances[equipmentslottype.getIndex()] = 2.0F; - break; - case ARMOR: - this.inventoryArmorDropChances[equipmentslottype.getIndex()] = 2.0F; - } - - this.persistenceRequired = true; - this.onItemPickup(itemEntity, itemstack.getCount()); - itemEntity.remove(); + this.func_233657_b_(equipmentslottype, p_233665_1_); + this.playEquipSound(p_233665_1_); + return true; + } else { + return false; } } @@ -234,18 +244,18 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt } @Inject(method = "processInitialInteract", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;clearLeashed(ZZ)V")) - private void arclight$unleash(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + private void arclight$unleash(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { if (CraftEventFactory.callPlayerUnleashEntityEvent((MobEntity) (Object) this, player).isCancelled()) { ((ServerPlayerEntity) player).connection.sendPacket(new SMountEntityPacket((MobEntity) (Object) this, this.getLeashHolder())); - cir.setReturnValue(false); + cir.setReturnValue(ActionResultType.PASS); } } - @Inject(method = "processInitialInteract", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;setLeashHolder(Lnet/minecraft/entity/Entity;Z)V")) - private void arclight$leash(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { + @Inject(method = "func_233661_c_", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;setLeashHolder(Lnet/minecraft/entity/Entity;Z)V")) + private void arclight$leash(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { if (CraftEventFactory.callPlayerLeashEntityEvent((MobEntity) (Object) this, player, player).isCancelled()) { ((ServerPlayerEntity) player).connection.sendPacket(new SMountEntityPacket((MobEntity) (Object) this, this.getLeashHolder())); - cir.setReturnValue(false); + cir.setReturnValue(ActionResultType.PASS); } } @@ -265,11 +275,41 @@ public abstract class MobEntityMixin extends LivingEntityMixin implements MobEnt this.forceDrops = true; } - @Inject(method = "recreateLeash", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;clearLeashed(ZZ)V")) - public void arclight$createLeash(CallbackInfo ci) { + @Inject(method = "startRiding", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;clearLeashed(ZZ)V")) + private void arclight$unleashRide(Entity entityIn, boolean force, CallbackInfoReturnable cir) { Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); } + @Inject(method = "setDead", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/MobEntity;clearLeashed(ZZ)V")) + private void arclight$unleashDead(CallbackInfo ci) { + Bukkit.getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.UNKNOWN)); + } + + @Eject(method = "func_233656_b_", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + private boolean arclight$copySpawn(World world, Entity entityIn, CallbackInfoReturnable cir) { + EntityTransformEvent.TransformReason transformReason = arclight$transform == null ? EntityTransformEvent.TransformReason.UNKNOWN : arclight$transform; + arclight$transform = null; + if (CraftEventFactory.callEntityTransformEvent((MobEntity) (Object) this, (LivingEntity) entityIn, transformReason).isCancelled()) { + cir.setReturnValue(null); + return false; + } else { + return world.addEntity(entityIn); + } + } + + public T a(EntityType entityType, boolean flag, EntityTransformEvent.TransformReason transformReason, CreatureSpawnEvent.SpawnReason spawnReason) { + ((WorldBridge) this.world).bridge$pushAddEntityReason(spawnReason); + bridge$pushTransformReason(transformReason); + return this.func_233656_b_(entityType, flag); + } + + private transient EntityTransformEvent.TransformReason arclight$transform; + + @Override + public void bridge$pushTransformReason(EntityTransformEvent.TransformReason transformReason) { + this.arclight$transform = transformReason; + } + @Redirect(method = "attackEntityAsMob", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;setFire(I)V")) public void arclight$attackCombust(Entity entity, int seconds) { EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), ((EntityBridge) entity).bridge$getBukkitEntity(), seconds); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java index bfc49b29..9f0c3d25 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java @@ -11,7 +11,9 @@ import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.profiler.IProfiler; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.RegistryKey; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.DimensionType; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.border.WorldBorder; @@ -59,9 +61,10 @@ public abstract class WorldMixin implements WorldBridge { @Shadow public abstract WorldBorder getWorldBorder(); @Shadow@Final private WorldBorder worldBorder; @Shadow public abstract long getDayTime(); - @Accessor("mainThread") public abstract Thread arclight$getMainThread(); + @Shadow@Final private DimensionType dimensionType;@Accessor("mainThread") public abstract Thread arclight$getMainThread(); // @formatter:on + private RegistryKey typeKey; protected CraftWorld world; public boolean pvpMode; public boolean keepSpawnInMemory = true; @@ -90,6 +93,8 @@ public abstract class WorldMixin implements WorldBridge { this.ticksPerWaterSpawns = 1; this.ticksPerAmbientSpawns = 1; } + this.typeKey = this.getServer().getHandle().getServer().func_244267_aX().func_230520_a_().func_230519_c_(dimensionType) + .orElseThrow(() -> new IllegalStateException("Unregistered dimension type: " + dimType)); } @Override @@ -123,6 +128,15 @@ public abstract class WorldMixin implements WorldBridge { bridge$getWorld(); } + public RegistryKey getTypeKey() { + return this.typeKey; + } + + @Override + public RegistryKey bridge$getTypeKey() { + return getTypeKey(); + } + @Override public SpigotWorldConfig bridge$spigotConfig() { return this.spigotConfig; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java index da3c3c65..df2daa7c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java @@ -198,6 +198,27 @@ public class ArclightCaptures { } } + private static transient Entity endPortalEntity; + private static transient boolean spawnPortal; + + public static void captureEndPortalEntity(Entity entity, boolean portal) { + endPortalEntity = entity; + spawnPortal = portal; + } + + public static boolean getEndPortalSpawn() { + return spawnPortal; + } + + public static Entity getEndPortalEntity() { + try { + return endPortalEntity; + } finally { + endPortalEntity = null; + spawnPortal = false; + } + } + private static void recapture(String type) { throw new IllegalStateException("Recapturing " + type); }