Replace Achievements with Advancements

- Advancements are now in JSON files, converted by the included migration script.
- WizardryAdvancementTrigger is a generic achievement trigger that can be reused throughout the code to trigger custom advancements not covered by the JSON conditions.
- Plus some other small and obvious fixes.
This commit is contained in:
Philipp Rustemeier
2018-03-14 19:12:13 +01:00
parent 62c2a9e9b8
commit 612bbdb64d
48 changed files with 706 additions and 723 deletions
@@ -1,16 +1,5 @@
package electroblob.wizardry;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.enchantment.Imbuement;
import electroblob.wizardry.entity.EntityShield;
@@ -22,6 +11,7 @@ import electroblob.wizardry.packet.PacketPlayerSync;
import electroblob.wizardry.packet.PacketTransportation;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.spell.None;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.MagicDamage;
@@ -59,6 +49,10 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.Map.Entry;
/**
* Capability-based replacement for the old ExtendedPlayer class from 1.7.10. This has been reworked to leave minimum
* external changes (for my own sanity, mainly!). Turns out the only major difference between an internal capability and
@@ -179,13 +173,13 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
if(!spellsDiscovered.add(spell)) return false;
// If the spell had not already been discovered, achievements can be triggered and the method returns true
if(spellsDiscovered.containsAll(Spell.getSpells(Spell::isEnabled))){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.all_spells);
WizardryAdvancementTriggers.all_spells.triggerFor(this.player);
}
for(Element element : Element.values()){
if(element != Element.MAGIC
&& spellsDiscovered.containsAll(Spell.getSpells(new Spell.TierElementFilter(null, element)))){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.element_master);
WizardryAdvancementTriggers.element_master.triggerFor(this.player);
}
}
@@ -1,7 +1,5 @@
package electroblob.wizardry;
import org.apache.logging.log4j.Logger;
import electroblob.wizardry.command.CommandCastSpell;
import electroblob.wizardry.command.CommandDiscoverSpell;
import electroblob.wizardry.command.CommandSetAlly;
@@ -18,7 +16,6 @@ import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.Capability.IStorage;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.Mod.Instance;
@@ -30,6 +27,7 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import org.apache.logging.log4j.Logger;
@Mod(modid = Wizardry.MODID, name = Wizardry.NAME, version = Wizardry.VERSION, guiFactory = "electroblob." + Wizardry.MODID + ".WizardryGuiFactory")
public class Wizardry {
@@ -37,7 +35,7 @@ public class Wizardry {
/** Wizardry's mod ID. */
// This is going to have to change for 1.12 or it'll conflict with the other wizardry mod.
// They were there first, it's only fair... although I wonder if that will have unintended side-effects?
public static final String MODID = "wizardry"; // How about 'ebwizardry', to keep it short?
public static final String MODID = "ebwizardry";
/** Wizardry's mod name, in readable form. */
public static final String NAME = "Electroblob's Wizardry";
/**
@@ -50,7 +48,7 @@ public class Wizardry {
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
* 1.11.x versions, and so on.
*/
public static final String VERSION = "3.1.0";
public static final String VERSION = "4.0.0";
// IDEA: Improve the algorithm that finds a place to summon creatures to take walls into account.
// IDEA: Replace all uses of Math.cos and Math.sin with MathHelper versions
@@ -138,6 +136,8 @@ public class Wizardry {
// The check for the generateLoot setting is now done within this method.
WizardryRegistry.registerLoot();
WizardryRegistry.registerAdvancementTriggers();
// Moved to preInit, because apparently it has to be here now.
proxy.registerRenderers();
// It seems this also has to be here
@@ -158,7 +158,9 @@ public class Wizardry {
NetworkRegistry.INSTANCE.registerGuiHandler(this, new WizardryGuiHandler());
WizardryPacketHandler.initPackets();
// NOTE: Will need to be moved to init for 1.12, as will anything that needs to be after the registry events.
// Recipes
WizardryRegistry.registerRecipes();
WizardryTabs.sort();
proxy.initGuiBits();
@@ -11,20 +11,11 @@ import electroblob.wizardry.event.DiscoverSpellEvent;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.item.ItemWizardArmour;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryEnchantments;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.registry.*;
import electroblob.wizardry.spell.FreezingWeapon;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.IElementalDamage;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.*;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
@@ -57,7 +48,6 @@ import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
@@ -354,7 +344,7 @@ public final class WizardryEventHandler {
}
if(event.getEntityLiving() == player && event.getSource() instanceof IElementalDamage){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.self_destruct);
WizardryAdvancementTriggers.self_destruct.triggerFor(player);
}
}
}
@@ -384,13 +374,6 @@ public final class WizardryEventHandler {
}
}
@SubscribeEvent
public static void onItemPickupEvent(EntityItemPickupEvent event){
if(event.getItem().getItem().getItem() == WizardryItems.magic_crystal){
AdvancementHelper.grantAdvancement(event.getEntityPlayer(), EnumAdvancement.crystal);
}
}
// Private helper methods
// ================================================================================================================
@@ -1,10 +1,7 @@
package electroblob.wizardry.entity.construct;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
@@ -24,6 +21,8 @@ import net.minecraft.util.DamageSource;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.List;
public class EntityTornado extends EntityMagicConstruct {
private double velX, velZ;
@@ -104,7 +103,7 @@ public class EntityTornado extends EntityMagicConstruct {
// The 'Not Again...' achievement
if(target instanceof EntityPig && WizardryUtilities.getRider(target) instanceof EntityPlayer){
AdvancementHelper.grantAdvancement((EntityPlayer)WizardryUtilities.getRider(target), EnumAdvancement.pig_tornado);
WizardryAdvancementTriggers.pig_tornado.triggerFor((EntityPlayer)WizardryUtilities.getRider(target));
}
}
}
@@ -1,15 +1,7 @@
package electroblob.wizardry.entity.living;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import com.google.common.base.Predicate;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.item.ItemSpellBook;
@@ -22,19 +14,8 @@ import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIOpenDoor;
import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest2;
import net.minecraft.entity.*;
import net.minecraft.entity.ai.*;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
@@ -55,6 +36,11 @@ import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntityAdditionalSpawnData {
private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell(this, 0.5D, 14.0F, 30, 50);
@@ -319,15 +305,6 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
return LOOT_TABLE;
}
@Override
public void onDeath(DamageSource source){
super.onDeath(source);
if(source.getTrueSource() instanceof EntityPlayer){
AdvancementHelper.grantAdvancement((EntityPlayer)source.getTrueSource(), EnumAdvancement.defeat_evil_wizard);
}
}
@Override
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData data){
@@ -1,49 +1,21 @@
package electroblob.wizardry.entity.living;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import com.google.common.base.Predicate;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.item.ItemSpellBook;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.registry.*;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIOpenDoor;
import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITradePlayer;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityAIWatchClosest2;
import net.minecraft.entity.*;
import net.minecraft.entity.ai.*;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityVillager;
@@ -81,6 +53,8 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
import java.util.*;
@Mod.EventBusSubscriber
public class EntityWizard extends EntityVillager implements ISpellCaster, IEntityAdditionalSpawnData {
@@ -401,11 +375,11 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
// Achievements
if(this.getCustomer() != null){
AdvancementHelper.grantAdvancement(getCustomer(), EnumAdvancement.wizard_trade);
WizardryAdvancementTriggers.wizard_trade.triggerFor(this.getCustomer());
if(merchantrecipe.getItemToSell().getItem() instanceof ItemSpellBook
&& Spell.get(merchantrecipe.getItemToSell().getItemDamage()).tier == Tier.MASTER){
AdvancementHelper.grantAdvancement(getCustomer(), EnumAdvancement.buy_master_spell);
WizardryAdvancementTriggers.buy_master_spell.triggerFor(this.getCustomer());
}
}
@@ -776,7 +750,7 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
public boolean attackEntityFrom(DamageSource source, float damage){
if(source.getTrueSource() instanceof EntityPlayer){
AdvancementHelper.grantAdvancement((EntityPlayer)source.getTrueSource(), EnumAdvancement.anger_wizard);
WizardryAdvancementTriggers.anger_wizard.triggerFor((EntityPlayer)source.getTrueSource());
}
return super.attackEntityFrom(source, damage);
@@ -795,9 +769,7 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
/**
* Tests whether the block at the given coordinates is part of this wizard's tower.
*
* @param x
* @param y
* @param z
* @param pos
* @return
*/
public boolean isBlockPartOfTower(BlockPos pos){
@@ -818,7 +790,7 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
for(EntityWizard wizard : wizards){
if(wizard.isBlockPartOfTower(event.getPos())){
wizard.setRevengeTarget(event.getPlayer());
AdvancementHelper.grantAdvancement(event.getPlayer(), EnumAdvancement.anger_wizard);
WizardryAdvancementTriggers.anger_wizard.triggerFor(event.getPlayer());
}
}
}
@@ -1,11 +1,10 @@
package electroblob.wizardry.item;
import java.util.List;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.event.DiscoverSpellEvent;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryTabs;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.WizardryUtilities;
@@ -24,6 +23,9 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.List;
public class ItemIdentificationScroll extends Item {
public ItemIdentificationScroll(){
@@ -65,7 +67,7 @@ public class ItemIdentificationScroll extends Item {
// Identification scrolls give the chat readout in creative mode, otherwise it looks like
// nothing happens!
properties.discoverSpell(spell);
AdvancementHelper.grantAdvancement(player, EnumAdvancement.identify_spell);
WizardryAdvancementTriggers.identify_spell.triggerFor(player);
player.playSound(SoundEvents.ENTITY_PLAYER_LEVELUP, 1.25f, 1);
if(!player.capabilities.isCreativeMode) stack.shrink(1);
if(!world.isRemote) player.sendMessage(new TextComponentTranslation("spell.discover",
@@ -83,5 +85,5 @@ public class ItemIdentificationScroll extends Item {
return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
}
}
@@ -25,6 +25,8 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.Nullable;
public class ItemSpellBook extends Item {
public ItemSpellBook(){
@@ -1,7 +1,5 @@
package electroblob.wizardry.item;
import java.util.List;
import electroblob.wizardry.SpellGlyphData;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.Wizardry;
@@ -15,6 +13,7 @@ import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.event.SpellCastEvent.Source;
import electroblob.wizardry.packet.PacketCastSpell;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardryTabs;
@@ -46,6 +45,9 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.List;
/**
* This class is (literally) where the magic happens! All wand types are single instances of this class. There's a lot
* of quite hard-to-read code in here, but unfortunately there's not much I can do about that. For this reason, I have
@@ -97,11 +99,6 @@ public class ItemWand extends Item {
* WandHelper.getUpgradeLevel(itemstack, WizardryItems.storage_upgrade)) + 0.5f);
}
@Override
public void onCreated(ItemStack stack, World par2World, EntityPlayer player){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.arcane_initiate);
}
@Override
public void onUpdate(ItemStack itemstack, World world, Entity entity, int slot, boolean isHeld){
@@ -118,10 +115,8 @@ public class ItemWand extends Item {
if(entity instanceof EntityPlayer && this.element != null && this.element != Element.MAGIC){
// As it stands, this will trigger every tick. Not ideal, but I can't find a way to detect if a player
// has a certain achievement.
// EDIT: There is a way to check, using StatFileWriter#hasAchievementUnlocked, but this ends up calling the
// same
// thing as addStat anyway, meaning there's no point and it's probably not much of a problem anyway.
AdvancementHelper.grantAdvancement((EntityPlayer)entity, EnumAdvancement.elemental);
// TODO: check if this is somehow triggerable via JSON conditions.
WizardryAdvancementTriggers.element_master.triggerFor((EntityPlayer)entity);
}
}
@@ -1,17 +1,16 @@
package electroblob.wizardry.item;
import java.util.List;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.constants.Element;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.resources.I18n;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryTabs;
import electroblob.wizardry.spell.Petrify;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -30,6 +29,9 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.List;
@Mod.EventBusSubscriber
public class ItemWizardArmour extends ItemArmor implements ISpecialArmor {
@@ -233,7 +235,7 @@ public class ItemWizardArmour extends ItemArmor implements ISpecialArmor {
}
}
// If it gets this far, then all slots must be wizard armour, so trigger the achievement.
AdvancementHelper.grantAdvancement(player, EnumAdvancement.armour_set);
WizardryAdvancementTriggers.armour_set.triggerFor(player);
}
}
@@ -0,0 +1,33 @@
package electroblob.wizardry.registry;
import electroblob.wizardry.util.CustomAdvancementTrigger;
/**
* This class stores a collection of custom advancement triggers, for advancements that cannot be triggered
* from plain vanilla JSON definitions. It replaces the old WizardryAchievements class.
*
* @author 12foo
* @since Wizardry 3.1.0
*/
public final class WizardryAdvancementTriggers {
public static final CustomAdvancementTrigger armour_set = new CustomAdvancementTrigger("trigger_armour_set");
public static final CustomAdvancementTrigger jam_wizard = new CustomAdvancementTrigger("trigger_jam_wizard");
public static final CustomAdvancementTrigger self_destruct = new CustomAdvancementTrigger("trigger_self_destruct");
public static final CustomAdvancementTrigger all_spells = new CustomAdvancementTrigger("trigger_all_spells");
public static final CustomAdvancementTrigger element_master = new CustomAdvancementTrigger("trigger_element_master");
public static final CustomAdvancementTrigger identify_spell = new CustomAdvancementTrigger("trigger_identify_spell");
public static final CustomAdvancementTrigger elemental = new CustomAdvancementTrigger("trigger_elemental");
public static final CustomAdvancementTrigger legendary = new CustomAdvancementTrigger("trigger_legendary");
public static final CustomAdvancementTrigger max_out_wand = new CustomAdvancementTrigger("trigger_max_out_wand");
public static final CustomAdvancementTrigger special_upgrade = new CustomAdvancementTrigger("trigger_special_upgrade");
public static final CustomAdvancementTrigger pig_tornado = new CustomAdvancementTrigger("trigger_pig_tornado");
public static final CustomAdvancementTrigger master = new CustomAdvancementTrigger("trigger_master");
public static final CustomAdvancementTrigger apprentice = new CustomAdvancementTrigger("trigger_apprentice");
public static final CustomAdvancementTrigger anger_wizard = new CustomAdvancementTrigger("trigger_anger_wizard");
public static final CustomAdvancementTrigger buy_master_spell = new CustomAdvancementTrigger("trigger_buy_master_spell");
public static final CustomAdvancementTrigger wizard_trade = new CustomAdvancementTrigger("trigger_wizard_trade");
public static final CustomAdvancementTrigger slime_skeleton = new CustomAdvancementTrigger("trigger_slime_skeleton");
public static final CustomAdvancementTrigger freeze_blaze = new CustomAdvancementTrigger("trigger_freeze_blaze");
public static final CustomAdvancementTrigger frankenstein = new CustomAdvancementTrigger("trigger_frankenstein");
public static final CustomAdvancementTrigger charge_creeper = new CustomAdvancementTrigger("trigger_charge_creeper");
}
@@ -103,12 +103,7 @@ public final class WizardryItems {
public static final Item spectral_pickaxe = new ItemSpectralPickaxe(ToolMaterial.IRON);
public static final Item spectral_bow = new ItemSpectralBow();
public static final Item mana_flask = new Item(){
@Override
public void onCreated(ItemStack par1ItemStack, World par2World, EntityPlayer player){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.craft_flask);
}
}.setCreativeTab(WizardryTabs.WIZARDRY);
public static final Item mana_flask = new Item().setCreativeTab(WizardryTabs.WIZARDRY);
public static final Item storage_upgrade = new Item().setCreativeTab(WizardryTabs.WIZARDRY);
public static final Item siphon_upgrade = new Item().setCreativeTab(WizardryTabs.WIZARDRY);
@@ -82,7 +82,7 @@ public final class WizardryPotions {
/**
* Sets both the registry and unlocalised names of the given potion, then registers it with the given registry. Use
* this instead of {@link potion#setRegistryName(String)} and {@link potion#setUnlocalizedName(String)} during
* this instead of {@link Potion#setRegistryName(String)} and {@link Potion#setUnlocalizedName(String)} during
* construction, for convenience and consistency.
*
* @param registry The registry to register the given potion to.
@@ -13,6 +13,7 @@ import electroblob.wizardry.loot.RandomSpell;
import electroblob.wizardry.loot.WizardSpell;
import electroblob.wizardry.tileentity.*;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Biomes;
@@ -50,6 +51,29 @@ public final class WizardryRegistry {
// NOTE: In 1.12, recipes have a registry (they can still stay here though since we don't keep references to them)
public static void registerAdvancementTriggers(){
CriteriaTriggers.register(WizardryAdvancementTriggers.armour_set);
CriteriaTriggers.register(WizardryAdvancementTriggers.jam_wizard);
CriteriaTriggers.register(WizardryAdvancementTriggers.self_destruct);
CriteriaTriggers.register(WizardryAdvancementTriggers.all_spells);
CriteriaTriggers.register(WizardryAdvancementTriggers.element_master);
CriteriaTriggers.register(WizardryAdvancementTriggers.identify_spell);
CriteriaTriggers.register(WizardryAdvancementTriggers.elemental);
CriteriaTriggers.register(WizardryAdvancementTriggers.legendary);
CriteriaTriggers.register(WizardryAdvancementTriggers.max_out_wand);
CriteriaTriggers.register(WizardryAdvancementTriggers.special_upgrade);
CriteriaTriggers.register(WizardryAdvancementTriggers.pig_tornado);
CriteriaTriggers.register(WizardryAdvancementTriggers.master);
CriteriaTriggers.register(WizardryAdvancementTriggers.apprentice);
CriteriaTriggers.register(WizardryAdvancementTriggers.anger_wizard);
CriteriaTriggers.register(WizardryAdvancementTriggers.buy_master_spell);
CriteriaTriggers.register(WizardryAdvancementTriggers.wizard_trade);
CriteriaTriggers.register(WizardryAdvancementTriggers.slime_skeleton);
CriteriaTriggers.register(WizardryAdvancementTriggers.freeze_blaze);
CriteriaTriggers.register(WizardryAdvancementTriggers.frankenstein);
CriteriaTriggers.register(WizardryAdvancementTriggers.charge_creeper);
}
/** Called from the preInit method in the main mod class to register the custom dungeon loot. */
public static void registerLoot(){
@@ -8,6 +8,7 @@ import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.entity.living.EntityWizard;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
@@ -44,7 +45,7 @@ public class ArcaneJammer extends Spell {
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.ENTITY && WizardryUtilities.isLiving(rayTrace.entityHit)){
EntityLivingBase entity = (EntityLivingBase)rayTrace.entityHit;
if(entity instanceof EntityWizard) { AdvancementHelper.grantAdvancement(caster, EnumAdvancement.jam_wizard); }
if(entity instanceof EntityWizard) WizardryAdvancementTriggers.jam_wizard.triggerFor(caster);
if(!world.isRemote){
entity.addPotionEffect(new PotionEffect(WizardryPotions.arcane_jammer,
@@ -1,12 +1,9 @@
package electroblob.wizardry.spell;
import java.util.List;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
@@ -24,6 +21,8 @@ import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.List;
public class IceAge extends Spell {
private static final int baseDuration = 1200;
@@ -59,7 +58,7 @@ public class IceAge extends Spell {
target.extinguish();
}
if(target instanceof EntityBlaze) { AdvancementHelper.grantAdvancement(caster, EnumAdvancement.freeze_blaze); }
if(target instanceof EntityBlaze) WizardryAdvancementTriggers.freeze_blaze.triggerFor(caster);
if(target instanceof EntityLiving){
@@ -6,6 +6,7 @@ import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
@@ -53,7 +54,7 @@ public class IceStatue extends Spell {
// Stops the entity looking red while frozen and the resulting z-fighting
target.hurtTime = 0;
if(target instanceof EntityBlaze) { AdvancementHelper.grantAdvancement(caster, EnumAdvancement.freeze_blaze); }
if(target instanceof EntityBlaze) WizardryAdvancementTriggers.freeze_blaze.triggerFor(caster);
// Short mobs such as spiders and pigs
if((target.height < 1.2 || target.isChild()) && WizardryUtilities.canBlockBeReplaced(world, pos)){
@@ -5,6 +5,7 @@ import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.EntityLiving;
@@ -110,11 +111,11 @@ public class LightningBolt extends Spell {
event.getLightning().getEntityData().getUniqueId("summoningPlayer"));
if(event.getEntity() instanceof EntityCreeper){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.charge_creeper);
WizardryAdvancementTriggers.charge_creeper.triggerFor(player);
}
if(event.getEntity() instanceof EntityPig){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.frankenstein);
WizardryAdvancementTriggers.frankenstein.triggerFor(player);
}
}
@@ -7,6 +7,7 @@ import electroblob.wizardry.constants.Element;
import electroblob.wizardry.constants.SpellType;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.entity.living.EntityMagicSlime;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.SpellModifiers;
@@ -49,7 +50,7 @@ public class Slime extends Spell {
this.getNameForTranslationFormatted()));
}else if(!(target instanceof EntityMagicSlime)){
if(target instanceof EntitySkeleton) { AdvancementHelper.grantAdvancement(caster, EnumAdvancement.slime_skeleton); }
if(target instanceof EntitySkeleton) WizardryAdvancementTriggers.slime_skeleton.triggerFor(caster);
if(!world.isRemote){
EntityMagicSlime slime = new EntityMagicSlime(world, caster, target,
@@ -1,8 +1,5 @@
package electroblob.wizardry.tileentity;
import java.util.HashSet;
import java.util.Set;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.advancement.AdvancementHelper;
@@ -10,12 +7,9 @@ import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.event.SpellBindEvent;
import electroblob.wizardry.item.ItemArcaneTome;
import electroblob.wizardry.item.ItemArmourUpgrade;
import electroblob.wizardry.item.ItemSpellBook;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.item.ItemWizardArmour;
import electroblob.wizardry.item.*;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.WandHelper;
@@ -30,6 +24,9 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
import java.util.HashSet;
import java.util.Set;
public class ContainerArcaneWorkbench extends Container {
/** The arcane workbench tile entity associated with this container. */
@@ -298,7 +295,7 @@ public class ContainerArcaneWorkbench extends Container {
newWand.setItemDamage(newWand.getMaxDamage() - (wand.getMaxDamage() - wand.getItemDamage()));
this.putStackInSlot(WAND_SLOT, newWand);
this.putStackInSlot(UPGRADE_SLOT, ItemStack.EMPTY);
AdvancementHelper.grantAdvancement(player, EnumAdvancement.apprentice);
WizardryAdvancementTriggers.apprentice.triggerFor(player);
}
break;
@@ -321,7 +318,7 @@ public class ContainerArcaneWorkbench extends Container {
newWand.setItemDamage(newWand.getMaxDamage() - (wand.getMaxDamage() - wand.getItemDamage()));
this.putStackInSlot(WAND_SLOT, newWand);
this.putStackInSlot(UPGRADE_SLOT, ItemStack.EMPTY);
AdvancementHelper.grantAdvancement(player, EnumAdvancement.master);
WizardryAdvancementTriggers.master.triggerFor(player);
}
break;
@@ -375,10 +372,10 @@ public class ContainerArcaneWorkbench extends Container {
}
this.getSlot(UPGRADE_SLOT).decrStackSize(1);
AdvancementHelper.grantAdvancement(player, EnumAdvancement.special_upgrade);
WizardryAdvancementTriggers.special_upgrade.triggerFor(player);
if(WandHelper.getTotalUpgrades(wand) == Tier.MASTER.upgradeLimit){
AdvancementHelper.grantAdvancement(player, EnumAdvancement.max_out_wand);
WizardryAdvancementTriggers.max_out_wand.triggerFor(player);
}
}
}
@@ -429,7 +426,7 @@ public class ContainerArcaneWorkbench extends Container {
if(!wand.getTagCompound().hasKey("legendary")){
wand.getTagCompound().setBoolean("legendary", true);
this.putStackInSlot(UPGRADE_SLOT, ItemStack.EMPTY);
AdvancementHelper.grantAdvancement(player, EnumAdvancement.legendary);
WizardryAdvancementTriggers.legendary.triggerFor(player);
}
}
// Charges armour by appropriate amount
@@ -0,0 +1,80 @@
package electroblob.wizardry.util;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import electroblob.wizardry.Wizardry;
import net.minecraft.advancements.ICriterionTrigger;
import net.minecraft.advancements.PlayerAdvancements;
import net.minecraft.advancements.critereon.AbstractCriterionInstance;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ResourceLocation;
/**
* This class implements a generic custom advancement trigger that can be fired from any point in
* the code. This replaces the achievement system in instances where the JSON advancement descriptions
* cannot properly capture the advancement-worthy events. Where possible, advancement conditions
* should be triggered by JSON descriptions and vanilla advancement triggers.
*
* @author 12foo
* @since 3.1.0
*/
public class CustomAdvancementTrigger implements ICriterionTrigger<CustomAdvancementTrigger.Instance> {
private final ResourceLocation id;
private final SetMultimap<PlayerAdvancements, Listener> listeners = HashMultimap.create();
/**
* This is a dummy criterion instance that does nothing on its own (but it is bound to this
* trigger, and via listeners to the player). We later fire this manually when we want the
* advancement to happen.
*/
public static class Instance extends AbstractCriterionInstance {
public Instance(ResourceLocation triggerId) {
super(triggerId);
}
}
public CustomAdvancementTrigger(String name) {
super();
id = new ResourceLocation(Wizardry.MODID, name);
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public void addListener(PlayerAdvancements playerAdvancementsIn, Listener<Instance> listener) {
listeners.put(playerAdvancementsIn, listener);
}
@Override
public void removeListener(PlayerAdvancements playerAdvancementsIn, Listener<Instance> listener) {
listeners.remove(playerAdvancementsIn, listener);
}
@Override
public void removeAllListeners(PlayerAdvancements playerAdvancementsIn) {
listeners.removeAll(playerAdvancementsIn);
}
@Override
public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) {
// Every time a trigger with this name is deserialized from the JSON, we just return a new
// dummy criterion instance.
return new CustomAdvancementTrigger.Instance(id);
}
public void triggerFor(EntityPlayer player) {
// Fire our dummy criterion manually on all advancements of the player, thereby granting
// the ones that match it.
if (player instanceof EntityPlayerMP) {
final PlayerAdvancements advances = ((EntityPlayerMP) player).getAdvancements();
listeners.get(advances).forEach((listener) -> listener.grantCriterion(advances));
}
}
}
@@ -1,7 +1,6 @@
package electroblob.wizardry.util;
import electroblob.wizardry.advancement.AdvancementHelper;
import electroblob.wizardry.advancement.AdvancementHelper.EnumAdvancement;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.util.MagicDamage.DamageType;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.player.EntityPlayer;
@@ -46,7 +45,7 @@ public interface IElementalDamage {
WizardryUtilities.chargeCreeper((EntityCreeper)event.getEntityLiving());
// Gives the player that caused the shock damage the 'It's Gonna Blow' achievement
if(event.getSource().getTrueSource() instanceof EntityPlayer){
AdvancementHelper.grantAdvancement((EntityPlayer)event.getSource().getTrueSource(), EnumAdvancement.charge_creeper);
WizardryAdvancementTriggers.charge_creeper.triggerFor((EntityPlayer)event.getSource().getTrueSource());
}
}
}