Skip to content

Instantly share code, notes, and snippets.

@Vatuu
Created April 30, 2020 16:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Vatuu/a6ab9c759bd813be9b0ee5e49e109d99 to your computer and use it in GitHub Desktop.
Save Vatuu/a6ab9c759bd813be9b0ee5e49e109d99 to your computer and use it in GitHub Desktop.
A entity template for spellcasting entities, with a spell registry and all.
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.goal.Goal;
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.mob.HostileEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import javax.management.InvalidAttributeValueException;
import java.util.HashMap;
import java.util.function.Consumer;
public abstract class SpellcastingEntity extends HostileEntity {
private Spell spell;
private int spellTicks;
public SpellcastingEntity(EntityType<? extends SpellcastingEntity> type, World w) {
super(type, w);
this.spell = Spell.NONE;
}
protected abstract SoundEvent getCastSpellSound();
protected void initDataTracker() {
super.initDataTracker();
this.dataTracker.startTracking(SPELL, Spell.NONE);
}
public void readCustomDataFromTag(CompoundTag tag) {
super.readCustomDataFromTag(tag);
this.spellTicks = tag.getInt("SpellTicks");
}
public void writeCustomDataToTag(CompoundTag tag) {
super.writeCustomDataToTag(tag);
tag.putInt("SpellTicks", this.spellTicks);
}
public boolean isSpellcasting() {
if (this.world.isClient) {
return !this.dataTracker.get(SPELL).equals(Spell.NONE);
} else {
return this.spellTicks > 0;
}
}
public void setSpell(Spell spell) {
this.spell = spell;
this.dataTracker.set(SPELL, spell);
}
protected Spell getSpell() {
return !this.world.isClient ? this.spell : this.dataTracker.get(SPELL);
}
protected void mobTick() {
super.mobTick();
if (this.spellTicks > 0)
--this.spellTicks;
}
public void tick() {
super.tick();
if (this.world.isClient && this.isSpellcasting())
this.getSpell().spellEffect.accept(this);
}
public static final class SpellRegistry {
private static final HashMap<Identifier, Spell> spells = new HashMap<>();
public static Spell get(Identifier spell) {
try {
return spells.values().stream()
.filter(s -> s.getId().equals(spell))
.findFirst()
.orElseThrow(() -> new InvalidAttributeValueException(String.format("Trying to get unknown spell! [%s]", spell)));
} catch (InvalidAttributeValueException e) {
e.printStackTrace();
return null;
}
}
public static boolean registerSpell(Spell spell) {
if(spells.containsKey(spell.getId()))
return false;
else {
spells.put(spell.getId(), spell);
return true;
}
}
static { registerSpell(Spell.NONE); }
}
public static class Spell {
public static final Spell NONE = new Spell(new Identifier("tessebase", "none"), (e) -> {});
private final Identifier id;
private final Consumer<SpellcastingEntity> spellEffect;
public Spell(Identifier id, Consumer<SpellcastingEntity> t) {
this.id = id;
this.spellEffect = t;
}
public Identifier getId() {
return id;
}
public boolean equals(Object o) {
if(!(o instanceof Spell))
return false;
else
return ((Spell)o).getId().equals(id);
}
}
public abstract class CastSpellGoal extends Goal {
protected int spellCooldown;
protected int startTime;
protected CastSpellGoal() { }
public boolean canStart() {
LivingEntity livingEntity = SpellcastingEntity.this.getTarget();
if (livingEntity != null && livingEntity.isAlive()) {
if (SpellcastingEntity.this.isSpellcasting())
return false;
else
return SpellcastingEntity.this.age >= this.startTime;
} else
return false;
}
public boolean shouldContinue() {
LivingEntity livingEntity = SpellcastingEntity.this.getTarget();
return livingEntity != null && livingEntity.isAlive() && this.spellCooldown > 0;
}
public void start() {
this.spellCooldown = this.getInitialCooldown();
SpellcastingEntity.this.spellTicks = this.getSpellTicks();
this.startTime = SpellcastingEntity.this.age + this.startTimeDelay();
SoundEvent soundEvent = this.getSoundPrepare();
if (soundEvent != null)
SpellcastingEntity.this.playSound(soundEvent, 1.0F, 1.0F);
SpellcastingEntity.this.setSpell(this.getSpell());
}
public void tick() {
--this.spellCooldown;
if (this.spellCooldown == 0) {
this.castSpell();
SpellcastingEntity.this.playSound(SpellcastingEntity.this.getCastSpellSound(), 1.0F, 1.0F);
}
}
protected int getInitialCooldown() {
return 20;
}
protected abstract void castSpell();
protected abstract int getSpellTicks();
protected abstract int startTimeDelay();
protected abstract SoundEvent getSoundPrepare();
protected abstract Spell getSpell();
}
private static final TrackedDataHandler<Spell> TRACKED_SPELL = new TrackedDataHandler<Spell>() {
@Override
public void write(PacketByteBuf data, Spell spell) {
data.writeString(spell.getId().toString());
}
@Override
public Spell read(PacketByteBuf buf) {
return SpellRegistry.get(new Identifier(buf.readString()));
}
@Override
public Spell copy(Spell spell) {
return spell;
}
};
private static final TrackedData<Spell> SPELL = DataTracker.registerData(SpellcastingEntity.class, TRACKED_SPELL);
static {
TrackedDataHandlerRegistry.register(TRACKED_SPELL);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment