From 5640328bada718f2a08fe2ad3849a6f63ce5a871 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Fri, 26 May 2023 13:12:05 +0800 Subject: [PATCH] Update upstream --- .../player/ServerPlayerEntityBridge.java | 5 +- .../network/ServerPlayNetHandlerMixin.java | 27 +++--- .../server/commands/SetSpawnCommandMixin.java | 25 ++++++ .../server/management/PlayerListMixin.java | 14 ++- .../mixin/core/world/ExplosionMixin.java | 21 +++-- .../core/world/entity/ExperienceOrbMixin.java | 7 ++ .../entity/player/ServerPlayerMixin.java | 85 ++++++++++++++++--- .../entity/projectile/FishingHookMixin.java | 28 ++++++ .../world/level/block/FireBlockMixin.java | 6 ++ .../level/block/RespawnAnchorBlockMixin.java | 25 ++++++ .../core/world/level/block/TntBlockMixin.java | 40 ++++++++- .../main/resources/mixins.arclight.core.json | 2 + arclight-forge/build.gradle | 2 +- 13 files changed, 248 insertions(+), 39 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/commands/SetSpawnCommandMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java index 30bbc0d1..8b116f07 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/entity/player/ServerPlayerEntityBridge.java @@ -1,15 +1,14 @@ package io.izzel.arclight.common.bridge.core.entity.player; import net.minecraft.core.BlockPos; -import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftPlayer; +import org.bukkit.event.player.PlayerSpawnChangeEvent; import org.bukkit.event.player.PlayerTeleportEvent; import java.util.Optional; -import java.util.UUID; public interface ServerPlayerEntityBridge extends PlayerEntityBridge { @@ -18,6 +17,8 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge { void bridge$pushChangeDimensionCause(PlayerTeleportEvent.TeleportCause cause); + void bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause cause); + Optional bridge$getTeleportCause(); BlockPos bridge$getSpawnPoint(ServerLevel world); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java index 11a0b225..8ad33bc1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/ServerPlayNetHandlerMixin.java @@ -436,8 +436,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB } @Inject(method = "handleAcceptTeleportPacket", - at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;awaitingPositionFromClient:Lnet/minecraft/world/phys/Vec3;"), - slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isChangingDimension()Z"))) + at = @At(value = "FIELD", shift = At.Shift.AFTER, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;awaitingPositionFromClient:Lnet/minecraft/world/phys/Vec3;"), + slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;isChangingDimension()Z"))) private void arclight$updateLoc(ServerboundAcceptTeleportationPacket packetIn, CallbackInfo ci) { if (((ServerPlayerEntityBridge) this.player).bridge$isValid()) { this.player.getLevel().getChunkSource().move(this.player); @@ -985,6 +985,13 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB } } + @Inject(method = "*", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;performChatCommand(Lnet/minecraft/network/protocol/game/ServerboundChatCommandPacket;Lnet/minecraft/network/chat/LastSeenMessages;)V")) + private void arclight$rejectIfDisconnect(CallbackInfo ci) { + if (this.player.hasDisconnected()) { + ci.cancel(); + } + } + /** * @author IzzelAliz * @reason @@ -1293,19 +1300,19 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB @Override public void onInteraction(InteractionHand hand) { this.performInteraction(hand, net.minecraft.world.entity.player.Player::interactOn, - new PlayerInteractEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), - (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); + new PlayerInteractEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), + (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); } @Override public void onInteraction(InteractionHand hand, Vec3 vec) { this.performInteraction(hand, (player, e, h) -> { - var onInteractEntityAtResult = ForgeHooks.onInteractEntityAt(player, entity, vec, hand); - if (onInteractEntityAtResult != null) return onInteractEntityAtResult; - return e.interactAt(player, vec, h); - }, - new PlayerInteractAtEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), - new org.bukkit.util.Vector(vec.x, vec.y, vec.z), (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); + var onInteractEntityAtResult = ForgeHooks.onInteractEntityAt(player, entity, vec, hand); + if (onInteractEntityAtResult != null) return onInteractEntityAtResult; + return e.interactAt(player, vec, h); + }, + new PlayerInteractAtEntityEvent(getCraftPlayer(), ((EntityBridge) entity).bridge$getBukkitEntity(), + new org.bukkit.util.Vector(vec.x, vec.y, vec.z), (hand == InteractionHand.OFF_HAND) ? EquipmentSlot.OFF_HAND : EquipmentSlot.HAND)); } @Override diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/commands/SetSpawnCommandMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/commands/SetSpawnCommandMixin.java new file mode 100644 index 00000000..9db1a65c --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/commands/SetSpawnCommandMixin.java @@ -0,0 +1,25 @@ +package io.izzel.arclight.common.mixin.core.server.commands; + +import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.core.BlockPos; +import net.minecraft.server.commands.SetSpawnCommand; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.event.player.PlayerSpawnChangeEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Collection; + +@Mixin(SetSpawnCommand.class) +public class SetSpawnCommandMixin { + + @Inject(method = "setSpawn", at = @At("HEAD")) + private static void arclight$cause(CommandSourceStack p_138650_, Collection players, BlockPos p_138652_, float p_138653_, CallbackInfoReturnable cir) { + for (ServerPlayer player : players) { + ((ServerPlayerEntityBridge) player).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.COMMAND); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java index a5a0ca00..1421040b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java @@ -66,11 +66,7 @@ import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.craftbukkit.v.util.CraftChatMessage; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.player.*; import org.spigotmc.SpigotConfig; import org.spigotmc.event.player.PlayerSpawnLocationEvent; import org.spongepowered.asm.mixin.Final; @@ -298,12 +294,13 @@ public abstract class PlayerListMixin implements PlayerListBridge { f2 = (float) Mth.wrapDegrees(Mth.atan2(vec3d2.z, vec3d2.x) * 57.2957763671875 - 90.0); } // playerIn.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, f2, 0.0f); - playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); + // playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); flag3 = (!flag && flag4); isBedSpawn = true; location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), vec3d.x, vec3d.y, vec3d.z); } else if (pos != null) { playerIn.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0f)); + ((ServerPlayerEntityBridge) playerIn).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESET); playerIn.setRespawnPosition(Level.OVERWORLD, null, 0f, false, false); // CraftBukkit - SPIGOT-5988: Clear respawn location when obstructed } } @@ -419,12 +416,13 @@ public abstract class PlayerListMixin implements PlayerListBridge { f2 = (float) Mth.wrapDegrees(Mth.atan2(vec3d2.z, vec3d2.x) * 57.2957763671875 - 90.0); } // playerIn.setLocationAndAngles(vec3d.x, vec3d.y, vec3d.z, f2, 0.0f); - playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); + // playerIn.setRespawnPosition(spawnWorld.dimension(), pos, f2, flag2, false); flag3 = (!flag2 && flag4); isBedSpawn = true; location = new Location(((WorldBridge) spawnWorld).bridge$getWorld(), vec3d.x, vec3d.y, vec3d.z); } else if (pos != null) { playerIn.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.NO_RESPAWN_BLOCK_AVAILABLE, 0.0f)); + ((ServerPlayerEntityBridge) playerIn).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESET); playerIn.setRespawnPosition(Level.OVERWORLD, null, 0f, false, false); } } @@ -462,7 +460,7 @@ public abstract class PlayerListMixin implements PlayerListBridge { serverplayerentity.connection = playerIn.connection; serverplayerentity.restoreFrom(playerIn, conqueredEnd); serverplayerentity.setRespawnPosition(playerIn.getRespawnDimension(), playerIn.getRespawnPosition(), - playerIn.getRespawnAngle(), playerIn.isRespawnForced(), false); + playerIn.getRespawnAngle(), playerIn.isRespawnForced(), false); if (!conqueredEnd) { // keep inventory here since inventory dropped at ServerPlayerEntity#onDeath serverplayerentity.getInventory().replaceWith(playerIn.getInventory()); } 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 7f6859ef..e6c6cf3d 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 @@ -26,6 +26,8 @@ import net.minecraft.world.level.ExplosionDamageCalculator; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.BaseFireBlock; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.TntBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; @@ -40,12 +42,9 @@ import org.bukkit.Location; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.TNTPrimeEvent; import org.bukkit.event.entity.EntityExplodeEvent; -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.*; import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -85,7 +84,7 @@ public abstract class ExplosionMixin implements ExplosionBridge { // @formatter:on @Inject(method = "(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/Entity;DDDFZLnet/minecraft/world/level/Explosion$BlockInteraction;)V", - at = @At("RETURN")) + at = @At("RETURN")) public void arclight$adjustSize(Level worldIn, Entity exploderIn, double xIn, double yIn, double zIn, float sizeIn, boolean causesFireIn, Explosion.BlockInteraction modeIn, CallbackInfo ci) { this.radius = Math.max(sizeIn, 0F); } @@ -271,6 +270,16 @@ public abstract class ExplosionMixin implements ExplosionBridge { for (BlockPos blockpos : this.toBlow) { BlockState blockstate = this.level.getBlockState(blockpos); Block block = blockstate.getBlock(); + // CraftBukkit start - TNTPrimeEvent + if (block instanceof TntBlock) { + var sourceEntity = source == null ? null : source; + var sourceBlock = sourceEntity == null ? BlockPos.containing(this.x, this.y, this.z) : null; + if (!CraftEventFactory.callTNTPrimeEvent(this.level, blockpos, TNTPrimeEvent.PrimeCause.EXPLOSION, sourceEntity, sourceBlock)) { + this.level.sendBlockUpdated(blockpos, Blocks.AIR.defaultBlockState(), blockstate, 3); // Update the block on the client + continue; + } + } + // CraftBukkit end if (!blockstate.isAir()) { BlockPos blockpos1 = blockpos.immutable(); this.level.getProfiler().push("explosion_blocks"); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java index 584c6329..1b7ae939 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/ExperienceOrbMixin.java @@ -12,6 +12,8 @@ import org.bukkit.craftbukkit.v.entity.CraftLivingEntity; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.EntityTargetEvent; import org.bukkit.event.entity.EntityTargetLivingEntityEvent; +import org.bukkit.event.player.PlayerExpCooldownChangeEvent; +import org.objectweb.asm.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; @@ -67,6 +69,11 @@ public abstract class ExperienceOrbMixin extends EntityMixin { player.giveExperiencePoints(CraftEventFactory.callPlayerExpChangeEvent(player, amount).getAmount()); } + @Redirect(method = "playerTouch", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/world/entity/player/Player;takeXpDelay:I")) + private void arclight$cooldown(Player instance, int value) { + instance.takeXpDelay = CraftEventFactory.callPlayerXpCooldownEvent(instance, value, PlayerExpCooldownChangeEvent.ChangeReason.PICKUP_ORB).getNewCooldown(); + } + /** * @author IzzelAliz * @reason diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java index 6ce2f650..eb86b775 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/player/ServerPlayerMixin.java @@ -10,6 +10,7 @@ import io.izzel.arclight.common.bridge.core.network.play.ServerPlayNetHandlerBri import io.izzel.arclight.common.bridge.core.util.FoodStatsBridge; import io.izzel.arclight.common.bridge.core.world.TeleporterBridge; import io.izzel.arclight.common.bridge.core.world.WorldBridge; +import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.mod.server.block.ChestBlockDoubleInventoryHacks; import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.BlockUtil; @@ -99,13 +100,7 @@ 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.player.PlayerBedLeaveEvent; -import org.bukkit.event.player.PlayerChangedMainHandEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerLocaleChangeEvent; -import org.bukkit.event.player.PlayerPortalEvent; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.event.player.PlayerToggleSneakEvent; +import org.bukkit.event.player.*; import org.bukkit.event.world.PortalCreateEvent; import org.bukkit.inventory.MainHand; import org.spongepowered.asm.mixin.Final; @@ -160,7 +155,6 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla @Shadow protected abstract void tellNeutralMobsThatIDied(); @Shadow protected abstract void createEndPlatform(ServerLevel p_242110_1_, BlockPos p_242110_2_); @Shadow public abstract boolean isCreative(); - @Shadow public abstract void setRespawnPosition(ResourceKey p_242111_1_, @org.jetbrains.annotations.Nullable BlockPos p_242111_2_, float p_242111_3_, boolean p_242111_4_, boolean p_242111_5_); @Shadow protected abstract boolean bedBlocked(BlockPos p_241156_1_, Direction p_241156_2_); @Shadow protected abstract boolean bedInRange(BlockPos p_241147_1_, Direction p_241147_2_); @Shadow public abstract void setLevel(ServerLevel p_143426_); @@ -170,6 +164,10 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla @Shadow public abstract void shadow$nextContainerCounter(); @Shadow public abstract void initMenu(AbstractContainerMenu p_143400_); @Shadow public abstract boolean teleportTo(ServerLevel p_265564_, double p_265424_, double p_265680_, double p_265312_, Set p_265192_, float p_265059_, float p_265266_); + @Shadow @Nullable private BlockPos respawnPosition; + @Shadow public abstract void sendSystemMessage(Component p_215097_); + @Shadow private float respawnAngle; + @Shadow private boolean respawnForced; // @formatter:on public String displayName; @@ -521,7 +519,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla if (registrykey == LevelStem.OVERWORLD && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.NETHER) { this.enteredNetherPosition = this.position(); } else if (spawnPortal && ((WorldBridge) exitWorld[0]).bridge$getTypeKey() == LevelStem.END - && (((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo() == null || ((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo().getCanCreatePortal())) { + && (((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo() == null || ((PortalInfoBridge) portalinfo).bridge$getPortalEventInfo().getCanCreatePortal())) { this.createEndPlatform(exitWorld[0], BlockPos.containing(portalinfo.pos)); } } @@ -648,7 +646,7 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla if (this.bedBlocked(blockposition, enumdirection)) { return Either.left(Player.BedSleepingProblem.OBSTRUCTED); } - this.setRespawnPosition(this.level.dimension(), blockposition, this.getYRot(), false, true); + this.setRespawnPosition(this.level.dimension(), blockposition, this.getYRot(), false, true, PlayerSpawnChangeEvent.Cause.BED); if (this.level.isDay()) { return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW); } @@ -677,6 +675,11 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla return arclight$fireBedEvent(either, pos).ifRight(consumer); } + @Inject(method = "startSleepInBed", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) + private void arclight$bedCause(BlockPos p_9115_, CallbackInfoReturnable> cir) { + this.bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.BED); + } + @SuppressWarnings("unchecked") private Either arclight$fireBedEvent(Either e, BlockPos pos) { Either either = (Either) e; @@ -948,6 +951,68 @@ public abstract class ServerPlayerMixin extends PlayerMixin implements ServerPla return super.isImmobile() || !this.getBukkitEntity().isOnline(); } + private transient PlayerSpawnChangeEvent.Cause arclight$spawnChangeCause; + + @Override + public void bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause cause) { + this.arclight$spawnChangeCause = cause; + } + + public void setRespawnPosition(ResourceKey p_9159_, @Nullable BlockPos p_9160_, float p_9161_, boolean p_9162_, boolean p_9163_, PlayerSpawnChangeEvent.Cause cause) { + arclight$spawnChangeCause = cause; + this.setRespawnPosition(p_9159_, p_9160_, p_9161_, p_9162_, p_9163_); + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void setRespawnPosition(ResourceKey p_9159_, @Nullable BlockPos p_9160_, float p_9161_, boolean p_9162_, boolean p_9163_) { + if (ForgeEventFactory.onPlayerSpawnSet((ServerPlayer) (Object) this, p_9160_ == null ? Level.OVERWORLD : p_9159_, p_9160_, p_9162_)) + return; + var cause = arclight$spawnChangeCause == null ? PlayerSpawnChangeEvent.Cause.UNKNOWN : arclight$spawnChangeCause; + arclight$spawnChangeCause = null; + var newWorld = this.server.getLevel(p_9159_); + Location newSpawn = (p_9160_ != null) ? new Location(((ServerWorldBridge) newWorld).bridge$getWorld(), p_9160_.getX(), p_9160_.getY(), p_9160_.getZ(), p_9161_, 0) : null; + + PlayerSpawnChangeEvent event = new PlayerSpawnChangeEvent(this.getBukkitEntity(), newSpawn, p_9162_, cause); + Bukkit.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return; + } + newSpawn = event.getNewSpawn(); + p_9162_ = event.isForced(); + + if (newSpawn != null) { + p_9159_ = ((CraftWorld) newSpawn.getWorld()).getHandle().dimension(); + p_9160_ = BlockPos.containing(newSpawn.getX(), newSpawn.getY(), newSpawn.getZ()); + p_9161_ = newSpawn.getYaw(); + } else { + p_9159_ = Level.OVERWORLD; + p_9160_ = null; + p_9161_ = 0.0F; + } + + if (p_9160_ != null) { + boolean flag = p_9160_.equals(this.respawnPosition) && p_9159_.equals(this.respawnDimension); + if (p_9163_ && !flag) { + this.sendSystemMessage(Component.translatable("block.minecraft.set_spawn")); + } + + this.respawnPosition = p_9160_; + this.respawnDimension = p_9159_; + this.respawnAngle = p_9161_; + this.respawnForced = p_9162_; + } else { + this.respawnPosition = null; + this.respawnDimension = Level.OVERWORLD; + this.respawnAngle = 0.0F; + this.respawnForced = false; + } + + } + @Override public Scoreboard getScoreboard() { return this.getBukkitEntity().getScoreboard().getHandle(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java index 53503d39..627c83d8 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/projectile/FishingHookMixin.java @@ -9,12 +9,14 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stats; import net.minecraft.tags.ItemTags; import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraft.world.level.storage.loot.BuiltInLootTables; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.LootTable; @@ -54,7 +56,13 @@ public abstract class FishingHookMixin extends ProjectileMixin { public int minWaitTime = 100; public int maxWaitTime = 600; + public int minLureTime = 20; + public int maxLureTime = 80; + public float minLureAngle = 0.0F; + public float maxLureAngle = 360.0F; public boolean applyLure = true; + public boolean rainInfluenced = true; + public boolean skyInfluenced = true; @Redirect(method = "checkCollision", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/FishingHook;onHit(Lnet/minecraft/world/phys/HitResult;)V")) private void arclight$collide(FishingHook fishingHook, HitResult hitResult) { @@ -84,6 +92,26 @@ public abstract class FishingHookMixin extends ProjectileMixin { } } + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;isRainingAt(Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$rainInfluenced(Level level, BlockPos pos) { + return this.rainInfluenced && level.isRainingAt(pos); + } + + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;canSeeSky(Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$skyInfluenced(Level instance, BlockPos blockPos) { + return this.skyInfluenced && instance.canSeeSky(blockPos); + } + + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/util/Mth;nextFloat(Lnet/minecraft/util/RandomSource;FF)F")) + private float arclight$lureAngleParam(RandomSource random, float p_216269_, float p_216270_) { + return Mth.nextFloat(random, this.minLureAngle, this.maxLureAngle); + } + + @Redirect(method = "catchingFish", at = @At(value = "INVOKE", ordinal = 2, target = "Lnet/minecraft/util/Mth;nextInt(Lnet/minecraft/util/RandomSource;II)I")) + private int arclight$lureTimeParam(RandomSource random, int p_216273_, int p_216274_) { + return Mth.nextInt(random, this.minLureTime, this.maxLureTime); + } + /** * @author IzzelAliz * @reason diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java index 4414d9f1..c8a66780 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/FireBlockMixin.java @@ -11,6 +11,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.FireBlock; +import net.minecraft.world.level.block.TntBlock; import net.minecraft.world.level.block.state.BlockState; import org.bukkit.Bukkit; import org.bukkit.block.Block; @@ -20,6 +21,7 @@ import org.bukkit.craftbukkit.v.block.CraftBlockStates; import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.block.BlockFadeEvent; +import org.bukkit.event.block.TNTPrimeEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -63,6 +65,10 @@ public abstract class FireBlockMixin extends BaseFireBlockMixin implements FireB Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { ci.cancel(); + return; + } + if (worldIn.getBlockState(pos).getBlock() instanceof TntBlock && !CraftEventFactory.callTNTPrimeEvent(worldIn, pos, TNTPrimeEvent.PrimeCause.FIRE, null, pos.relative(face))) { + ci.cancel(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java new file mode 100644 index 00000000..4c883019 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/RespawnAnchorBlockMixin.java @@ -0,0 +1,25 @@ +package io.izzel.arclight.common.mixin.core.world.level.block; + +import io.izzel.arclight.common.bridge.core.entity.player.ServerPlayerEntityBridge; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.RespawnAnchorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.BlockHitResult; +import org.bukkit.event.player.PlayerSpawnChangeEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(RespawnAnchorBlock.class) +public class RespawnAnchorBlockMixin { + + @Inject(method = "use", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerPlayer;setRespawnPosition(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/BlockPos;FZZ)V")) + private void arclight$cause(BlockState p_55874_, Level p_55875_, BlockPos p_55876_, Player player, InteractionHand p_55878_, BlockHitResult p_55879_, CallbackInfoReturnable cir) { + ((ServerPlayerEntityBridge) player).bridge$pushChangeSpawnCause(PlayerSpawnChangeEvent.Cause.RESPAWN_ANCHOR); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java index bfd70067..8d9eba5d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/block/TntBlockMixin.java @@ -1,23 +1,59 @@ package io.izzel.arclight.common.mixin.core.world.level.block; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.Projectile; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.TntBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import org.bukkit.craftbukkit.v.event.CraftEventFactory; +import org.bukkit.event.block.TNTPrimeEvent; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(TntBlock.class) -public class TntBlockMixin { +public abstract class TntBlockMixin { + + @Redirect(method = "onPlace", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;hasNeighborSignal(Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$redstone1(Level instance, BlockPos pos) { + return instance.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(instance, pos, TNTPrimeEvent.PrimeCause.REDSTONE, null, null); + } + + @Redirect(method = "neighborChanged", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/Level;hasNeighborSignal(Lnet/minecraft/core/BlockPos;)Z")) + private boolean arclight$redstone2(Level instance, BlockPos pos, BlockState p_57457_, Level p_57458_, BlockPos p_57459_, Block p_57460_, BlockPos source) { + return instance.hasNeighborSignal(pos) && CraftEventFactory.callTNTPrimeEvent(instance, pos, TNTPrimeEvent.PrimeCause.REDSTONE, null, source); + } + + @Redirect(method = "playerWillDestroy", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$playerBreak(TntBlock instance, BlockState state, Level world, BlockPos pos, Direction face, LivingEntity igniter, + Level p_57445_, BlockPos p_57446_, BlockState p_57447_, Player player) { + if (CraftEventFactory.callTNTPrimeEvent(world, pos, TNTPrimeEvent.PrimeCause.BLOCK_BREAK, player, null)) { + instance.onCaughtFire(state, world, pos, face, igniter); + } + } + + @Inject(method = "use", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) + private void arclight$player(BlockState p_57450_, Level level, BlockPos pos, Player player, InteractionHand p_57454_, BlockHitResult p_57455_, CallbackInfoReturnable cir) { + if (!CraftEventFactory.callTNTPrimeEvent(level, pos, TNTPrimeEvent.PrimeCause.PLAYER, player, null)) { + cir.setReturnValue(InteractionResult.CONSUME); + } + } @Inject(method = "onProjectileHit", cancellable = true, at = @At(value = "INVOKE", remap = false, target = "Lnet/minecraft/world/level/block/TntBlock;onCaughtFire(Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;Lnet/minecraft/core/Direction;Lnet/minecraft/world/entity/LivingEntity;)V")) public void arclight$entityChangeBlock(Level worldIn, BlockState state, BlockHitResult hit, Projectile projectile, CallbackInfo ci) { - if (CraftEventFactory.callEntityChangeBlockEvent(projectile, hit.getBlockPos(), Blocks.AIR.defaultBlockState()).isCancelled()) { + if (CraftEventFactory.callEntityChangeBlockEvent(projectile, hit.getBlockPos(), Blocks.AIR.defaultBlockState()).isCancelled() + || !CraftEventFactory.callTNTPrimeEvent(worldIn, hit.getBlockPos(), TNTPrimeEvent.PrimeCause.PROJECTILE, projectile, null)) { ci.cancel(); } } diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index 2ca68cf2..21a504ee 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -56,6 +56,7 @@ "server.commands.EffectCommandMixin", "server.commands.GameRuleCommandMixin", "server.commands.ReloadCommandMixin", + "server.commands.SetSpawnCommandMixin", "server.commands.SummonCommandMixin", "server.commands.TeleportCommandMixin", "server.commands.TimeCommandMixin", @@ -411,6 +412,7 @@ "world.level.block.RedstoneOreBlockMixin", "world.level.block.RedstoneTorchBlockMixin", "world.level.block.RedstoneWireBlockMixin", + "world.level.block.RespawnAnchorBlockMixin", "world.level.block.RootedDirtBlockMixin", "world.level.block.SaplingBlockMixin", "world.level.block.ScaffoldingBlockMixin", diff --git a/arclight-forge/build.gradle b/arclight-forge/build.gradle index 682eed7b..0dbc8426 100644 --- a/arclight-forge/build.gradle +++ b/arclight-forge/build.gradle @@ -43,7 +43,7 @@ repositories { } def embedLibs = [/*"org.spongepowered:mixin:$mixinVersion", */ 'org.yaml:snakeyaml:1.33', - 'org.xerial:sqlite-jdbc:3.41.0.0', 'com.mysql:mysql-connector-j:8.0.32', + 'org.xerial:sqlite-jdbc:3.41.2.2', 'com.mysql:mysql-connector-j:8.0.32', /*'commons-lang:commons-lang:2.6',*/ 'com.googlecode.json-simple:json-simple:1.1.1', 'org.apache.logging.log4j:log4j-jul:2.17.2', 'net.md-5:SpecialSource:1.11.0', 'org.jline:jline-terminal-jansi:3.12.1', 'org.fusesource.jansi:jansi:1.18',