Add entity- and tileentity-sensitive versions of Spell#canBeCastByNPCs and Spell#canBeCastByDispensers

This commit is contained in:
Electroblob77
2020-01-27 16:42:28 +00:00
parent b682740751
commit 3052e56d03
42 changed files with 160 additions and 96 deletions
@@ -433,7 +433,7 @@ public final class Settings {
Property property;
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
property = config.get(SPELLS_CATEGORY, spell.getRegistryName().toString(), true,
I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc"));
// Uses the same config key as the spell name, because - well, that's what it's called!
@@ -547,7 +547,7 @@ public class ClientProxy extends CommonProxy {
data.randomNames = new HashMap<>();
data.randomDescriptions = new HashMap<>();
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
// -1 because the none spell isn't included
// This is a case where we must use the network ID, not the metadata
data.randomNames.put(spell, message.names.get(spell.networkID() - 1));
@@ -190,7 +190,8 @@ public class CommandCastSpell extends CommandBase {
}
if(spell.isContinuous){
// We need not query Spell#canBeCastByDispensers since with commands there's no difference between
// a spell that can't be cast positionally and one that can be cast positionally but fails
if(spell.cast(world, origin.x, origin.y, origin.z, direction, 0, duration, modifiers)){
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, origin.x, origin.y, origin.z, direction, modifiers));
@@ -113,7 +113,7 @@ public class CommandDiscoverSpell extends CommandBase {
if(server.sendCommandFeedback()) sender.sendMessage(
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.clear", player.getName()));
}else if(all){
data.spellsDiscovered.addAll(Spell.getSpells(Spell.allSpells));
data.spellsDiscovered.addAll(Spell.getAllSpells());
if(server.sendCommandFeedback()) sender.sendMessage(
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.all", player.getName()));
}else{
@@ -44,11 +44,11 @@ public class SpellGlyphData extends WorldSavedData {
/** Generates random names and descriptions for any spells which don't already have them. */
public void generateGlyphNames(World world){
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
if(!randomNames.containsKey(spell)) randomNames.put(spell, generateRandomName(world.rand));
}
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
if(!randomDescriptions.containsKey(spell))
randomDescriptions.put(spell, generateRandomDescription(world.rand));
}
@@ -162,7 +162,7 @@ public class SpellGlyphData extends WorldSavedData {
NBTTagList tagList = new NBTTagList();
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
// Much like the enchantments tag for items, this stores a list of spell-id-to-name tag pairs
// The description is now also included; there's no point in making a second compound tag!
NBTTagCompound tag = new NBTTagCompound();
@@ -252,7 +252,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
// When right-clicked with a spell book in creative, sets one of the spells to that spell
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
Spell spell = Spell.byMetadata(stack.getItemDamage());
if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){
if(this.spells.size() >= 4 && spell.canBeCastBy(this, true)){
// The set(...) method returns the element that was replaced - neat!
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
@@ -369,7 +369,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
// All wizards know magic missile, even if it is disabled.
spells.add(Spells.magic_missile);
Tier maxTier = EntityWizard.populateSpells(spells, element, hasStructure, 3, rand);
Tier maxTier = EntityWizard.populateSpells(this, spells, element, hasStructure, 3, rand);
// Now done after the spells so it can take the tier into account. For evil wizards this is slightly different;
// it picks a random wand which is at least a high enough tier for the spells the wizard has.
@@ -359,7 +359,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
// When right-clicked with a spell book in creative, sets one of the spells to that spell
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
Spell spell = Spell.byMetadata(stack.getItemDamage());
if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){
if(this.spells.size() >= 4 && spell.canBeCastBy(this, true)){
// The set(...) method returns the element that was replaced - neat!
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
@@ -752,7 +752,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
// All wizards know magic missile, even if it is disabled.
spells.add(Spells.magic_missile);
Tier maxTier = populateSpells(spells, element, false, 3, rand);
Tier maxTier = populateSpells(this, spells, element, false, 3, rand);
// Now done after the spells so it can take the tier into account.
ItemStack wand = new ItemStack(WizardryItems.getWand(maxTier, element));
@@ -769,19 +769,21 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
/**
* Adds n random spells to the given list. The spells will be of the given element if possible. Extracted as a
* separate function since it was the same in both EntityWizard and EntityEvilWizard.
*
*
* @param wizard The wizard whose spells are to be populated.
* @param spells The spell list to be populated.
* @param e The element that the spells should belong to, or {@link Element#MAGIC} for a random element each time.
* @param master Whether to include master spells.
* @param n The number of spells to add.
* @param random A random number generator to use.
* @return The tier of the highest-tier spell that was added to the list.
*/
static Tier populateSpells(List<Spell> spells, Element e, boolean master, int n, Random random){
static Tier populateSpells(final EntityLiving wizard, List<Spell> spells, Element e, boolean master, int n, Random random){
// This is the tier of the highest tier spell added.
Tier maxTier = Tier.NOVICE;
List<Spell> npcSpells = Spell.getSpells(Spell.npcSpells);
List<Spell> npcSpells = Spell.getSpells(s -> s.canBeCastBy(wizard, false));
npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book));
for(int i = 0; i < n; i++){
@@ -36,7 +36,7 @@ public interface ISpellCaster {
*
* @return A list of {@link Spell} instances. A random spell from this list will be cast when the entity attacks.
* The list will not be modified by the AI class and can therefore be an immutable list. The spells in the
* list <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastByNPCs()} returns true).
* list <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)} returns true).
*/
@Nonnull
public List<Spell> getSpells();
@@ -68,7 +68,7 @@ public interface ISpellCaster {
public void setContinuousSpell(Spell spell);
/**
* Returns the aiming arror for the given difficulty, used in projectile spells. Defaults to the values used by
* Returns the aiming error for the given difficulty, used in projectile spells. Defaults to the values used by
* skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used).
*/
// This is what default methods are actually intended for!
@@ -50,7 +50,7 @@ public class ItemScroll extends Item implements ISpellCastingItem {
if(tab == WizardryTabs.SPELLS){
List<Spell> spells = Spell.getSpells(Spell.allSpells);
List<Spell> spells = Spell.getAllSpells();
spells.removeIf(s -> !s.applicableForItem(this));
for(Spell spell : spells){
@@ -41,7 +41,7 @@ public class ItemSpellBook extends Item {
if(tab == WizardryTabs.SPELLS){
List<Spell> spells = Spell.getSpells(Spell.allSpells);
List<Spell> spells = Spell.getAllSpells();
spells.removeIf(s -> !s.applicableForItem(this));
for(Spell spell : spells){
@@ -62,7 +62,7 @@ public class BehaviourSpellDispense extends BehaviorDispenseOptional {
if(world.isSideSolid(source.getBlockPos().offset(direction), direction.getOpposite())) return stack;
// If the scroll can never be cast by a dispenser, it should be dispensed as an item.
if(!spell.canBeCastByDispensers()) return super.dispenseStack(source, stack);
if(!spell.canBeCastBy(source.getBlockTileEntity())) return super.dispenseStack(source, stack);
SpellModifiers modifiers = new SpellModifiers();
@@ -5,6 +5,7 @@ import electroblob.wizardry.entity.construct.*;
import electroblob.wizardry.entity.living.*;
import electroblob.wizardry.entity.projectile.*;
import electroblob.wizardry.spell.*;
import net.minecraft.entity.EntityLiving;
import net.minecraft.init.MobEffects;
import net.minecraft.item.EnumAction;
import net.minecraft.util.ResourceLocation;
@@ -321,7 +322,7 @@ public final class Spells {
registry.register(new SpellProjectile<>("darkness_orb", EntityDarknessOrb::new).addProperties(Spell.DAMAGE, Spell.EFFECT_DURATION, Spell.EFFECT_STRENGTH).soundValues(0.5f, 0.4f, 0.2f));
registry.register(new ShadowWard());
registry.register(new Decay());
registry.register(new SpellBuff("water_breathing", 0.3f, 0.3f, 1, () -> MobEffects.WATER_BREATHING){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("water_breathing", 0.3f, 0.3f, 1, () -> MobEffects.WATER_BREATHING){ @Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; } }.soundValues(0.7f, 1.2f, 0.4f));
registry.register(new Tornado());
registry.register(new Glide());
registry.register(new SummonSpiritHorse());
@@ -372,7 +373,7 @@ public final class Spells {
registry.register(new Intimidate());
registry.register(new Banish());
registry.register(new SixthSense());
registry.register(new SpellBuff("darkvision", 0, 0.4f, 0.7f, () -> MobEffects.NIGHT_VISION){ @Override public boolean canBeCastByNPCs(){ return false; } }.soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("darkvision", 0, 0.4f, 0.7f, () -> MobEffects.NIGHT_VISION){ @Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; } }.soundValues(0.7f, 1.2f, 0.4f));
registry.register(new Clairvoyance());
registry.register(new PocketWorkbench());
registry.register(new ImbueWeapon());
@@ -258,7 +258,7 @@ public final class WizardrySounds {
event.getRegistry().register(MISC_PAGE_TURN);
event.getRegistry().register(MISC_FREEZE);
for(Spell spell : Spell.getSpells(Spell.allSpells)){
for(Spell spell : Spell.getAllSpells()){
event.getRegistry().registerAll(spell.getSounds());
}
@@ -6,11 +6,13 @@ import electroblob.wizardry.util.NBTExtras;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@@ -32,9 +34,9 @@ public class ArcaneLock extends SpellRay {
@Override public boolean requiresPacket(){ return true; }
@Override public boolean canBeCastByDispensers(){ return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return false; }
@Override public boolean canBeCastByNPCs(){ return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
@@ -136,7 +136,7 @@ public class Blink extends Spell {
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return true;
}
@@ -12,6 +12,7 @@ import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
@@ -21,6 +22,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.pathfinding.Path;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.pathfinding.PathPoint;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentTranslation;
@@ -44,8 +46,8 @@ public class Clairvoyance extends Spell {
WizardData.registerStoredVariables(LOCATION_KEY, DIMENSION_KEY);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastByDispensers() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -9,12 +9,14 @@ import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.*;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
@@ -45,9 +47,9 @@ public class CurseOfSoulbinding extends SpellRay {
WizardData.registerStoredVariables(TARGETS_KEY);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
// You can't damage a dispenser so this would be nonsense!
@Override public boolean canBeCastByDispensers() { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
@@ -21,7 +21,7 @@ public class Decoy extends Spell {
addProperties(DECOY_LIFETIME, MOB_TRICK_CHANCE);
}
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -85,7 +85,7 @@ public class DragonFireball extends Spell {
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return true;
}
@@ -11,6 +11,7 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -29,8 +30,8 @@ public class ForestOfThorns extends Spell {
}
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastByDispensers(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -19,6 +19,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumAction;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundEvent;
@@ -58,12 +59,12 @@ public class Grapple extends Spell {
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return true;
}
@Override
public boolean canBeCastByDispensers(){
public boolean canBeCastBy(TileEntityDispenser dispenser){
return true;
}
@@ -9,12 +9,14 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityTNTPrimed;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumAction;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
@@ -41,8 +43,8 @@ public class GreaterTelekinesis extends SpellRay {
this.soundValues(0.8f, 1, 0.2f);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastByDispensers() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
protected SoundEvent[] createSounds(){
@@ -10,6 +10,7 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.*;
import net.minecraft.entity.passive.*;
@@ -52,7 +53,7 @@ public class Metamorphosis extends SpellRay {
this.soundValues(0.5f, 1f, 0);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
@@ -19,6 +19,7 @@ import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@@ -43,8 +44,8 @@ public class MindControl extends SpellRay {
addProperties(EFFECT_DURATION);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastByDispensers() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
@@ -8,6 +8,7 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.MobEffects;
@@ -28,7 +29,7 @@ public class Poison extends SpellRay {
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return true;
}
@@ -44,6 +44,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.potion.PotionEffect;
import net.minecraft.potion.PotionUtils;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@@ -124,8 +125,8 @@ public class Possession extends SpellRay {
addProperties(EFFECT_DURATION, CRITICAL_HEALTH);
}
@Override public boolean canBeCastByNPCs() { return false; }
@Override public boolean canBeCastByDispensers() { return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
@Override
public boolean requiresPacket(){
@@ -1,6 +1,7 @@
package electroblob.wizardry.spell;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHand;
@@ -17,7 +18,7 @@ public class ReplenishHunger extends SpellBuff {
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
}
@Override public boolean canBeCastByNPCs(){ return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
@Override
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
@@ -8,6 +8,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.EnumAction;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@@ -28,7 +29,7 @@ public class Reversal extends SpellRay {
}
@Override
public boolean canBeCastByDispensers(){
public boolean canBeCastBy(TileEntityDispenser dispenser){
return false;
}
@@ -1,6 +1,7 @@
package electroblob.wizardry.spell;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHand;
@@ -17,7 +18,7 @@ public class Satiety extends SpellBuff {
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
}
@Override public boolean canBeCastByNPCs(){ return false; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
@Override
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
@@ -13,6 +13,7 @@ import net.minecraft.entity.projectile.EntityShulkerBullet;
import net.minecraft.item.EnumAction;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -30,9 +31,9 @@ public class ShulkerBullet extends Spell {
addProperties(RANGE);
}
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers(){ return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -3,7 +3,9 @@ package electroblob.wizardry.spell;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@@ -35,12 +37,12 @@ public class SlowTime extends SpellBuff {
}
@Override
public boolean canBeCastByDispensers(){
public boolean canBeCastBy(TileEntityDispenser dispenser){
return false;
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return false;
}
}
@@ -20,6 +20,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumAction;
import net.minecraft.item.Item;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
@@ -354,7 +355,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
* work if the caster is on full health).
* <p></p>
* This method is intended for use by NPCs (see {@link EntityWizard}) so that they can cast spells. Override it if
* you want a spell to be cast by wizards. Note that you must also override {@link Spell#canBeCastByNPCs()} to
* you want a spell to be cast by wizards. Note that you must also override {@link Spell#canBeCastBy(EntityLiving, boolean)} to
* return true to allow wizards to select the spell. For some spells, this method may well be exactly the same as
* the regular cast method; for others it won't be - for example, projectile-based spells are normally done using
* the player's look vector, but NPCs need to use a target-based method instead.
@@ -390,7 +391,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
* won't work if the caster is on full health).
* <p></p>
* This method is intended for use by dispensers and command blocks so that they can cast spells. Override it if
* you want a spell to be cast by dispensers. Note that you must also override {@link Spell#canBeCastByDispensers()} to
* you want a spell to be cast by dispensers. Note that you must also override {@link Spell#canBeCastBy(TileEntityDispenser)} to
* return true to allow dispensers to select the spell. For some spells, this method may well be exactly the same as
* the regular cast method; for others it won't be - for example, projectile-based spells are normally done using
* the player's look vector, but dispensers need to use a facing-based method instead.
@@ -446,20 +447,46 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
public void finishCasting(World world, @Nullable EntityLivingBase caster, double x, double y, double z,
@Nullable EnumFacing direction, int duration, SpellModifiers modifiers){}
/**
* Whether the given entity can cast this spell. If you have overridden
* {@link Spell#cast(World, EntityLiving, EnumHand, int, EntityLivingBase, SpellModifiers)}, you should override
* this to return true (either always or under certain circumstances).
* @param npc The entity to query.
* @param override True if a player in creative mode is assigning this spell the given entity, false otherwise.
* Usually this means situational conditions should be ignored.
*/
public boolean canBeCastBy(EntityLiving npc, boolean override){
return canBeCastByNPCs();
}
/**
* Whether NPCs such as wizards can cast this spell. If you have overridden
* {@link Spell#cast(World, EntityLiving, EnumHand, int, EntityLivingBase, SpellModifiers)}, you should override
* this to return true.
* @deprecated Use the entity-sensitive version {@link Spell#canBeCastBy(EntityLiving, boolean)}.
*/
@Deprecated
public boolean canBeCastByNPCs(){
return false;
}
/**
* Whether the given dispenser can cast this spell. If you have overridden
* {@link Spell#cast(World, double, double, double, EnumFacing, int, int, SpellModifiers)}, you should override this
* to return true (either always or under certain circumstances).
* @param dispenser The dispenser to query.
*/
public boolean canBeCastBy(TileEntityDispenser dispenser){
return canBeCastByDispensers();
}
/**
* Whether dispensers can cast this spell. If you have overridden
* {@link Spell#cast(World, double, double, double, EnumFacing, int, int, SpellModifiers)}, you should override this
* to return true.
* @deprecated Use the tileentity-sensitive version {@link Spell#canBeCastBy(TileEntityDispenser)}.
*/
@Deprecated
public boolean canBeCastByDispensers(){
return false;
}
@@ -785,7 +812,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
/**
* Returns the total number of registered spells, excluding the 'None' spell. Returns the same number that would be
* returned by {@code Spell.getSpells(Spell.allSpells).size()}, but this method is more efficient.
* returned by {@code Spell.getAllSpells().size()}, but this method is more efficient.
*/
public static int getTotalSpellCount(){
return registry.getValuesCollection().size() - 1;
@@ -833,31 +860,37 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
/**
* Returns a list containing all spells matching the given {@link Predicate}. The returned list is separate from the
* internal spells list; any changes you make to the returned list will have no effect on wizardry since the
* returned list is local to this method. Never includes the {@link None} spell. For convenience, there are some
* predefined predicates in the Spell class (some of these really aren't shortcuts any more):
* <p></p>
* {@link Spell#allSpells} will allow all spells to be returned<br>
* {@link Spell#npcSpells} will only allow enabled spells that can be cast by NPCs (see
* {@link Spell#canBeCastByNPCs()})<br>
* {@link Spell#nonContinuousSpells} will filter out continuous spells but not disabled spells<br>
* {@link TierElementFilter} will only allow enabled spells of the specified tier and element
* returned list is local to this method. Never includes the {@link None} spell.
*
* @param filter A <code>Predicate&ltSpell&gt</code> that the returned spells must satisfy.
*
* @return A <b>local, modifiable</b> list of spells matching the given predicate. <i>Note that this list may be
* empty.</i>
*
* @see TierElementFilter
*/
public static List<Spell> getSpells(Predicate<Spell> filter){
return registry.getValuesCollection().stream().filter(filter.and(s -> s != Spells.none)).collect(Collectors.toList());
}
/** Predicate which allows all spells. */
/** Returns all registered spells, except the {@link None} spell. */
public static List<Spell> getAllSpells(){
return getSpells(s -> true);
}
/** Predicate which allows all spells.
* @deprecated Use {@link Spell#getAllSpells()}. */
@Deprecated
public static Predicate<Spell> allSpells = s -> true;
/** Predicate which allows all non-continuous spells, even those that have been disabled. */
/** Predicate which allows all non-continuous spells, even those that have been disabled.
* @deprecated Nobody ever uses this now we have continuous scrolls, if you really need it just use a lambda. */
@Deprecated
public static Predicate<Spell> nonContinuousSpells = s -> !s.isContinuous;
/** Predicate which allows all enabled spells for which {@link Spell#canBeCastByNPCs()} returns true. */
/** Predicate which allows all enabled spells for which {@link Spell#canBeCastBy(EntityLiving, boolean)} returns true.
* @deprecated in favour of entity-sensitive version, use a lambda expression directly. */
@Deprecated
public static Predicate<Spell> npcSpells = s -> s.isEnabled(SpellProperties.Context.NPCS) && s.canBeCastByNPCs();
/**
@@ -11,6 +11,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.MathHelper;
@@ -29,9 +30,9 @@ import java.util.function.Function;
* <p></p>
* Properties added by this type of spell: {@link Spell#RANGE}
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -62,9 +63,9 @@ public class SpellArrow<T extends EntityMagicArrow> extends Spell {
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
/** Computes the velocity the projectile should be launched at to achieve the required range. */
// Long story short, it doesn't make much sense to me to have the JSON file specify the velocity - even less so if
@@ -11,6 +11,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
@@ -32,9 +33,9 @@ import java.util.stream.Collectors;
* <p></p>
* Properties added by this type of spell: {@link SpellBuff#getDurationKey(Potion)}, {@link SpellBuff#getStrengthKey(Potion)}
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -103,9 +104,9 @@ public class SpellBuff extends Spell {
return this;
}
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -24,9 +24,9 @@ import net.minecraft.world.World;
* <p></p>
* Properties added by this type of spell: {@link SpellConjuration#ITEM_LIFETIME}
* <p></p>
* By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)}
* <p></p>
* By default, this type of spell cannot be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell cannot be cast by dispensers. {@link Spell#canBeCastBy(net.minecraft.tileentity.TileEntityDispenser)}
* <p></p>
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -9,6 +9,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -29,9 +30,9 @@ import java.util.function.Function;
* <p></p>
* Properties added by this type of spell: {@link Spell#DURATION} (if the construct is not permanent)
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -63,9 +64,9 @@ public class SpellConstruct<T extends EntityMagicConstruct> extends Spell {
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
/**
* Sets whether the construct must be spawned on the ground.
@@ -10,6 +10,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -30,9 +31,9 @@ import java.util.function.Function;
* Properties added by this type of spell: {@link Spell#RANGE}, {@link Spell#DURATION} (if the construct is not
* permanent)
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -80,9 +81,9 @@ public class SpellConstructRanged<T extends EntityMagicConstruct> extends SpellC
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -14,6 +14,7 @@ import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttributeInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -32,9 +33,9 @@ import java.util.function.Function;
* <p></p>
* Properties added by this type of spell: {@link SpellMinion#MINION_LIFETIME}
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -80,9 +81,9 @@ public class SpellMinion<T extends EntityLiving & ISummonedCreature> extends Spe
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
@@ -11,6 +11,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.MathHelper;
@@ -29,9 +30,9 @@ import java.util.function.Function;
* <p></p>
* Properties added by this type of spell: {@link Spell#RANGE}
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -62,9 +63,9 @@ public class SpellProjectile<T extends EntityMagicProjectile> extends Spell {
@Override public boolean requiresPacket(){ return false; }
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
/** Computes the velocity the projectile should be launched at to achieve the required range. */
// Long story short, it doesn't make much sense to me to have the JSON file specify the velocity - even less so if
@@ -10,6 +10,7 @@ import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.tileentity.TileEntityDispenser;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
@@ -34,9 +35,9 @@ import javax.annotation.Nullable;
* <p></p>
* Properties added by this type of spell: {@link Spell#RANGE}
* <p></p>
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
* <p></p>
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
* <p></p>
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
*
@@ -151,9 +152,9 @@ public abstract class SpellRay extends Spell {
return this;
}
@Override public boolean canBeCastByNPCs(){ return true; }
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
@Override public boolean canBeCastByDispensers() { return true; }
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
// Finally everything in here is standardised and written in a form that's actually readable - it was long overdue!
@Override
@@ -33,7 +33,7 @@ public class WitherSkull extends Spell {
}
@Override
public boolean canBeCastByNPCs(){
public boolean canBeCastBy(EntityLiving npc, boolean override){
return true;
}
@@ -247,7 +247,7 @@ public final class SpellProperties {
public static void init(){
// Collecting to a set should give us one of each mod ID
Set<String> modIDs = Spell.getSpells(Spell.allSpells).stream().map(s -> s.getRegistryName().getNamespace()).collect(Collectors.toSet());
Set<String> modIDs = Spell.getAllSpells().stream().map(s -> s.getRegistryName().getNamespace()).collect(Collectors.toSet());
boolean flag = loadConfigSpellProperties();