From 35851d3f23e4034530328175043b75df6486fe8c Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 22 Jan 2019 18:39:30 +0200 Subject: [PATCH] Implement sugar, implement spell affinities, fix some issues with the ice gem --- .../com/minelittlepony/unicopia/UItems.java | 4 +- .../com/minelittlepony/unicopia/Unicopia.java | 13 +-- .../unicopia/entity/EntitySpell.java | 14 +++ .../ICapabilitiesProxyContainer.java | 2 +- .../inventory/InventoryOfHolding.java | 2 +- .../unicopia/item/ICastable.java | 13 +++ .../unicopia/item/IMagicalItem.java | 12 +++ .../unicopia/item/ItemCereal.java | 21 +++- .../unicopia/item/ItemCurse.java | 6 ++ .../unicopia/item/ItemOfHolding.java | 10 +- .../unicopia/item/ItemSpell.java | 98 +++++++++++++------ .../unicopia/model/ModelGem.java | 4 +- .../unicopia/player/IPlayer.java | 8 ++ .../unicopia/player/IRaceContainer.java | 2 +- .../minelittlepony/unicopia/player/IView.java | 10 +- .../player/PlayerAbilityDelegate.java | 2 +- .../unicopia/player/PlayerCapabilities.java | 26 ++++- .../player/PlayerGravityDelegate.java | 2 +- .../unicopia/player/PlayerView.java | 42 +++++++- .../unicopia/spell/AbstractSpell.java | 10 ++ .../unicopia/spell/ICaster.java | 3 + .../unicopia/spell/IDispenceable.java | 3 +- .../unicopia/spell/IMagicEffect.java | 13 ++- .../unicopia/spell/IUseAction.java | 6 +- .../unicopia/spell/SpellAffinity.java | 34 +++++++ .../unicopia/spell/SpellCharge.java | 5 + .../unicopia/spell/SpellFire.java | 22 ++--- .../unicopia/spell/SpellIce.java | 75 +++++++------- .../unicopia/spell/SpellRegistry.java | 40 ++++++-- .../unicopia/spell/SpellShield.java | 5 + .../serialisation}/InbtSerialisable.java | 2 +- .../com/minelittlepony/util/Iterators.java | 65 ++++++++++++ .../com/minelittlepony/util/PosHelper.java | 40 +++++--- .../resources/assets/unicopia/lang/en_US.lang | 36 ++++--- 34 files changed, 486 insertions(+), 164 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java rename src/main/java/com/minelittlepony/unicopia/{ => util/serialisation}/InbtSerialisable.java (91%) create mode 100644 src/main/java/com/minelittlepony/util/Iterators.java diff --git a/src/main/java/com/minelittlepony/unicopia/UItems.java b/src/main/java/com/minelittlepony/unicopia/UItems.java index ccff1352..574d432d 100644 --- a/src/main/java/com/minelittlepony/unicopia/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/UItems.java @@ -115,8 +115,8 @@ public class UItems { .setTranslationKey("alfalfa_leaves") .setRegistryName(Unicopia.MODID, "alfalfa_leaves"); - public static final Item cereal = new ItemCereal(Unicopia.MODID, "cereal", 9, 0.8F); - public static final Item sugar_cereal = new ItemCereal(Unicopia.MODID, "sugar_cereal", 20, -2).setAlwaysEdible(); + public static final Item cereal = new ItemCereal(Unicopia.MODID, "cereal", 9, 0.8F).setSugarAmount(1); + public static final Item sugar_cereal = new ItemCereal(Unicopia.MODID, "sugar_cereal", 20, -2).setSugarAmount(110).setAlwaysEdible(); public static final ItemTomato tomato = new ItemTomato(Unicopia.MODID, "tomato", 4, 34); public static final ItemTomato cloudsdale_tomato = new ItemTomato(Unicopia.MODID, "cloudsdale_tomato", 16, 4); diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index d7fe0298..515ef080 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -65,6 +65,7 @@ import com.minelittlepony.unicopia.network.MsgPlayerAbility; import com.minelittlepony.unicopia.network.MsgPlayerCapabilities; import com.minelittlepony.unicopia.network.MsgRequestCapabilities; import com.minelittlepony.unicopia.player.IPlayer; +import com.minelittlepony.unicopia.player.IView; import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.unicopia.power.PowersRegistry; import com.minelittlepony.unicopia.util.crafting.CraftingManager; @@ -205,7 +206,11 @@ public class Unicopia implements IGuiHandler { EntityPlayer player = Minecraft.getMinecraft().player; if (player != null) { - event.setRoll((float)PlayerSpeciesList.instance().getPlayer(player).getCamera().calculateRoll(player)); + IView view = PlayerSpeciesList.instance().getPlayer(player).getCamera(); + + event.setRoll(view.calculateRoll()); + event.setPitch(view.calculatePitch(event.getPitch())); + event.setYaw(view.calculateYaw(event.getYaw())); } } @@ -322,11 +327,7 @@ public class Unicopia implements IGuiHandler { @SubscribeEvent public static void modifyFOV(FOVUpdateEvent event) { - float fov = event.getFov(); - - fov += PlayerSpeciesList.instance().getPlayer(event.getEntity()).getExertion() / 5; - - event.setNewfov(fov); + event.setNewfov(PlayerSpeciesList.instance().getPlayer(event.getEntity()).getCamera().calculateFieldOfView(event.getFov())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java index 714a23a8..d3ef2b16 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntitySpell.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.item.ICastable; import com.minelittlepony.unicopia.network.EffectSync; import com.minelittlepony.unicopia.spell.ICaster; import com.minelittlepony.unicopia.spell.IMagicEffect; +import com.minelittlepony.unicopia.spell.SpellAffinity; import com.minelittlepony.unicopia.spell.SpellRegistry; import net.minecraft.block.SoundType; @@ -45,6 +46,9 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster EFFECT = EntityDataManager .createKey(EntitySpell.class, DataSerializers.COMPOUND_TAG); + private static final DataParameter AFFINITY = EntityDataManager + .createKey(EntitySpell.class, DataSerializers.VARINT); + private final EffectSync effectDelegate = new EffectSync<>(this, EFFECT); public EntitySpell(World w) { @@ -64,6 +68,15 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster(EnumActionResult.SUCCESS, stack); } + @Override + public boolean hasInnerSpace() { + return true; + } + public class Inventory implements IInteractionObject { private String customname = null; @@ -163,9 +168,4 @@ public class ItemOfHolding extends Item implements IMagicalItem { return "unicopia:itemofholding"; } } - - @Override - public boolean hasInnerSpace() { - return true; - } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java b/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java index 3b20a4b8..b195fba3 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/item/ItemSpell.java @@ -1,21 +1,29 @@ package com.minelittlepony.unicopia.item; +import java.util.List; + +import javax.annotation.Nullable; + import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.IUseAction; +import com.minelittlepony.unicopia.spell.SpellAffinity; import com.minelittlepony.unicopia.spell.SpellCastResult; import com.minelittlepony.unicopia.spell.IDispenceable; import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.util.vector.VecHelper; import net.minecraft.block.BlockDispenser; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.dispenser.BehaviorDefaultDispenseItem; import net.minecraft.dispenser.IBehaviorDispenseItem; import net.minecraft.dispenser.IBlockSource; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; @@ -37,24 +45,28 @@ public class ItemSpell extends Item implements ICastable { return super.dispenseStack(source, stack); } - SpellCastResult dispenceResult = ((ICastable)stack.getItem()).onDispenseSpell(source, stack, effect); + if (stack.getItem() instanceof ICastable) { + ICastable castable = (ICastable)stack.getItem(); - if (dispenceResult == SpellCastResult.DEFAULT) { - return super.dispenseStack(source, stack); - } + SpellCastResult dispenceResult = castable.onDispenseSpell(source, stack, effect); - if (dispenceResult == SpellCastResult.PLACE) { - BlockPos pos = source.getBlockPos(); + if (dispenceResult == SpellCastResult.DEFAULT) { + return super.dispenseStack(source, stack); + } - castContainedSpell(source.getWorld(), pos, stack, effect); + if (dispenceResult == SpellCastResult.PLACE) { + castable.castContainedSpell(source.getWorld(), source.getBlockPos(), stack, effect); - stack.shrink(1); + stack.shrink(1); + } } return stack; } }; + protected String translationKey; + public ItemSpell(String domain, String name) { super(); @@ -69,6 +81,11 @@ public class ItemSpell extends Item implements ICastable { BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, dispenserBehavior); } + public Item setTranslationKey(String key) { + translationKey = key; + return super.setTranslationKey(key); + } + @Override public boolean hasEffect(ItemStack stack) { return SpellRegistry.stackHasEnchantment(stack); @@ -79,13 +96,13 @@ public class ItemSpell extends Item implements ICastable { EnumFacing facing = source.getBlockState().getValue(BlockDispenser.FACING); BlockPos pos = source.getBlockPos().offset(facing); - return effect.onDispenced(pos, facing, source); + return effect.onDispenced(pos, facing, source, getAffinity(stack)); } @Override public SpellCastResult onCastSpell(EntityPlayer player, World world, BlockPos pos, ItemStack stack, IMagicEffect effect, EnumFacing side, float hitX, float hitY, float hitZ) { if (effect instanceof IUseAction) { - return ((IUseAction)effect).onUse(stack, player, world, pos, side, hitX, hitY, hitZ); + return ((IUseAction)effect).onUse(stack, getAffinity(stack), player, world, pos, side, hitX, hitY, hitZ); } return SpellCastResult.PLACE; @@ -110,7 +127,7 @@ public class ItemSpell extends Item implements ICastable { return EnumActionResult.FAIL; } - SpellCastResult result = ((ICastable)stack.getItem()).onCastSpell(player, world, pos, stack, effect, side, hitX, hitY, hitZ); + SpellCastResult result = onCastSpell(player, world, pos, stack, effect, side, hitX, hitY, hitZ); if (!world.isRemote) { pos = pos.offset(side); @@ -146,10 +163,10 @@ public class ItemSpell extends Item implements ICastable { return new ActionResult(EnumActionResult.FAIL, stack); } - IMagicEffect effect = SpellRegistry.instance().getSpellFromItemStack(stack); + IUseAction effect = SpellRegistry.instance().getUseActionFrom(stack); - if (effect instanceof IUseAction) { - SpellCastResult result = ((IUseAction)effect).onUse(stack, player, world, target); + if (effect != null) { + SpellCastResult result = effect.onUse(stack, getAffinity(stack), player, world, target); if (result != SpellCastResult.NONE) { if (result == SpellCastResult.PLACE && !player.capabilities.isCreativeMode) { @@ -163,6 +180,35 @@ public class ItemSpell extends Item implements ICastable { return new ActionResult(EnumActionResult.PASS, stack); } + @Override + public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { + if (SpellRegistry.stackHasEnchantment(stack)) { + SpellAffinity affinity = getAffinity(stack); + + tooltip.add(affinity.getColourCode() + I18n.format(String.format("%s.%s.name", + affinity.getTranslationKey(), + SpellRegistry.getKeyFromStack(stack) + ))); + } + } + + @Override + public String getTranslationKey(ItemStack stack) { + return super.getTranslationKey(); + } + + @Override + public String getItemStackDisplayName(ItemStack stack) { + if (SpellRegistry.stackHasEnchantment(stack)) { + return I18n.format(getTranslationKey(stack) + ".enchanted.name", I18n.format(String.format("%s.%s.name", + getAffinity(stack).getTranslationKey(), + SpellRegistry.getKeyFromStack(stack) + ))); + } + + return super.getItemStackDisplayName(stack); + } + @Override public void getSubItems(CreativeTabs tab, NonNullList subItems) { super.getSubItems(tab, subItems); @@ -175,31 +221,23 @@ public class ItemSpell extends Item implements ICastable { } @Override - public String getTranslationKey(ItemStack stack) { - String result = super.getTranslationKey(stack); - + public EnumRarity getRarity(ItemStack stack) { if (SpellRegistry.stackHasEnchantment(stack)) { - result += "." + stack.getTagCompound().getString("spell"); + return EnumRarity.UNCOMMON; } - return result; - } - - protected static EntitySpell castContainedSpell(World world, BlockPos pos, ItemStack stack, IMagicEffect effect) { - EntitySpell spell = new EntitySpell(world); - - spell.setEffect(effect); - spell.setLocationAndAngles(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0, 0); - world.spawnEntity(spell); - - return spell; + return super.getRarity(stack); } @Override public boolean canFeed(EntitySpell entity, ItemStack stack) { - IMagicEffect effect = entity.getEffect(); return effect != null && effect.getName().equals(SpellRegistry.getKeyFromStack(stack)); } + + @Override + public SpellAffinity getAffinity(ItemStack stack) { + return SpellAffinity.GOOD; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/model/ModelGem.java b/src/main/java/com/minelittlepony/unicopia/model/ModelGem.java index 14acf08d..a893cf8f 100644 --- a/src/main/java/com/minelittlepony/unicopia/model/ModelGem.java +++ b/src/main/java/com/minelittlepony/unicopia/model/ModelGem.java @@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.model; import com.minelittlepony.render.model.ModelQuads; import com.minelittlepony.unicopia.entity.EntitySpell; -import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.util.render.Color; import com.minelittlepony.util.render.Vertex; @@ -105,8 +104,7 @@ public class ModelGem extends ModelBase { setLightingConditionsBrightness(0xF0F0); - Color.glColor(SpellRegistry.instance().getSpellTint(spell.getEffect().getName()), 1); - + Color.glColor(spell.getEffect().getTint(), 1); int tiers = Math.min(spell.getCurrentLevel(), 5); diff --git a/src/main/java/com/minelittlepony/unicopia/player/IPlayer.java b/src/main/java/com/minelittlepony/unicopia/player/IPlayer.java index ec15deb9..c7296026 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/IPlayer.java +++ b/src/main/java/com/minelittlepony/unicopia/player/IPlayer.java @@ -30,6 +30,14 @@ public interface IPlayer extends ICaster, IRaceContainer { +class PlayerCapabilities implements IPlayer { private static final DataParameter PLAYER_RACE = EntityDataManager .createKey(EntityPlayer.class, DataSerializers.VARINT); - private static final DataParameter ENERGY = EntityDataManager - .createKey(EntityPlayer.class, DataSerializers.VARINT); + private static final DataParameter ENERGY = EntityDataManager + .createKey(EntityPlayer.class, DataSerializers.FLOAT); private static final DataParameter EXERTION = EntityDataManager .createKey(EntityPlayer.class, DataSerializers.FLOAT); @@ -67,8 +67,8 @@ class PlayerCapabilities implements IPlayer, ICaster { player.getDataManager().register(PLAYER_RACE, Race.HUMAN.ordinal()); player.getDataManager().register(EXERTION, 0F); + player.getDataManager().register(ENERGY, 0F); player.getDataManager().register(EFFECT, new NBTTagCompound()); - player.getDataManager().register(ENERGY, 0); } @Override @@ -107,6 +107,21 @@ class PlayerCapabilities implements IPlayer, ICaster { getOwner().getDataManager().set(EXERTION, Math.max(0, exertion)); } + @Override + public float getEnergy() { + return getOwner().getDataManager().get(ENERGY); + } + + @Override + public void setEnergy(float energy) { + getOwner().getDataManager().set(ENERGY, Math.max(0, energy)); + } + + @Override + public SpellAffinity getAffinity() { + return SpellAffinity.NEUTRAL; + } + @Override public void sendCapabilities(boolean full) { if (!getOwner().getEntityWorld().isRemote) { @@ -182,6 +197,7 @@ class PlayerCapabilities implements IPlayer, ICaster { } addExertion(-1); + addEnergy(-1); attributes.applyAttributes(entity, getPlayerSpecies()); } diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java index 6dd52685..de12955b 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerGravityDelegate.java @@ -1,8 +1,8 @@ package com.minelittlepony.unicopia.player; -import com.minelittlepony.unicopia.InbtSerialisable; import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.mixin.MixinEntity; +import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable; import net.minecraft.block.Block; import net.minecraft.block.SoundType; diff --git a/src/main/java/com/minelittlepony/unicopia/player/PlayerView.java b/src/main/java/com/minelittlepony/unicopia/player/PlayerView.java index 9263c33e..9cd9788e 100644 --- a/src/main/java/com/minelittlepony/unicopia/player/PlayerView.java +++ b/src/main/java/com/minelittlepony/unicopia/player/PlayerView.java @@ -2,8 +2,6 @@ package com.minelittlepony.unicopia.player; import com.minelittlepony.transform.MotionCompositor; -import net.minecraft.entity.player.EntityPlayer; - class PlayerView extends MotionCompositor implements IView { private final IPlayer player; @@ -15,15 +13,49 @@ class PlayerView extends MotionCompositor implements IView { } @Override - public double calculateRoll(EntityPlayer entity) { + public float calculateRoll() { double roll = baseRoll; if (player.getGravity().isFlying()) { - roll -= super.calculateRoll(entity, entity.motionX, entity.motionY, entity.motionZ); + roll -= super.calculateRoll(player.getOwner(), player.getOwner().motionX, player.getOwner().motionY, player.getOwner().motionZ); } - return player.getInterpolator().interpolate("roll", (float)roll, 100); + return (float)player.getInterpolator().interpolate("roll", (float)roll, 100); + } + + @Override + public float calculatePitch(float pitch) { + return pitch + getEnergyAddition(); + } + + @Override + public float calculateYaw(float yaw) { + return yaw + getEnergyAddition(); + } + + @Override + public float calculateFieldOfView(float fov) { + fov += player.getExertion() / 5; + fov += getEnergyAddition(); + + return fov; + } + + protected float getEnergyAddition() { + int maxE = (int)Math.floor(player.getEnergy() * 100); + + if (maxE <= 0) { + return 0; + } + + float energyAddition = (player.getWorld().rand.nextInt(maxE) - maxE/2) / 100F; + + if (Math.abs(energyAddition) <= 0.001) { + return 0; + } + + return energyAddition; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java index d9c526db..63583e27 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/AbstractSpell.java @@ -4,6 +4,16 @@ public abstract class AbstractSpell implements IMagicEffect { protected boolean isDead = false; + @Override + public int getCurrentLevel() { + return 0; + } + + @Override + public void setCurrentLevel(int level) { + + } + @Override public void setDead() { isDead = true; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java index be1699fa..00bf9c52 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/ICaster.java @@ -15,10 +15,13 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public interface ICaster extends IOwned, ILevelled { + void setEffect(IMagicEffect effect); IMagicEffect getEffect(); + SpellAffinity getAffinity(); + default boolean hasEffect() { return getEffect() != null; } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IDispenceable.java b/src/main/java/com/minelittlepony/unicopia/spell/IDispenceable.java index ef9f8415..45c30624 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IDispenceable.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IDispenceable.java @@ -16,7 +16,8 @@ public interface IDispenceable extends IMagicEffect { * @param pos Block position in front of the dispenser * @param facing Direction of the dispenser * @param source The dispenser currently dispensing + * @param affinity The affinity of the casting artifact * @return an ActionResult for the type of action to perform. */ - public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source); + public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source, SpellAffinity affinity); } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java index fb5a9e94..00a747cd 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IMagicEffect.java @@ -1,14 +1,22 @@ package com.minelittlepony.unicopia.spell; -import com.minelittlepony.unicopia.InbtSerialisable; +import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable; /** * Interface for a magic spells */ public interface IMagicEffect extends InbtSerialisable, ILevelled { + /** + * Gets the name used to identify this effect. + */ String getName(); + /** + * Gets the tint for this spell when applied to a gem. + */ + int getTint(); + /** * Sets this effect as dead. */ @@ -30,7 +38,8 @@ public interface IMagicEffect extends InbtSerialisable, ILevelled { } /** - * Called every tick when attached to a gem. + * Called every tick when attached to an entity. + * Called on both sides. * * @param source The entity we are currently attached to. * @param level Current active spell level diff --git a/src/main/java/com/minelittlepony/unicopia/spell/IUseAction.java b/src/main/java/com/minelittlepony/unicopia/spell/IUseAction.java index b32d4444..e36d1cd6 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/IUseAction.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/IUseAction.java @@ -19,6 +19,7 @@ public interface IUseAction { * Triggered when the player right clicks a block * * @param stack The current itemstack + * @param affinity The affinity of the casting artifact * @param player The player * @param world The player's world * @param pos The location clicked @@ -29,17 +30,18 @@ public interface IUseAction { * * @return ActionResult for the type of action to perform */ - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ); + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ); /** * Triggered when the player right clicks * * @param stack The current itemstack + * @param affinity The affinity of the casting artifact * @param player The player * @param world The player's world * @param hitEntity The entity in focus, if any * * @return ActionResult for the type of action to perform */ - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, @Nonnull Entity hitEntity); + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, @Nonnull Entity hitEntity); } diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java new file mode 100644 index 00000000..5ac0394a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellAffinity.java @@ -0,0 +1,34 @@ +package com.minelittlepony.unicopia.spell; + +import net.minecraft.util.text.TextFormatting; + +public enum SpellAffinity { + GOOD(TextFormatting.BLUE, -1), + NEUTRAL(TextFormatting.WHITE, 0), + BAD(TextFormatting.RED, 1); + + private final TextFormatting color; + + private final int corruption; + + SpellAffinity(TextFormatting color, int corruption) { + this.color = color; + this.corruption = corruption; + } + + public TextFormatting getColourCode() { + return color; + } + + public String getTranslationKey() { + return this == BAD ? "curse" : "spell"; + } + + public int getCorruption() { + return corruption; + } + + public boolean isNeutral() { + return this == NEUTRAL; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java index d2cb2ad6..0e3f2781 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellCharge.java @@ -33,6 +33,11 @@ public class SpellCharge extends AbstractSpell { return "charge"; } + @Override + public int getTint() { + return 0x0000AA; + } + @Override public void render(ICaster source, int level) { if (source.getWorld().rand.nextInt(4 + level * 4) == 0) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java index 9653cb0c..578ea0f4 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellFire.java @@ -68,21 +68,16 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl : s)); } - @Override - public int getCurrentLevel() { - return 0; - } - - - @Override - public void setCurrentLevel(int level) { - } - @Override public String getName() { return "fire"; } + @Override + public int getTint() { + return 0xFF0000; + } + @Override public boolean update(ICaster source, int level) { return false; @@ -90,14 +85,13 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl @Override public void render(ICaster source, int level) { - source.spawnParticles(visual_effect_region, level * 6, pos -> { source.getWorld().spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.x, pos.y, pos.z, 0, 0, 0); }); } @Override - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) { + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) { boolean result = false; if (player == null || player.isSneaking()) { @@ -117,12 +111,12 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl } @Override - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, @Nonnull Entity hitEntity) { + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, @Nonnull Entity hitEntity) { return applyEntitySingle(player, world, hitEntity) ? SpellCastResult.DEFAULT : SpellCastResult.NONE; } @Override - public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source) { + public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source, SpellAffinity affinity) { pos = pos.offset(facing, 4); boolean result = false; diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java index ee5d4394..608559df 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellIce.java @@ -5,6 +5,7 @@ import com.minelittlepony.util.MagicalDamageSource; import com.minelittlepony.util.PosHelper; import com.minelittlepony.util.blockstate.IStateMapping; import com.minelittlepony.util.blockstate.StateMapList; +import com.minelittlepony.util.shape.IShape; import com.minelittlepony.util.shape.Sphere; import com.minelittlepony.util.vector.VecHelper; @@ -29,9 +30,9 @@ import net.minecraft.world.World; public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable { - public static final StateMapList affected = new StateMapList(); + public final StateMapList affected = new StateMapList(); - static { + public SpellIce() { affected.add(IStateMapping.build( s -> s.getMaterial() == Material.WATER, s -> Blocks.ICE.getDefaultState())); @@ -40,27 +41,31 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable s -> Blocks.OBSIDIAN.getDefaultState())); affected.add(IStateMapping.build( s -> s.getBlock() == Blocks.SNOW_LAYER, - s -> s.cycleProperty(BlockSnow.LAYERS))); + s -> { + s = s.cycleProperty(BlockSnow.LAYERS); + if (s.getValue(BlockSnow.LAYERS) >= 7) { + return Blocks.SNOW.getDefaultState(); + } + + return s; + })); affected.replaceBlock(Blocks.FIRE, Blocks.AIR); affected.setProperty(Blocks.REDSTONE_WIRE, BlockRedstoneWire.POWER, 0); } - protected int rad = 3; - - @Override - public int getCurrentLevel() { - return 0; - } - - @Override - public void setCurrentLevel(int level) { - } + private final int rad = 3; + private final IShape effect_range = new Sphere(false, rad); @Override public String getName() { return "ice"; } + @Override + public int getTint() { + return 0xADD8E6; + } + @Override public boolean update(ICaster source, int level) { return false; @@ -71,12 +76,12 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable } @Override - public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source) { + public SpellCastResult onDispenced(BlockPos pos, EnumFacing facing, IBlockSource source, SpellAffinity affinity) { return applyBlocks(null, source.getWorld(), pos.offset(facing, rad)) ? SpellCastResult.NONE : SpellCastResult.DEFAULT; } @Override - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) { + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ) { if (player != null && player.isSneaking()) { applyBlockSingle(world, pos); } else { @@ -87,9 +92,8 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable } @Override - public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, Entity hitEntity) { - if (hitEntity != null) { - applyEntitySingle(player, hitEntity); + public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, Entity hitEntity) { + if (hitEntity != null && applyEntitySingle(player, hitEntity)) { return SpellCastResult.DEFAULT; } @@ -98,7 +102,7 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable private boolean applyBlocks(EntityPlayer owner, World world, BlockPos pos) { - for (BlockPos i : PosHelper.getAllInRegionMutable(pos, new Sphere(false, rad))) { + for (BlockPos i : PosHelper.getAllInRegionMutable(pos, effect_range)) { applyBlockSingle(world, i); } @@ -106,24 +110,23 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable } protected boolean applyEntities(EntityPlayer owner, World world, BlockPos pos) { - return VecHelper.findAllEntitiesInRange(owner, world, pos, 3).filter(i -> { - applyEntitySingle(owner, i); - return true; - }).count() > 0; + return VecHelper.findAllEntitiesInRange(owner, world, pos, 3).filter(i -> + applyEntitySingle(owner, i) + ).count() > 0; } - protected void applyEntitySingle(EntityPlayer owner, Entity e) { + protected boolean applyEntitySingle(EntityPlayer owner, Entity e) { if (e instanceof EntityTNTPrimed) { e.setDead(); e.getEntityWorld().setBlockState(e.getPosition(), Blocks.TNT.getDefaultState()); + } else if (e.isBurning()) { + e.extinguish(); } else { - if (e.isBurning()) { - e.extinguish(); - } else { - DamageSource d = MagicalDamageSource.causePlayerDamage("cold", owner); - e.attackEntityFrom(d, 2); - } + DamageSource d = MagicalDamageSource.causePlayerDamage("cold", owner); + e.attackEntityFrom(d, 2); } + + return true; } private void applyBlockSingle(World world, BlockPos pos) { @@ -138,7 +141,7 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable || (id == Blocks.SNOW) || (id instanceof BlockLeaves)) { incrementIce(world, pos.up()); - } else if (id == Blocks.ICE && world.rand.nextInt(10) == 0) { + } else if (state.getMaterial() == Material.ICE && world.rand.nextInt(10) == 0) { if (isSurroundedByIce(world, pos)) { world.setBlockState(pos, Blocks.PACKED_ICE.getDefaultState()); } @@ -148,13 +151,9 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable } public static boolean isSurroundedByIce(World w, BlockPos pos) { - return isIce(w, pos.up()) && isIce(w, pos.down()) && - isIce(w, pos.north()) && isIce(w, pos.south()) && - isIce(w, pos.east()) && isIce(w, pos.west()); - } - - public static boolean isIce(World world, BlockPos pos) { - return world.getBlockState(pos).getMaterial() == Material.ICE; + return !PosHelper.adjacentNeighbours(pos).stream().anyMatch(i -> + w.getBlockState(i).getMaterial() == Material.ICE + ); } private void incrementIce(World world, BlockPos pos) { diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java index 59a5166c..5b3ad079 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellRegistry.java @@ -6,6 +6,7 @@ import java.util.Set; import java.util.concurrent.Callable; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -25,10 +26,10 @@ public class SpellRegistry { private final Map entries = new HashMap<>(); private SpellRegistry() { - registerSpell("shield", 0x66CDAA, SpellShield::new); - registerSpell("charge", 0x0000AA, SpellCharge::new); - registerSpell("fire", 0xFF0000, SpellFire::new); - registerSpell("ice", 0xADD8E6, SpellIce::new); + registerSpell(SpellShield::new); + registerSpell(SpellCharge::new); + registerSpell(SpellFire::new); + registerSpell(SpellIce::new); } public IMagicEffect getSpellFromName(String name) { @@ -61,6 +62,7 @@ public class SpellRegistry { return compound; } + @Nullable public IDispenceable getDispenseActionFrom(ItemStack stack) { String key = getKeyFromStack(stack); @@ -74,13 +76,27 @@ public class SpellRegistry { return null; } + @Nullable + public IUseAction getUseActionFrom(ItemStack stack) { + String key = getKeyFromStack(stack); + + if (entries.containsKey(key)) { + Entry entry = entries.get(key); + if (entry.canUse) { + return entry.create(); + } + } + + return null; + } + public IMagicEffect getSpellFromItemStack(ItemStack stack) { return getSpellFromName(getKeyFromStack(stack)); } - public void registerSpell(String key, int tint, Callable factory) { + public void registerSpell(Callable factory) { try { - entries.put(key, new Entry(factory, tint)); + new Entry(factory); } catch (Exception e) { e.printStackTrace(); } @@ -143,11 +159,17 @@ public class SpellRegistry { int color; boolean canDispense; + boolean canUse; + + Entry(Callable factory) throws Exception { + IMagicEffect inst = factory.call(); - Entry(Callable factory, int color) throws Exception { this.factory = factory; - this.color = color; - this.canDispense = factory.call() instanceof IDispenceable; + this.color = inst.getTint(); + this.canDispense = inst instanceof IDispenceable; + this.canUse = inst instanceof IUseAction; + + entries.put(inst.getName(), this); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java index 9f0c026f..30965b07 100644 --- a/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java +++ b/src/main/java/com/minelittlepony/unicopia/spell/SpellShield.java @@ -36,6 +36,11 @@ public class SpellShield extends AbstractSpell { return "shield"; } + @Override + public int getTint() { + return 0x66CDAA; + } + @Override public int getMaxLevel() { return 17; diff --git a/src/main/java/com/minelittlepony/unicopia/InbtSerialisable.java b/src/main/java/com/minelittlepony/unicopia/util/serialisation/InbtSerialisable.java similarity index 91% rename from src/main/java/com/minelittlepony/unicopia/InbtSerialisable.java rename to src/main/java/com/minelittlepony/unicopia/util/serialisation/InbtSerialisable.java index b0be0ef9..89a1eea4 100644 --- a/src/main/java/com/minelittlepony/unicopia/InbtSerialisable.java +++ b/src/main/java/com/minelittlepony/unicopia/util/serialisation/InbtSerialisable.java @@ -1,4 +1,4 @@ -package com.minelittlepony.unicopia; +package com.minelittlepony.unicopia.util.serialisation; import net.minecraft.nbt.NBTTagCompound; diff --git a/src/main/java/com/minelittlepony/util/Iterators.java b/src/main/java/com/minelittlepony/util/Iterators.java new file mode 100644 index 00000000..eae25b7e --- /dev/null +++ b/src/main/java/com/minelittlepony/util/Iterators.java @@ -0,0 +1,65 @@ +package com.minelittlepony.util; + +import java.util.function.Supplier; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import com.google.common.collect.AbstractIterator; + +public interface Iterators extends Iterable { + + static Iterators iterate(Supplier producer) { + return () -> new AbstractIterator() { + @Override + protected T computeNext() { + T next = producer.get(); + + if (next == null) { + endOfData(); + } + + return next; + } + }; + } + + /** + * Returns a sequential {@code Stream} with this collection as its source. + * + *

This method should be overridden when the {@link #spliterator()} + * method cannot return a spliterator that is {@code IMMUTABLE}, + * {@code CONCURRENT}, or late-binding. (See {@link #spliterator()} + * for details.) + * + * @implSpec + * The default implementation creates a sequential {@code Stream} from the + * collection's {@code Spliterator}. + * + * @return a sequential {@code Stream} over the elements in this collection + * @since 1.8 + */ + default Stream stream() { + return StreamSupport.stream(spliterator(), false); + } + + /** + * Returns a possibly parallel {@code Stream} with this collection as its + * source. It is allowable for this method to return a sequential stream. + * + *

This method should be overridden when the {@link #spliterator()} + * method cannot return a spliterator that is {@code IMMUTABLE}, + * {@code CONCURRENT}, or late-binding. (See {@link #spliterator()} + * for details.) + * + * @implSpec + * The default implementation creates a parallel {@code Stream} from the + * collection's {@code Spliterator}. + * + * @return a possibly parallel {@code Stream} over the elements in this + * collection + * @since 1.8 + */ + default Stream parallelStream() { + return StreamSupport.stream(spliterator(), true); + } +} diff --git a/src/main/java/com/minelittlepony/util/PosHelper.java b/src/main/java/com/minelittlepony/util/PosHelper.java index 15888b06..0b2dd63d 100644 --- a/src/main/java/com/minelittlepony/util/PosHelper.java +++ b/src/main/java/com/minelittlepony/util/PosHelper.java @@ -5,7 +5,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; -import com.google.common.collect.AbstractIterator; +import com.google.common.collect.Lists; import com.google.common.collect.Streams; import com.minelittlepony.util.shape.IShape; @@ -31,29 +31,39 @@ public class PosHelper { return false; } - public static Iterable getAllInRegionMutable(BlockPos origin, IShape shape) { + public static Iterators adjacentNeighbours(BlockPos origin) { + MutableBlockPos pos = new MutableBlockPos(origin); + Iterator directions = Lists.newArrayList(EnumFacing.values()).iterator(); + return Iterators.iterate(() -> { + if (directions.hasNext()) { + EnumFacing next = directions.next(); + + pos.setPos(origin.getX() + next.getXOffset(), origin.getY() + next.getYOffset(), origin.getZ() + next.getZOffset()); + return pos; + } + + return null; + }); + } + + public static Iterators getAllInRegionMutable(BlockPos origin, IShape shape) { Iterator iter = BlockPos.getAllInBoxMutable( origin.add(new BlockPos(shape.getLowerBound())), origin.add(new BlockPos(shape.getUpperBound())) ).iterator(); - return () -> new AbstractIterator() { - @Override - protected MutableBlockPos computeNext() { - while (iter.hasNext()) { - MutableBlockPos pos = iter.next(); + return Iterators.iterate(() -> { + while (iter.hasNext()) { + MutableBlockPos pos = iter.next(); - if (shape.isPointInside(new Vec3d(pos.subtract(origin)))) { - return pos; - } + if (shape.isPointInside(new Vec3d(pos.subtract(origin)))) { + return pos; } - - endOfData(); - - return null; } - }; + + return null; + }); } /** diff --git a/src/main/resources/assets/unicopia/lang/en_US.lang b/src/main/resources/assets/unicopia/lang/en_US.lang index 23afc68a..cd84f0e5 100644 --- a/src/main/resources/assets/unicopia/lang/en_US.lang +++ b/src/main/resources/assets/unicopia/lang/en_US.lang @@ -21,23 +21,27 @@ item.dew_drop.name=Dew Drop item.cloud_anvil.name=Anvilhead Anvil item.gem.name=Gem +item.gem.enchanted.name=Gem of %s item.corrupted_gem.name=Fractured Gem -item.gem.shield.name=Gem of Repulsion -item.corrupted_gem.shield.name=Corrupt Gem of Repulsion -item.gem.charge.name=Channeling Gem -item.corrupted_gem.charge.name=Gem of Draining -item.gem.fire.name=Gem of Flame -item.corrupted_gem.fire.name=Corrupt Gem of Burning -item.gem.inferno.name=Gem of Inferno -item.corrupted_gem.inferno.name=Corrupt Gem of Inferno -item.gem.ice.name=Gem of Freezing -item.corrupted_gem.ice.name=Corrupt Gem of Freezing -item.gem.portal.name=Gem of Transportation -item.corrupted_gem.portal.name=Corrupt Gem of Transportation -item.gem.attract.name=Gem of Retention -item.corrupted_gem.attract.name=Gem of Entrapment -item.gem.minion.name=Gem of Obedience -item.corrupted_gem.minion.name=Corrupt Gem of Obedience +item.corrupted_gem.enchanted.name=Fractured Gem of %s + +spell.shield.name=Defense +spell.charge.name=Chanelling +spell.fire.name=Flame +spell.infero.name=Burning +spell.ice.name=Frost +spell.portal.name=Transportation +spell.attract.name=Retention +spell.minion.name=Obedience + +curse.shield.name=Repulsion +curse.charge.name=Draining +curse.fire.name=Hades +curse.inferno.name=Inferno +curse.ice.name=Freezing +curse.portal.name=Summoning +curse.attract.name=Entrapment +curse.minion.name=Slavery item.spellbook.name=Spellbook item.bag_of_holding.name=Bag of Holding