Make the Endest Pearl check whether the throwing player has permission to break the affected blocks.

This commit is contained in:
nicksitnikov committed 2026-04-12 00:06:10 -05:00
1 parent 704836810c
commit b276dfd2c7
3 files changed
+143 -7

No files matched your search

+4 -1
View File
@@ -17,5 +17,8 @@ dependencies {
compileOnly("curse.maven:cofh-core-69162:2388751") {transitive = false}
compileOnly("curse.maven:witchery-69673:2234410") {transitive = false}
runtimeOnly("com.github.GTNewHorizons:GTNHLib:0.7.7:dev")
runtimeOnlyNonPublishable("com.github.GTNewHorizons:GTNHLib:0.7.7:dev")
runtimeOnlyNonPublishable("com.github.GTNewHorizons:ServerUtilities:2.2.20:dev")
compileOnly('org.jetbrains:annotations:26.0.1')
}
@@ -42,7 +42,7 @@ public class EntityEndestPearl extends EntityThrowable {
if (!this.worldObj.isRemote) {
// this.worldObj.createExplosion(this, pos.hitVec.xCoord, pos.hitVec.yCoord, pos.hitVec.zCoord, 4.0f, true);
Entity ent = new EntityGapingVoid(this.worldObj);
Entity ent = new EntityGapingVoid(this.worldObj, this.getThrower());
// Entity ent = new EntityChicken(this.worldObj);
ForgeDirection dir = ForgeDirection.getOrientation(pos.sideHit);
ent.setLocationAndAngles(
@@ -1,26 +1,49 @@
package fox.spiteful.avaritia.entity;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Vec3;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.world.BlockEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.mojang.authlib.GameProfile;
import fox.spiteful.avaritia.Config;
public class EntityGapingVoid extends Entity {
public static final int maxLifetime = 186;
public static double collapse = .95;
public static double suckrange = 20.0;
public static final double collapse = .95;
public static final double suckrange = 20.0;
private static final GameProfile defaultProfile = new GameProfile(
UUID.fromString("139a261e-4a64-4d98-8321-e484cfe7c6af"),
"[Endest Pearl]");
private static WeakReference<EntityPlayer> defaultFakePlayer = new WeakReference<>(null);
private @Nullable GameProfile throwerInfo;
private WeakReference<EntityPlayer> thrower;
@SuppressWarnings("unused")
public EntityGapingVoid(World world) {
super(world);
this.isImmuneToFire = true;
@@ -29,6 +52,15 @@ public class EntityGapingVoid extends Entity {
this.renderDistanceWeight = 100.0;
}
public EntityGapingVoid(World world, EntityLivingBase thrower) {
this(world);
if (thrower instanceof EntityPlayer player) {
this.thrower = new WeakReference<>(player);
this.throwerInfo = player.getGameProfile();
}
}
@Override
protected void entityInit() {
dataWatcher.addObject(12, 0);
@@ -43,7 +75,9 @@ public class EntityGapingVoid extends Entity {
int age = this.getAge();
if (age >= maxLifetime) {
this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 6.0f, true);
if (!this.worldObj.isRemote) {
this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 6.0f, true);
}
this.setDead();
} else {
if (age == 0) {
@@ -188,7 +222,7 @@ public class EntityGapingVoid extends Entity {
this.posY,
this.posZ);
if (resist <= 10.0) {
if (resist <= 10.0 && checkPermissions(this.worldObj, lx, ly, lz, b, meta)) {
b.dropBlockAsItemWithChance(worldObj, lx, ly, lz, meta, 0.9f, 0);
this.worldObj.setBlockToAir(lx, ly, lz);
}
@@ -210,11 +244,48 @@ public class EntityGapingVoid extends Entity {
@Override
protected void readEntityFromNBT(NBTTagCompound tag) {
this.setAge(tag.getInteger("age"));
if (tag.hasKey("owner", Constants.NBT.TAG_COMPOUND)) {
NBTTagCompound ownerTag = tag.getCompoundTag("owner");
String name = ownerTag.getString("name");
if (name.isEmpty()) name = null;
UUID uuid;
if (ownerTag.hasKey("uuidLower", Constants.NBT.TAG_LONG)
&& ownerTag.hasKey("uuidUpper", Constants.NBT.TAG_LONG)) {
uuid = new UUID(tag.getLong("uuidUpper"), tag.getLong("uuidLower"));
} else {
uuid = null;
}
if (name != null || uuid != null) {
this.throwerInfo = new GameProfile(uuid, name);
this.thrower = new WeakReference<>(null);
}
}
}
@Override
protected void writeEntityToNBT(NBTTagCompound tag) {
tag.setInteger("age", this.getAge());
if (this.throwerInfo != null) {
NBTTagCompound ownerTag = new NBTTagCompound();
final var ownerName = this.throwerInfo.getName();
if (ownerName != null) {
ownerTag.setString("name", ownerName);
}
final var ownerUUID = this.throwerInfo.getId();
if (ownerUUID != null) {
ownerTag.setLong("uuidUpper", ownerUUID.getMostSignificantBits());
ownerTag.setLong("uuidLower", ownerUUID.getLeastSignificantBits());
}
tag.setTag("owner", ownerTag);
}
}
public static double getVoidScale(double age) {
@@ -243,6 +314,68 @@ public class EntityGapingVoid extends Entity {
public boolean func_145774_a(Explosion explosionIn, World worldIn, int x, int y, int z, Block blockIn,
float unused) {
// Can the final explosion break this block?
return Config.endestGriefing && (Config.endestTileGriefing || worldIn.getTileEntity(x, y, z) == null);
return Config.endestGriefing && (Config.endestTileGriefing || worldIn.getTileEntity(x, y, z) == null)
&& checkPermissions(worldIn, x, y, z, blockIn, worldIn.getBlockMetadata(x, y, z));
}
private boolean checkPermissions(World worldIn, int x, int y, int z, Block block, int meta) {
final var event = new BlockEvent.BreakEvent(x, y, z, worldIn, block, meta, getOwningPlayer());
return !MinecraftForge.EVENT_BUS.post(event);
}
private @NotNull EntityPlayer getOwningPlayer() {
// If throwerInfo is null, this pearl intentionally has no player.
if (this.throwerInfo == null) return getDefaultFakePlayer();
// If we have the player entity cached, return it.
final EntityPlayer thrower = this.thrower.get();
if (thrower != null) return thrower;
// We have the player info, but no player - try to find the player.
final var onlinePlayer = findPlayerByProfile(this.throwerInfo);
if (onlinePlayer != null) {
this.thrower = new WeakReference<>(onlinePlayer);
return onlinePlayer;
}
// If the player is offline, make a fake player that pretends to be that player (same UUID & name)
final var playerMimic = FakePlayerFactory.get((WorldServer) this.worldObj, this.throwerInfo);
playerMimic.setPosition(this.posX, this.posY, this.posZ);
this.thrower = new WeakReference<>(playerMimic);
return playerMimic;
}
private @NotNull EntityPlayer getDefaultFakePlayer() {
EntityPlayer fakePlayer = defaultFakePlayer.get();
if (fakePlayer == null) {
fakePlayer = FakePlayerFactory.get((WorldServer) this.worldObj, defaultProfile);
defaultFakePlayer = new WeakReference<>(fakePlayer);
}
fakePlayer.setWorld(this.worldObj);
fakePlayer.setPosition(this.posX, this.posY, this.posZ);
return fakePlayer;
}
private static @Nullable EntityPlayerMP findPlayerByProfile(GameProfile profile) {
final String throwerName = profile.getName();
final UUID throwerUUID = profile.getId();
final var players = MinecraftServer.getServer().getConfigurationManager().playerEntityList;
if (throwerUUID != null) {
for (var player : players) {
if (throwerUUID.equals(player.getGameProfile().getId())) {
return player;
}
}
} else {
for (var player : players) {
if (throwerName.equals(player.getCommandSenderName())) {
return player;
}
}
}
return null;
}
}