From 32f68d25c3d4c6c9ac11c027bbef880d219502fd Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 30 Mar 2023 15:04:05 +0200 Subject: [PATCH] Second Identity - Deployers no longer fail to activate in chunks claimed or protected by the player that placed them --- .../components/deployer/DeployerBlock.java | 9 +++ .../deployer/DeployerBlockEntity.java | 12 +++- .../deployer/DeployerFakePlayer.java | 67 +++++++++++++++++-- .../deployer/DeployerMovementBehaviour.java | 4 +- .../deployer/DeployerMovingInteraction.java | 5 +- 5 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java index 9ca3d723b..41d6c73d5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlock.java @@ -12,8 +12,10 @@ import com.simibubi.create.foundation.block.IBE; import net.minecraft.MethodsReturnNonnullByDefault; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; @@ -57,6 +59,13 @@ public class DeployerBlock extends DirectionalAxisKineticBlock implements IBE dbe.owner = placer.getUUID()); + } + @Override public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) { if (!isMoving && !state.is(newState.getBlock())) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlockEntity.java index f2c9fbbe7..56f95723c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerBlockEntity.java @@ -5,6 +5,7 @@ import static com.simibubi.create.content.contraptions.base.DirectionalKineticBl import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.UUID; import javax.annotation.Nullable; @@ -75,6 +76,7 @@ public class DeployerBlockEntity extends KineticBlockEntity { protected List overflowItems = new ArrayList<>(); protected FilteringBehaviour filtering; protected boolean redstoneLocked; + protected UUID owner; private LazyOptional invHandler; private ListTag deferredInventoryList; @@ -125,7 +127,7 @@ public class DeployerBlockEntity extends KineticBlockEntity { if (invHandler != null) return; if (level instanceof ServerLevel sLevel) { - player = new DeployerFakePlayer(sLevel); + player = new DeployerFakePlayer(sLevel, owner); if (deferredInventoryList != null) { player.getInventory() .load(deferredInventoryList); @@ -350,6 +352,8 @@ public class DeployerBlockEntity extends KineticBlockEntity { mode = NBTHelper.readEnum(compound, "Mode", Mode.class); timer = compound.getInt("Timer"); redstoneLocked = compound.getBoolean("Powered"); + if (compound.contains("Owner")) + owner = compound.getUUID("Owner"); deferredInventoryList = compound.getList("Inventory", Tag.TAG_COMPOUND); overflowItems = NBTHelper.readItemList(compound.getList("Overflow", Tag.TAG_COMPOUND)); @@ -374,6 +378,8 @@ public class DeployerBlockEntity extends KineticBlockEntity { NBTHelper.writeEnum(compound, "State", state); compound.putInt("Timer", timer); compound.putBoolean("Powered", redstoneLocked); + if (owner != null) + compound.putUUID("Owner", owner); if (player != null) { ListTag invNBT = new ListTag(); @@ -489,8 +495,8 @@ public class DeployerBlockEntity extends KineticBlockEntity { .forGoggles(tooltip); if (!heldItem.isEmpty()) - Lang.translate("tooltip.deployer.contains", - Components.translatable(heldItem.getDescriptionId()).getString(), heldItem.getCount()) + Lang.translate("tooltip.deployer.contains", Components.translatable(heldItem.getDescriptionId()) + .getString(), heldItem.getCount()) .style(ChatFormatting.GREEN) .forGoggles(tooltip); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java index d904ab5c0..5598f2c45 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerFakePlayer.java @@ -1,8 +1,11 @@ package com.simibubi.create.content.contraptions.components.deployer; +import java.util.Objects; import java.util.OptionalInt; import java.util.UUID; +import javax.annotation.Nullable; + import org.apache.commons.lang3.tuple.Pair; import com.mojang.authlib.GameProfile; @@ -23,6 +26,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.MenuProvider; import net.minecraft.world.damagesource.EntityDamageSource; +import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; @@ -33,6 +37,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.UsernameCache; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; @@ -46,16 +51,17 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber; public class DeployerFakePlayer extends FakePlayer { private static final Connection NETWORK_MANAGER = new Connection(PacketFlow.CLIENTBOUND); - public static final GameProfile DEPLOYER_PROFILE = - new GameProfile(UUID.fromString("9e2faded-cafe-4ec2-c314-dad129ae971d"), "Deployer"); + public static final UUID fallbackID = UUID.fromString("9e2faded-cafe-4ec2-c314-dad129ae971d"); Pair blockBreakingProgress; ItemStack spawnedItemEffects; public boolean placedTracks; public boolean onMinecartContraption; + private UUID owner; - public DeployerFakePlayer(ServerLevel world) { - super(world, DEPLOYER_PROFILE); + public DeployerFakePlayer(ServerLevel world, @Nullable UUID owner) { + super(world, new DeployerGameProfile(fallbackID, "Deployer", owner)); connection = new FakePlayNetHandler(world.getServer(), this); + this.owner = owner; } @Override @@ -95,6 +101,16 @@ public class DeployerFakePlayer extends FakePlayer { return stack; } + @Override + public boolean canBeAffected(MobEffectInstance pEffectInstance) { + return false; + } + + @Override + public UUID getUUID() { + return owner == null ? super.getUUID() : owner; + } + @SubscribeEvent public static void deployerHasEyesOnHisFeet(EntityEvent.Size event) { if (event.getEntity() instanceof DeployerFakePlayer) @@ -156,6 +172,49 @@ public class DeployerFakePlayer extends FakePlayer { } } + // Credit to Mekanism for this approach. Helps fake players get past claims and + // protection by other mods + private static class DeployerGameProfile extends GameProfile { + + private UUID owner; + + public DeployerGameProfile(UUID id, String name, UUID owner) { + super(id, name); + this.owner = owner; + } + + @Override + public UUID getId() { + return owner == null ? super.getId() : owner; + } + + @Override + public String getName() { + if (owner == null) + return super.getName(); + String lastKnownUsername = UsernameCache.getLastKnownUsername(owner); + return lastKnownUsername == null ? super.getName() : lastKnownUsername; + } + + @Override + public boolean equals(final Object o) { + if (this == o) + return true; + if (!(o instanceof GameProfile otherProfile)) + return false; + return Objects.equals(getId(), otherProfile.getId()) && Objects.equals(getName(), otherProfile.getName()); + } + + @Override + public int hashCode() { + UUID id = getId(); + String name = getName(); + int result = id == null ? 0 : id.hashCode(); + result = 31 * result + (name == null ? 0 : name.hashCode()); + return result; + } + } + private static class FakePlayNetHandler extends ServerGamePacketListenerImpl { public FakePlayNetHandler(MinecraftServer server, ServerPlayer playerIn) { super(server, NETWORK_MANAGER, playerIn); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java index 496403c3a..7482d3b23 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.deployer; import java.util.Arrays; import java.util.List; +import java.util.UUID; import javax.annotation.Nullable; @@ -274,7 +275,8 @@ public class DeployerMovementBehaviour implements MovementBehaviour { private DeployerFakePlayer getPlayer(MovementContext context) { if (!(context.temporaryData instanceof DeployerFakePlayer) && context.world instanceof ServerLevel) { - DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) context.world); + UUID owner = context.blockEntityData.contains("Owner") ? context.blockEntityData.getUUID("Owner") : null; + DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) context.world, owner); deployerFakePlayer.onMinecartContraption = context.contraption instanceof MountedContraption; deployerFakePlayer.getInventory() .load(context.blockEntityData.getList("Inventory", Tag.TAG_COMPOUND)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java index 95910e376..d4a4ccb55 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovingInteraction.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.components.deployer; +import java.util.UUID; + import org.apache.commons.lang3.tuple.MutablePair; import com.simibubi.create.AllItems; @@ -41,7 +43,8 @@ public class DeployerMovingInteraction extends MovingInteractionBehaviour { DeployerFakePlayer fake = null; if (!(ctx.temporaryData instanceof DeployerFakePlayer) && ctx.world instanceof ServerLevel) { - DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) ctx.world); + UUID owner = ctx.blockEntityData.contains("Owner") ? ctx.blockEntityData.getUUID("Owner") : null; + DeployerFakePlayer deployerFakePlayer = new DeployerFakePlayer((ServerLevel) ctx.world, owner); deployerFakePlayer.onMinecartContraption = ctx.contraption instanceof MountedContraption; deployerFakePlayer.getInventory() .load(ctx.blockEntityData.getList("Inventory", Tag.TAG_COMPOUND));