Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ dependencies {
compileOnly("curse.maven:cofh-lib-220333:2388748") {transitive = false}
compileOnly("curse.maven:cofh-core-69162:2388751") {transitive = false}
compileOnly("curse.maven:witchery-69673:2234410") {transitive = false}

compileOnly('org.jetbrains:annotations:26.0.1')
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected void onImpact(MovingObjectPosition pos) {
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(
Expand Down
143 changes: 138 additions & 5 deletions src/main/java/fox/spiteful/avaritia/entity/EntityGapingVoid.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -29,6 +52,15 @@ public EntityGapingVoid(World world) {
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);
Expand All @@ -43,7 +75,9 @@ public void onUpdate() {
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) {
Expand Down Expand Up @@ -188,7 +222,7 @@ public void onUpdate() {
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);
}
Expand All @@ -210,11 +244,48 @@ public int getAge() {
@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) {
Expand Down Expand Up @@ -243,6 +314,68 @@ public float getShadowSize() {
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;
}
}
Loading