This repository has been archived on 2023-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
Herobrine-Rewoven/src/main/java/com/thebrokenrail/herobrine/entity/HerobrineEntity.java

304 lines
11 KiB
Java

package com.thebrokenrail.herobrine.entity;
import com.thebrokenrail.herobrine.HerobrineRewoven;
import com.thebrokenrail.herobrine.config.HardcodedConfig;
import com.thebrokenrail.herobrine.data.HerobrineData;
import com.thebrokenrail.herobrine.entity.ai.HerobrineAI;
import com.thebrokenrail.herobrine.entity.ai.stage.TeleportStage;
import net.minecraft.block.BlockState;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.boss.BossBar;
import net.minecraft.entity.boss.ServerBossBar;
import net.minecraft.entity.boss.WitherEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.data.DataTracker;
import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandler;
import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.MessageType;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText;
import net.minecraft.util.Arm;
import net.minecraft.util.Formatting;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.Difficulty;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@SuppressWarnings("EntityConstructor")
public class HerobrineEntity extends LivingEntity {
private static final TrackedDataHandler<Pose> POSE_HANDLER = new TrackedDataHandler<Pose>() {
@Override
public void write(PacketByteBuf data, Pose object) {
data.writeEnumConstant(object);
}
@Override
public Pose read(PacketByteBuf packetByteBuf) {
return packetByteBuf.readEnumConstant(Pose.class);
}
@Override
public Pose copy(Pose object) {
return object;
}
};
static {
TrackedDataHandlerRegistry.register(POSE_HANDLER);
}
public static final TrackedData<Pose> POSE = DataTracker.registerData(HerobrineEntity.class, POSE_HANDLER);
private final ServerBossBar bossBar;
private final List<ServerPlayerEntity> tracking = new ArrayList<>();
private int noPlayerTeleportCountdown = HardcodedConfig.HEROBRINE_NO_PLAYER_TELEPORT_COUNTDOWN;
private final HerobrineAI ai = new HerobrineAI(this);
public HerobrineEntity(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
bossBar = new ServerBossBar(getDisplayName(), BossBar.Color.RED, BossBar.Style.PROGRESS);
setHealth(getMaxHealth());
if (world.random.nextDouble() <= 0.001) {
setCustomName(new TranslatableText("entity." + HerobrineRewoven.NAMESPACE + ".herobrine/easter_egg"));
}
noClip = true;
}
@Override
protected void initDataTracker() {
super.initDataTracker();
getDataTracker().startTracking(POSE, Pose.NORMAL);
}
@Override
public void setCustomName(Text name) {
super.setCustomName(name);
bossBar.setName(name);
}
@Override
public Iterable<ItemStack> getArmorItems() {
return Collections.emptyList();
}
@Override
public ItemStack getEquippedStack(EquipmentSlot slot) {
if (slot == EquipmentSlot.MAINHAND) {
return new ItemStack(Items.DIAMOND_SWORD);
} else {
return ItemStack.EMPTY;
}
}
@Override
public void equipStack(EquipmentSlot slot, ItemStack stack) {
}
@Override
public Arm getMainArm() {
return Arm.RIGHT;
}
@Override
public boolean isInvulnerableTo(DamageSource damageSource) {
return damageSource == DamageSource.IN_WALL || super.isInvulnerableTo(damageSource);
}
@Override
public boolean hasNoGravity() {
return true;
}
public static DefaultAttributeContainer.Builder createMobAttributes() {
return LivingEntity.createLivingAttributes().add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 1.0D).add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.10000000149011612D).add(EntityAttributes.GENERIC_ATTACK_SPEED).add(EntityAttributes.GENERIC_LUCK).add(EntityAttributes.GENERIC_MAX_HEALTH, HardcodedConfig.HEROBRINE_HEALTH);
}
private int destroyTime = 0;
@Override
public void tick() {
super.tick();
if (!getEntityWorld().isClient()) {
if (getEntityWorld().getDifficulty() == Difficulty.PEACEFUL || HerobrineData.get((ServerWorld) getEntityWorld()).set(getUuid())) {
// Herobrine Already Exists Or Is Peaceful
remove();
} else {
ai.tick();
if (destroyTime > 0) {
destroyTime--;
if (destroyTime == 0 && getEntityWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
int j = MathHelper.floor(this.getY());
int n = MathHelper.floor(this.getX());
int o = MathHelper.floor(this.getZ());
boolean sendEvent = false;
for (int p = -1; p <= 1; p++) {
for (int q = -1; q <= 1; q++) {
for (int r = 0; r <= 3; r++) {
int s = n + p;
int t = j + r;
int u = o + q;
BlockPos blockPos = new BlockPos(s, t, u);
BlockState blockState = getEntityWorld().getBlockState(blockPos);
if (WitherEntity.canDestroy(blockState)) {
sendEvent = getEntityWorld().breakBlock(blockPos, true, this) || sendEvent;
}
}
}
}
if (sendEvent) {
getEntityWorld().syncWorldEvent(null, 1022, this.getBlockPos(), 0);
}
}
} else {
destroyTime = 20;
}
}
}
bossBar.setPercent(getHealth() / getMaxHealth());
}
public String getMessageKey(String id) {
return "entity." + HerobrineRewoven.NAMESPACE + ".herobrine.msg." + id;
}
public void dataTick() {
boolean reset = false;
if (getAI().getStage() instanceof TeleportStage) {
reset = true;
} else {
if (tracking.size() > 0) {
reset = true;
} else if (noPlayerTeleportCountdown == 0) {
reset = true;
List<? extends PlayerEntity> players = getEntityWorld().getPlayers();
if (players.size() > 0 || getNearestPlayer().distanceTo(this) >= HardcodedConfig.HEROBRINE_MAX_DISTANCE) {
while (true) {
PlayerEntity player = players.get(getEntityWorld().random.nextInt(players.size()));
if (player.isAlive()) {
getAI().setStage(new TeleportStage(this, player.getUuid()));
break;
}
}
}
} else {
noPlayerTeleportCountdown--;
}
}
if (reset) {
noPlayerTeleportCountdown = HardcodedConfig.HEROBRINE_NO_PLAYER_TELEPORT_COUNTDOWN;
}
}
@Override
public void onStartedTrackingBy(ServerPlayerEntity player) {
super.onStartedTrackingBy(player);
bossBar.addPlayer(player);
tracking.add(player);
}
@Override
public void onStoppedTrackingBy(ServerPlayerEntity player) {
super.onStoppedTrackingBy(player);
bossBar.removePlayer(player);
tracking.remove(player);
}
public ServerPlayerEntity getNearestPlayer() {
tracking.sort((player1, player2) -> Float.compare(distanceTo(player1), distanceTo(player2)));
if (tracking.size() > 0) {
int i = 0;
while (true) {
if (tracking.get(i).isAlive()) {
return tracking.get(i);
} else {
i++;
}
}
} else {
return null;
}
}
public static void summon(PlayerEntity player) {
HerobrineData data = HerobrineData.get((ServerWorld) player.getEntityWorld());
HerobrineEntity entity = data.get(player.getEntityWorld());
if (entity == null) {
ServerWorld world = Objects.requireNonNull(player.getEntityWorld().getServer()).getWorld(World.OVERWORLD);
entity = new HerobrineEntity(HerobrineRewoven.HEROBRINE_ENTITY_TYPE, world);
entity.updatePosition(0d, 51200d, 0d);
assert world != null;
Objects.requireNonNull(world.getServer().getWorld(World.OVERWORLD)).spawnEntity(entity);
data.set(entity.getUuid());
world.getServer().getPlayerManager().sendToAll(new GameMessageS2CPacket(new TranslatableText("multiplayer.player.joined", entity.getDisplayName()).formatted(Formatting.YELLOW), MessageType.CHAT, Util.NIL_UUID));
entity.getAI().setStage(new TeleportStage(entity, world.getSpawnPos()));
world.getServer().getPlayerManager().sendToAll(new GameMessageS2CPacket(new TranslatableText(entity.getMessageKey("spawn"), entity.getDisplayName()), MessageType.CHAT, Util.NIL_UUID));
}
}
public ServerWorld getServerWorld() {
return (ServerWorld) getEntityWorld();
}
public HerobrineAI getAI() {
return ai;
}
public void handleStageChange() {
getDataTracker().set(POSE, Pose.NORMAL);
}
@Override
public void writeCustomDataToTag(CompoundTag tag) {
super.writeCustomDataToTag(tag);
tag.put("AI", ai.toTag());
tag.putInt("DestroyTime", destroyTime);
}
@Override
public void readCustomDataFromTag(CompoundTag tag) {
super.readCustomDataFromTag(tag);
ai.fromTag(tag.getCompound("AI"));
destroyTime = tag.getInt("DestroyTime");
}
@Override
public void setRotation(float yaw, float pitch) {
super.setRotation(yaw, pitch);
}
public void playSound(SoundEvent sound) {
getEntityWorld().playSound(null, getX(), getY(), getZ(), sound, SoundCategory.HOSTILE, 1.0f, 1.0f);
}
public enum Pose {
NORMAL,
FIREBALL,
LIGHTNING
}
}