Implement sugar, implement spell affinities, fix some issues with the ice gem

This commit is contained in:
Sollace 2019-01-22 18:39:30 +02:00
parent cd0b86fc36
commit 35851d3f23
34 changed files with 486 additions and 164 deletions

View file

@ -115,8 +115,8 @@ public class UItems {
.setTranslationKey("alfalfa_leaves") .setTranslationKey("alfalfa_leaves")
.setRegistryName(Unicopia.MODID, "alfalfa_leaves"); .setRegistryName(Unicopia.MODID, "alfalfa_leaves");
public static final Item cereal = new ItemCereal(Unicopia.MODID, "cereal", 9, 0.8F); 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).setAlwaysEdible(); 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 tomato = new ItemTomato(Unicopia.MODID, "tomato", 4, 34);
public static final ItemTomato cloudsdale_tomato = new ItemTomato(Unicopia.MODID, "cloudsdale_tomato", 16, 4); public static final ItemTomato cloudsdale_tomato = new ItemTomato(Unicopia.MODID, "cloudsdale_tomato", 16, 4);

View file

@ -65,6 +65,7 @@ import com.minelittlepony.unicopia.network.MsgPlayerAbility;
import com.minelittlepony.unicopia.network.MsgPlayerCapabilities; import com.minelittlepony.unicopia.network.MsgPlayerCapabilities;
import com.minelittlepony.unicopia.network.MsgRequestCapabilities; import com.minelittlepony.unicopia.network.MsgRequestCapabilities;
import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.IView;
import com.minelittlepony.unicopia.player.PlayerSpeciesList; import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.power.PowersRegistry; import com.minelittlepony.unicopia.power.PowersRegistry;
import com.minelittlepony.unicopia.util.crafting.CraftingManager; import com.minelittlepony.unicopia.util.crafting.CraftingManager;
@ -205,7 +206,11 @@ public class Unicopia implements IGuiHandler {
EntityPlayer player = Minecraft.getMinecraft().player; EntityPlayer player = Minecraft.getMinecraft().player;
if (player != null) { 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 @SubscribeEvent
public static void modifyFOV(FOVUpdateEvent event) { public static void modifyFOV(FOVUpdateEvent event) {
float fov = event.getFov(); event.setNewfov(PlayerSpeciesList.instance().getPlayer(event.getEntity()).getCamera().calculateFieldOfView(event.getFov()));
fov += PlayerSpeciesList.instance().getPlayer(event.getEntity()).getExertion() / 5;
event.setNewfov(fov);
} }
@Override @Override

View file

@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.item.ICastable;
import com.minelittlepony.unicopia.network.EffectSync; import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.spell.ICaster; import com.minelittlepony.unicopia.spell.ICaster;
import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
@ -45,6 +46,9 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster<Enti
private static final DataParameter<NBTTagCompound> EFFECT = EntityDataManager private static final DataParameter<NBTTagCompound> EFFECT = EntityDataManager
.createKey(EntitySpell.class, DataSerializers.COMPOUND_TAG); .createKey(EntitySpell.class, DataSerializers.COMPOUND_TAG);
private static final DataParameter<Integer> AFFINITY = EntityDataManager
.createKey(EntitySpell.class, DataSerializers.VARINT);
private final EffectSync<EntityLivingBase> effectDelegate = new EffectSync<>(this, EFFECT); private final EffectSync<EntityLivingBase> effectDelegate = new EffectSync<>(this, EFFECT);
public EntitySpell(World w) { public EntitySpell(World w) {
@ -64,6 +68,15 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster<Enti
return super.isInRangeToRenderDist(distance); return super.isInRangeToRenderDist(distance);
} }
@Override
public SpellAffinity getAffinity() {
return SpellAffinity.values()[dataManager.get(AFFINITY)];
}
public void setAffinity(SpellAffinity affinity) {
dataManager.set(AFFINITY, affinity.ordinal());
}
@Override @Override
public void setEffect(IMagicEffect effect) { public void setEffect(IMagicEffect effect) {
effectDelegate.set(effect); effectDelegate.set(effect);
@ -80,6 +93,7 @@ public class EntitySpell extends EntityLiving implements IMagicals, ICaster<Enti
dataManager.register(LEVEL, 0); dataManager.register(LEVEL, 0);
dataManager.register(EFFECT, new NBTTagCompound()); dataManager.register(EFFECT, new NBTTagCompound());
dataManager.register(OWNER, ""); dataManager.register(OWNER, "");
dataManager.register(AFFINITY, SpellAffinity.NEUTRAL.ordinal());
} }
public ItemStack onPlayerMiddleClick(EntityPlayer player) { public ItemStack onPlayerMiddleClick(EntityPlayer player) {

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.forgebullshit; package com.minelittlepony.unicopia.forgebullshit;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.player.IPlayer; import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.IRaceContainer; import com.minelittlepony.unicopia.player.IRaceContainer;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;

View file

@ -4,9 +4,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.advancements.UAdvancements; import com.minelittlepony.unicopia.advancements.UAdvancements;
import com.minelittlepony.unicopia.item.IMagicalItem; import com.minelittlepony.unicopia.item.IMagicalItem;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import com.minelittlepony.util.MagicalDamageSource; import com.minelittlepony.util.MagicalDamageSource;
import net.minecraft.block.Block; import net.minecraft.block.Block;

View file

@ -20,4 +20,17 @@ public interface ICastable extends IMagicalItem {
boolean canFeed(EntitySpell spell, ItemStack stack); boolean canFeed(EntitySpell spell, ItemStack stack);
/**
* Called to cast a spell. The result is an entity spawned with the spell attached.
*/
default EntitySpell castContainedSpell(World world, BlockPos pos, ItemStack stack, IMagicEffect effect) {
EntitySpell spell = new EntitySpell(world);
spell.setAffinity(getAffinity(stack));
spell.setEffect(effect);
spell.setLocationAndAngles(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0, 0);
world.spawnEntity(spell);
return spell;
}
} }

View file

@ -1,5 +1,9 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import net.minecraft.item.ItemStack;
public interface IMagicalItem { public interface IMagicalItem {
/** /**
* If true this item serves as host to its own inner dimensional space. * If true this item serves as host to its own inner dimensional space.
@ -8,4 +12,12 @@ public interface IMagicalItem {
default boolean hasInnerSpace() { default boolean hasInnerSpace() {
return false; return false;
} }
/**
* Gets the affinity of this magical artifact. Either good, bad, or unaligned.
* What this returns may have effects on the behaviour of certain spells and effects.
*/
default SpellAffinity getAffinity(ItemStack stack) {
return SpellAffinity.NEUTRAL;
}
} }

View file

@ -1,6 +1,9 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.item.ItemFood; import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -8,6 +11,8 @@ import net.minecraft.world.World;
public class ItemCereal extends ItemFood { public class ItemCereal extends ItemFood {
private int sugarAmount;
public ItemCereal(String domain, String name, int amount, float saturation) { public ItemCereal(String domain, String name, int amount, float saturation) {
super(amount, saturation, false); super(amount, saturation, false);
@ -19,8 +24,20 @@ public class ItemCereal extends ItemFood {
public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) { public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) {
super.onItemUseFinish(stack, worldIn, entityLiving); super.onItemUseFinish(stack, worldIn, entityLiving);
this.setAlwaysEdible();
return new ItemStack(Items.BOWL); return new ItemStack(Items.BOWL);
} }
@Override
protected void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player) {
super.onFoodEaten(stack, worldIn, player);
if (sugarAmount != 0) {
PlayerSpeciesList.instance().getPlayer(player).addEnergy(sugarAmount);
}
}
public ItemCereal setSugarAmount(int sugar) {
sugarAmount = sugar;
return this;
}
} }

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.spell.IDispenceable; import com.minelittlepony.unicopia.spell.IDispenceable;
import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.unicopia.spell.SpellCastResult; import com.minelittlepony.unicopia.spell.SpellCastResult;
import com.minelittlepony.util.MagicalDamageSource; import com.minelittlepony.util.MagicalDamageSource;
@ -49,4 +50,9 @@ public class ItemCurse extends ItemSpell {
return result; return result;
} }
@Override
public SpellAffinity getAffinity(ItemStack stack) {
return SpellAffinity.BAD;
}
} }

View file

@ -125,6 +125,11 @@ public class ItemOfHolding extends Item implements IMagicalItem {
return new ActionResult<>(EnumActionResult.SUCCESS, stack); return new ActionResult<>(EnumActionResult.SUCCESS, stack);
} }
@Override
public boolean hasInnerSpace() {
return true;
}
public class Inventory implements IInteractionObject { public class Inventory implements IInteractionObject {
private String customname = null; private String customname = null;
@ -163,9 +168,4 @@ public class ItemOfHolding extends Item implements IMagicalItem {
return "unicopia:itemofholding"; return "unicopia:itemofholding";
} }
} }
@Override
public boolean hasInnerSpace() {
return true;
}
} }

View file

@ -1,21 +1,29 @@
package com.minelittlepony.unicopia.item; package com.minelittlepony.unicopia.item;
import java.util.List;
import javax.annotation.Nullable;
import com.minelittlepony.unicopia.Predicates; import com.minelittlepony.unicopia.Predicates;
import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.entity.EntitySpell;
import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.IUseAction; import com.minelittlepony.unicopia.spell.IUseAction;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.unicopia.spell.SpellCastResult; import com.minelittlepony.unicopia.spell.SpellCastResult;
import com.minelittlepony.unicopia.spell.IDispenceable; import com.minelittlepony.unicopia.spell.IDispenceable;
import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry;
import com.minelittlepony.util.vector.VecHelper; import com.minelittlepony.util.vector.VecHelper;
import net.minecraft.block.BlockDispenser; 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.creativetab.CreativeTabs;
import net.minecraft.dispenser.BehaviorDefaultDispenseItem; import net.minecraft.dispenser.BehaviorDefaultDispenseItem;
import net.minecraft.dispenser.IBehaviorDispenseItem; import net.minecraft.dispenser.IBehaviorDispenseItem;
import net.minecraft.dispenser.IBlockSource; import net.minecraft.dispenser.IBlockSource;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -37,24 +45,28 @@ public class ItemSpell extends Item implements ICastable {
return super.dispenseStack(source, stack); 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) { SpellCastResult dispenceResult = castable.onDispenseSpell(source, stack, effect);
return super.dispenseStack(source, stack);
}
if (dispenceResult == SpellCastResult.PLACE) { if (dispenceResult == SpellCastResult.DEFAULT) {
BlockPos pos = source.getBlockPos(); 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; return stack;
} }
}; };
protected String translationKey;
public ItemSpell(String domain, String name) { public ItemSpell(String domain, String name) {
super(); super();
@ -69,6 +81,11 @@ public class ItemSpell extends Item implements ICastable {
BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, dispenserBehavior); BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, dispenserBehavior);
} }
public Item setTranslationKey(String key) {
translationKey = key;
return super.setTranslationKey(key);
}
@Override @Override
public boolean hasEffect(ItemStack stack) { public boolean hasEffect(ItemStack stack) {
return SpellRegistry.stackHasEnchantment(stack); return SpellRegistry.stackHasEnchantment(stack);
@ -79,13 +96,13 @@ public class ItemSpell extends Item implements ICastable {
EnumFacing facing = source.getBlockState().getValue(BlockDispenser.FACING); EnumFacing facing = source.getBlockState().getValue(BlockDispenser.FACING);
BlockPos pos = source.getBlockPos().offset(facing); BlockPos pos = source.getBlockPos().offset(facing);
return effect.onDispenced(pos, facing, source); return effect.onDispenced(pos, facing, source, getAffinity(stack));
} }
@Override @Override
public SpellCastResult onCastSpell(EntityPlayer player, World world, BlockPos pos, ItemStack stack, IMagicEffect effect, EnumFacing side, float hitX, float hitY, float hitZ) { 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) { 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; return SpellCastResult.PLACE;
@ -110,7 +127,7 @@ public class ItemSpell extends Item implements ICastable {
return EnumActionResult.FAIL; 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) { if (!world.isRemote) {
pos = pos.offset(side); pos = pos.offset(side);
@ -146,10 +163,10 @@ public class ItemSpell extends Item implements ICastable {
return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack); return new ActionResult<ItemStack>(EnumActionResult.FAIL, stack);
} }
IMagicEffect effect = SpellRegistry.instance().getSpellFromItemStack(stack); IUseAction effect = SpellRegistry.instance().getUseActionFrom(stack);
if (effect instanceof IUseAction) { if (effect != null) {
SpellCastResult result = ((IUseAction)effect).onUse(stack, player, world, target); SpellCastResult result = effect.onUse(stack, getAffinity(stack), player, world, target);
if (result != SpellCastResult.NONE) { if (result != SpellCastResult.NONE) {
if (result == SpellCastResult.PLACE && !player.capabilities.isCreativeMode) { if (result == SpellCastResult.PLACE && !player.capabilities.isCreativeMode) {
@ -163,6 +180,35 @@ public class ItemSpell extends Item implements ICastable {
return new ActionResult<ItemStack>(EnumActionResult.PASS, stack); return new ActionResult<ItemStack>(EnumActionResult.PASS, stack);
} }
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> 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 @Override
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> subItems) { public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> subItems) {
super.getSubItems(tab, subItems); super.getSubItems(tab, subItems);
@ -175,31 +221,23 @@ public class ItemSpell extends Item implements ICastable {
} }
@Override @Override
public String getTranslationKey(ItemStack stack) { public EnumRarity getRarity(ItemStack stack) {
String result = super.getTranslationKey(stack);
if (SpellRegistry.stackHasEnchantment(stack)) { if (SpellRegistry.stackHasEnchantment(stack)) {
result += "." + stack.getTagCompound().getString("spell"); return EnumRarity.UNCOMMON;
} }
return result; return super.getRarity(stack);
}
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;
} }
@Override @Override
public boolean canFeed(EntitySpell entity, ItemStack stack) { public boolean canFeed(EntitySpell entity, ItemStack stack) {
IMagicEffect effect = entity.getEffect(); IMagicEffect effect = entity.getEffect();
return effect != null && effect.getName().equals(SpellRegistry.getKeyFromStack(stack)); return effect != null && effect.getName().equals(SpellRegistry.getKeyFromStack(stack));
} }
@Override
public SpellAffinity getAffinity(ItemStack stack) {
return SpellAffinity.GOOD;
}
} }

View file

@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.model;
import com.minelittlepony.render.model.ModelQuads; import com.minelittlepony.render.model.ModelQuads;
import com.minelittlepony.unicopia.entity.EntitySpell; import com.minelittlepony.unicopia.entity.EntitySpell;
import com.minelittlepony.unicopia.spell.SpellRegistry;
import com.minelittlepony.util.render.Color; import com.minelittlepony.util.render.Color;
import com.minelittlepony.util.render.Vertex; import com.minelittlepony.util.render.Vertex;
@ -105,8 +104,7 @@ public class ModelGem extends ModelBase {
setLightingConditionsBrightness(0xF0F0); setLightingConditionsBrightness(0xF0F0);
Color.glColor(SpellRegistry.instance().getSpellTint(spell.getEffect().getName()), 1); Color.glColor(spell.getEffect().getTint(), 1);
int tiers = Math.min(spell.getCurrentLevel(), 5); int tiers = Math.min(spell.getCurrentLevel(), 5);

View file

@ -30,6 +30,14 @@ public interface IPlayer extends ICaster<EntityPlayer>, IRaceContainer<EntityPla
setExertion(getExertion() + exertion/100F); setExertion(getExertion() + exertion/100F);
} }
float getEnergy();
void setEnergy(float energy);
default void addEnergy(int energy) {
setEnergy(getEnergy() + energy / 100F);
}
boolean isClientPlayer(); boolean isClientPlayer();
void copyFrom(IPlayer oldPlayer); void copyFrom(IPlayer oldPlayer);

View file

@ -1,7 +1,7 @@
package com.minelittlepony.unicopia.player; package com.minelittlepony.unicopia.player;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;

View file

@ -1,9 +1,13 @@
package com.minelittlepony.unicopia.player; package com.minelittlepony.unicopia.player;
import net.minecraft.entity.player.EntityPlayer;
public interface IView { public interface IView {
double calculateRoll(EntityPlayer player); float calculateRoll();
float calculatePitch(float pitch);
float calculateYaw(float yaw);
float calculateFieldOfView(float initialfow);
double getBaseRoll(); double getBaseRoll();

View file

@ -1,12 +1,12 @@
package com.minelittlepony.unicopia.player; package com.minelittlepony.unicopia.player;
import com.minelittlepony.jumpingcastle.api.Target; import com.minelittlepony.jumpingcastle.api.Target;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.network.MsgPlayerAbility; import com.minelittlepony.unicopia.network.MsgPlayerAbility;
import com.minelittlepony.unicopia.power.IData; import com.minelittlepony.unicopia.power.IData;
import com.minelittlepony.unicopia.power.IPower; import com.minelittlepony.unicopia.power.IPower;
import com.minelittlepony.unicopia.power.PowersRegistry; import com.minelittlepony.unicopia.power.PowersRegistry;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;

View file

@ -12,8 +12,8 @@ import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.network.EffectSync; import com.minelittlepony.unicopia.network.EffectSync;
import com.minelittlepony.unicopia.network.MsgPlayerCapabilities; import com.minelittlepony.unicopia.network.MsgPlayerCapabilities;
import com.minelittlepony.unicopia.spell.ICaster;
import com.minelittlepony.unicopia.spell.IMagicEffect; import com.minelittlepony.unicopia.spell.IMagicEffect;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.unicopia.spell.SpellRegistry; import com.minelittlepony.unicopia.spell.SpellRegistry;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -30,13 +30,13 @@ import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.potion.PotionEffect; import net.minecraft.potion.PotionEffect;
import net.minecraft.stats.StatList; import net.minecraft.stats.StatList;
class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> { class PlayerCapabilities implements IPlayer {
private static final DataParameter<Integer> PLAYER_RACE = EntityDataManager private static final DataParameter<Integer> PLAYER_RACE = EntityDataManager
.createKey(EntityPlayer.class, DataSerializers.VARINT); .createKey(EntityPlayer.class, DataSerializers.VARINT);
private static final DataParameter<Integer> ENERGY = EntityDataManager private static final DataParameter<Float> ENERGY = EntityDataManager
.createKey(EntityPlayer.class, DataSerializers.VARINT); .createKey(EntityPlayer.class, DataSerializers.FLOAT);
private static final DataParameter<Float> EXERTION = EntityDataManager private static final DataParameter<Float> EXERTION = EntityDataManager
.createKey(EntityPlayer.class, DataSerializers.FLOAT); .createKey(EntityPlayer.class, DataSerializers.FLOAT);
@ -67,8 +67,8 @@ class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> {
player.getDataManager().register(PLAYER_RACE, Race.HUMAN.ordinal()); player.getDataManager().register(PLAYER_RACE, Race.HUMAN.ordinal());
player.getDataManager().register(EXERTION, 0F); player.getDataManager().register(EXERTION, 0F);
player.getDataManager().register(ENERGY, 0F);
player.getDataManager().register(EFFECT, new NBTTagCompound()); player.getDataManager().register(EFFECT, new NBTTagCompound());
player.getDataManager().register(ENERGY, 0);
} }
@Override @Override
@ -107,6 +107,21 @@ class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> {
getOwner().getDataManager().set(EXERTION, Math.max(0, exertion)); 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 @Override
public void sendCapabilities(boolean full) { public void sendCapabilities(boolean full) {
if (!getOwner().getEntityWorld().isRemote) { if (!getOwner().getEntityWorld().isRemote) {
@ -182,6 +197,7 @@ class PlayerCapabilities implements IPlayer, ICaster<EntityPlayer> {
} }
addExertion(-1); addExertion(-1);
addEnergy(-1);
attributes.applyAttributes(entity, getPlayerSpecies()); attributes.applyAttributes(entity, getPlayerSpecies());
} }

View file

@ -1,8 +1,8 @@
package com.minelittlepony.unicopia.player; package com.minelittlepony.unicopia.player;
import com.minelittlepony.unicopia.InbtSerialisable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.mixin.MixinEntity; import com.minelittlepony.unicopia.mixin.MixinEntity;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;

View file

@ -2,8 +2,6 @@ package com.minelittlepony.unicopia.player;
import com.minelittlepony.transform.MotionCompositor; import com.minelittlepony.transform.MotionCompositor;
import net.minecraft.entity.player.EntityPlayer;
class PlayerView extends MotionCompositor implements IView { class PlayerView extends MotionCompositor implements IView {
private final IPlayer player; private final IPlayer player;
@ -15,15 +13,49 @@ class PlayerView extends MotionCompositor implements IView {
} }
@Override @Override
public double calculateRoll(EntityPlayer entity) { public float calculateRoll() {
double roll = baseRoll; double roll = baseRoll;
if (player.getGravity().isFlying()) { 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 @Override

View file

@ -4,6 +4,16 @@ public abstract class AbstractSpell implements IMagicEffect {
protected boolean isDead = false; protected boolean isDead = false;
@Override
public int getCurrentLevel() {
return 0;
}
@Override
public void setCurrentLevel(int level) {
}
@Override @Override
public void setDead() { public void setDead() {
isDead = true; isDead = true;

View file

@ -15,10 +15,13 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled { public interface ICaster<E extends EntityLivingBase> extends IOwned<E>, ILevelled {
void setEffect(IMagicEffect effect); void setEffect(IMagicEffect effect);
IMagicEffect getEffect(); IMagicEffect getEffect();
SpellAffinity getAffinity();
default boolean hasEffect() { default boolean hasEffect() {
return getEffect() != null; return getEffect() != null;
} }

View file

@ -16,7 +16,8 @@ public interface IDispenceable extends IMagicEffect {
* @param pos Block position in front of the dispenser * @param pos Block position in front of the dispenser
* @param facing Direction of the dispenser * @param facing Direction of the dispenser
* @param source The dispenser currently dispensing * @param source The dispenser currently dispensing
* @param affinity The affinity of the casting artifact
* @return an ActionResult for the type of action to perform. * @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);
} }

View file

@ -1,14 +1,22 @@
package com.minelittlepony.unicopia.spell; package com.minelittlepony.unicopia.spell;
import com.minelittlepony.unicopia.InbtSerialisable; import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
/** /**
* Interface for a magic spells * Interface for a magic spells
*/ */
public interface IMagicEffect extends InbtSerialisable, ILevelled { public interface IMagicEffect extends InbtSerialisable, ILevelled {
/**
* Gets the name used to identify this effect.
*/
String getName(); String getName();
/**
* Gets the tint for this spell when applied to a gem.
*/
int getTint();
/** /**
* Sets this effect as dead. * 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 source The entity we are currently attached to.
* @param level Current active spell level * @param level Current active spell level

View file

@ -19,6 +19,7 @@ public interface IUseAction {
* Triggered when the player right clicks a block * Triggered when the player right clicks a block
* *
* @param stack The current itemstack * @param stack The current itemstack
* @param affinity The affinity of the casting artifact
* @param player The player * @param player The player
* @param world The player's world * @param world The player's world
* @param pos The location clicked * @param pos The location clicked
@ -29,17 +30,18 @@ public interface IUseAction {
* *
* @return ActionResult for the type of action to perform * @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 * Triggered when the player right clicks
* *
* @param stack The current itemstack * @param stack The current itemstack
* @param affinity The affinity of the casting artifact
* @param player The player * @param player The player
* @param world The player's world * @param world The player's world
* @param hitEntity The entity in focus, if any * @param hitEntity The entity in focus, if any
* *
* @return ActionResult for the type of action to perform * @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);
} }

View file

@ -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;
}
}

View file

@ -33,6 +33,11 @@ public class SpellCharge extends AbstractSpell {
return "charge"; return "charge";
} }
@Override
public int getTint() {
return 0x0000AA;
}
@Override @Override
public void render(ICaster<?> source, int level) { public void render(ICaster<?> source, int level) {
if (source.getWorld().rand.nextInt(4 + level * 4) == 0) { if (source.getWorld().rand.nextInt(4 + level * 4) == 0) {

View file

@ -68,21 +68,16 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl
: s)); : s));
} }
@Override
public int getCurrentLevel() {
return 0;
}
@Override
public void setCurrentLevel(int level) {
}
@Override @Override
public String getName() { public String getName() {
return "fire"; return "fire";
} }
@Override
public int getTint() {
return 0xFF0000;
}
@Override @Override
public boolean update(ICaster<?> source, int level) { public boolean update(ICaster<?> source, int level) {
return false; return false;
@ -90,14 +85,13 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl
@Override @Override
public void render(ICaster<?> source, int level) { public void render(ICaster<?> source, int level) {
source.spawnParticles(visual_effect_region, level * 6, pos -> { source.spawnParticles(visual_effect_region, level * 6, pos -> {
source.getWorld().spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.x, pos.y, pos.z, 0, 0, 0); source.getWorld().spawnParticle(EnumParticleTypes.SMOKE_LARGE, pos.x, pos.y, pos.z, 0, 0, 0);
}); });
} }
@Override @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; boolean result = false;
if (player == null || player.isSneaking()) { if (player == null || player.isSneaking()) {
@ -117,12 +111,12 @@ public class SpellFire extends AbstractSpell implements IUseAction, IDispenceabl
} }
@Override @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; return applyEntitySingle(player, world, hitEntity) ? SpellCastResult.DEFAULT : SpellCastResult.NONE;
} }
@Override @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); pos = pos.offset(facing, 4);
boolean result = false; boolean result = false;

View file

@ -5,6 +5,7 @@ import com.minelittlepony.util.MagicalDamageSource;
import com.minelittlepony.util.PosHelper; import com.minelittlepony.util.PosHelper;
import com.minelittlepony.util.blockstate.IStateMapping; import com.minelittlepony.util.blockstate.IStateMapping;
import com.minelittlepony.util.blockstate.StateMapList; import com.minelittlepony.util.blockstate.StateMapList;
import com.minelittlepony.util.shape.IShape;
import com.minelittlepony.util.shape.Sphere; import com.minelittlepony.util.shape.Sphere;
import com.minelittlepony.util.vector.VecHelper; import com.minelittlepony.util.vector.VecHelper;
@ -29,9 +30,9 @@ import net.minecraft.world.World;
public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable { 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( affected.add(IStateMapping.build(
s -> s.getMaterial() == Material.WATER, s -> s.getMaterial() == Material.WATER,
s -> Blocks.ICE.getDefaultState())); s -> Blocks.ICE.getDefaultState()));
@ -40,27 +41,31 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
s -> Blocks.OBSIDIAN.getDefaultState())); s -> Blocks.OBSIDIAN.getDefaultState()));
affected.add(IStateMapping.build( affected.add(IStateMapping.build(
s -> s.getBlock() == Blocks.SNOW_LAYER, 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.replaceBlock(Blocks.FIRE, Blocks.AIR);
affected.setProperty(Blocks.REDSTONE_WIRE, BlockRedstoneWire.POWER, 0); affected.setProperty(Blocks.REDSTONE_WIRE, BlockRedstoneWire.POWER, 0);
} }
protected int rad = 3; private final int rad = 3;
private final IShape effect_range = new Sphere(false, rad);
@Override
public int getCurrentLevel() {
return 0;
}
@Override
public void setCurrentLevel(int level) {
}
@Override @Override
public String getName() { public String getName() {
return "ice"; return "ice";
} }
@Override
public int getTint() {
return 0xADD8E6;
}
@Override @Override
public boolean update(ICaster<?> source, int level) { public boolean update(ICaster<?> source, int level) {
return false; return false;
@ -71,12 +76,12 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
} }
@Override @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; return applyBlocks(null, source.getWorld(), pos.offset(facing, rad)) ? SpellCastResult.NONE : SpellCastResult.DEFAULT;
} }
@Override @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()) { if (player != null && player.isSneaking()) {
applyBlockSingle(world, pos); applyBlockSingle(world, pos);
} else { } else {
@ -87,9 +92,8 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
} }
@Override @Override
public SpellCastResult onUse(ItemStack stack, EntityPlayer player, World world, Entity hitEntity) { public SpellCastResult onUse(ItemStack stack, SpellAffinity affinity, EntityPlayer player, World world, Entity hitEntity) {
if (hitEntity != null) { if (hitEntity != null && applyEntitySingle(player, hitEntity)) {
applyEntitySingle(player, hitEntity);
return SpellCastResult.DEFAULT; return SpellCastResult.DEFAULT;
} }
@ -98,7 +102,7 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
private boolean applyBlocks(EntityPlayer owner, World world, BlockPos pos) { 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); applyBlockSingle(world, i);
} }
@ -106,24 +110,23 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
} }
protected boolean applyEntities(EntityPlayer owner, World world, BlockPos pos) { protected boolean applyEntities(EntityPlayer owner, World world, BlockPos pos) {
return VecHelper.findAllEntitiesInRange(owner, world, pos, 3).filter(i -> { return VecHelper.findAllEntitiesInRange(owner, world, pos, 3).filter(i ->
applyEntitySingle(owner, i); applyEntitySingle(owner, i)
return true; ).count() > 0;
}).count() > 0;
} }
protected void applyEntitySingle(EntityPlayer owner, Entity e) { protected boolean applyEntitySingle(EntityPlayer owner, Entity e) {
if (e instanceof EntityTNTPrimed) { if (e instanceof EntityTNTPrimed) {
e.setDead(); e.setDead();
e.getEntityWorld().setBlockState(e.getPosition(), Blocks.TNT.getDefaultState()); e.getEntityWorld().setBlockState(e.getPosition(), Blocks.TNT.getDefaultState());
} else if (e.isBurning()) {
e.extinguish();
} else { } else {
if (e.isBurning()) { DamageSource d = MagicalDamageSource.causePlayerDamage("cold", owner);
e.extinguish(); e.attackEntityFrom(d, 2);
} else {
DamageSource d = MagicalDamageSource.causePlayerDamage("cold", owner);
e.attackEntityFrom(d, 2);
}
} }
return true;
} }
private void applyBlockSingle(World world, BlockPos pos) { private void applyBlockSingle(World world, BlockPos pos) {
@ -138,7 +141,7 @@ public class SpellIce extends AbstractSpell implements IUseAction, IDispenceable
|| (id == Blocks.SNOW) || (id == Blocks.SNOW)
|| (id instanceof BlockLeaves)) { || (id instanceof BlockLeaves)) {
incrementIce(world, pos.up()); 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)) { if (isSurroundedByIce(world, pos)) {
world.setBlockState(pos, Blocks.PACKED_ICE.getDefaultState()); 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) { public static boolean isSurroundedByIce(World w, BlockPos pos) {
return isIce(w, pos.up()) && isIce(w, pos.down()) && return !PosHelper.adjacentNeighbours(pos).stream().anyMatch(i ->
isIce(w, pos.north()) && isIce(w, pos.south()) && w.getBlockState(i).getMaterial() == Material.ICE
isIce(w, pos.east()) && isIce(w, pos.west()); );
}
public static boolean isIce(World world, BlockPos pos) {
return world.getBlockState(pos).getMaterial() == Material.ICE;
} }
private void incrementIce(World world, BlockPos pos) { private void incrementIce(World world, BlockPos pos) {

View file

@ -6,6 +6,7 @@ import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
@ -25,10 +26,10 @@ public class SpellRegistry {
private final Map<String, Entry> entries = new HashMap<>(); private final Map<String, Entry> entries = new HashMap<>();
private SpellRegistry() { private SpellRegistry() {
registerSpell("shield", 0x66CDAA, SpellShield::new); registerSpell(SpellShield::new);
registerSpell("charge", 0x0000AA, SpellCharge::new); registerSpell(SpellCharge::new);
registerSpell("fire", 0xFF0000, SpellFire::new); registerSpell(SpellFire::new);
registerSpell("ice", 0xADD8E6, SpellIce::new); registerSpell(SpellIce::new);
} }
public IMagicEffect getSpellFromName(String name) { public IMagicEffect getSpellFromName(String name) {
@ -61,6 +62,7 @@ public class SpellRegistry {
return compound; return compound;
} }
@Nullable
public IDispenceable getDispenseActionFrom(ItemStack stack) { public IDispenceable getDispenseActionFrom(ItemStack stack) {
String key = getKeyFromStack(stack); String key = getKeyFromStack(stack);
@ -74,13 +76,27 @@ public class SpellRegistry {
return null; 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) { public IMagicEffect getSpellFromItemStack(ItemStack stack) {
return getSpellFromName(getKeyFromStack(stack)); return getSpellFromName(getKeyFromStack(stack));
} }
public void registerSpell(String key, int tint, Callable<IMagicEffect> factory) { public void registerSpell(Callable<IMagicEffect> factory) {
try { try {
entries.put(key, new Entry(factory, tint)); new Entry(factory);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -143,11 +159,17 @@ public class SpellRegistry {
int color; int color;
boolean canDispense; boolean canDispense;
boolean canUse;
Entry(Callable<IMagicEffect> factory) throws Exception {
IMagicEffect inst = factory.call();
Entry(Callable<IMagicEffect> factory, int color) throws Exception {
this.factory = factory; this.factory = factory;
this.color = color; this.color = inst.getTint();
this.canDispense = factory.call() instanceof IDispenceable; this.canDispense = inst instanceof IDispenceable;
this.canUse = inst instanceof IUseAction;
entries.put(inst.getName(), this);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View file

@ -36,6 +36,11 @@ public class SpellShield extends AbstractSpell {
return "shield"; return "shield";
} }
@Override
public int getTint() {
return 0x66CDAA;
}
@Override @Override
public int getMaxLevel() { public int getMaxLevel() {
return 17; return 17;

View file

@ -1,4 +1,4 @@
package com.minelittlepony.unicopia; package com.minelittlepony.unicopia.util.serialisation;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;

View file

@ -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<T> extends Iterable<T> {
static <T> Iterators<T> iterate(Supplier<T> producer) {
return () -> new AbstractIterator<T>() {
@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.
*
* <p>This method should be overridden when the {@link #spliterator()}
* method cannot return a spliterator that is {@code IMMUTABLE},
* {@code CONCURRENT}, or <em>late-binding</em>. (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<T> 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.
*
* <p>This method should be overridden when the {@link #spliterator()}
* method cannot return a spliterator that is {@code IMMUTABLE},
* {@code CONCURRENT}, or <em>late-binding</em>. (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<T> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}

View file

@ -5,7 +5,7 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; 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.google.common.collect.Streams;
import com.minelittlepony.util.shape.IShape; import com.minelittlepony.util.shape.IShape;
@ -31,29 +31,39 @@ public class PosHelper {
return false; return false;
} }
public static Iterable<MutableBlockPos> getAllInRegionMutable(BlockPos origin, IShape shape) { public static Iterators<MutableBlockPos> adjacentNeighbours(BlockPos origin) {
MutableBlockPos pos = new MutableBlockPos(origin);
Iterator<EnumFacing> 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<MutableBlockPos> getAllInRegionMutable(BlockPos origin, IShape shape) {
Iterator<MutableBlockPos> iter = BlockPos.getAllInBoxMutable( Iterator<MutableBlockPos> iter = BlockPos.getAllInBoxMutable(
origin.add(new BlockPos(shape.getLowerBound())), origin.add(new BlockPos(shape.getLowerBound())),
origin.add(new BlockPos(shape.getUpperBound())) origin.add(new BlockPos(shape.getUpperBound()))
).iterator(); ).iterator();
return () -> new AbstractIterator<MutableBlockPos>() { return Iterators.iterate(() -> {
@Override while (iter.hasNext()) {
protected MutableBlockPos computeNext() { MutableBlockPos pos = iter.next();
while (iter.hasNext()) {
MutableBlockPos pos = iter.next();
if (shape.isPointInside(new Vec3d(pos.subtract(origin)))) { if (shape.isPointInside(new Vec3d(pos.subtract(origin)))) {
return pos; return pos;
}
} }
endOfData();
return null;
} }
};
return null;
});
} }
/** /**

View file

@ -21,23 +21,27 @@ item.dew_drop.name=Dew Drop
item.cloud_anvil.name=Anvilhead Anvil item.cloud_anvil.name=Anvilhead Anvil
item.gem.name=Gem item.gem.name=Gem
item.gem.enchanted.name=Gem of %s
item.corrupted_gem.name=Fractured Gem item.corrupted_gem.name=Fractured Gem
item.gem.shield.name=Gem of Repulsion item.corrupted_gem.enchanted.name=Fractured Gem of %s
item.corrupted_gem.shield.name=Corrupt Gem of Repulsion
item.gem.charge.name=Channeling Gem spell.shield.name=Defense
item.corrupted_gem.charge.name=Gem of Draining spell.charge.name=Chanelling
item.gem.fire.name=Gem of Flame spell.fire.name=Flame
item.corrupted_gem.fire.name=Corrupt Gem of Burning spell.infero.name=Burning
item.gem.inferno.name=Gem of Inferno spell.ice.name=Frost
item.corrupted_gem.inferno.name=Corrupt Gem of Inferno spell.portal.name=Transportation
item.gem.ice.name=Gem of Freezing spell.attract.name=Retention
item.corrupted_gem.ice.name=Corrupt Gem of Freezing spell.minion.name=Obedience
item.gem.portal.name=Gem of Transportation
item.corrupted_gem.portal.name=Corrupt Gem of Transportation curse.shield.name=Repulsion
item.gem.attract.name=Gem of Retention curse.charge.name=Draining
item.corrupted_gem.attract.name=Gem of Entrapment curse.fire.name=Hades
item.gem.minion.name=Gem of Obedience curse.inferno.name=Inferno
item.corrupted_gem.minion.name=Corrupt Gem of Obedience curse.ice.name=Freezing
curse.portal.name=Summoning
curse.attract.name=Entrapment
curse.minion.name=Slavery
item.spellbook.name=Spellbook item.spellbook.name=Spellbook
item.bag_of_holding.name=Bag of Holding item.bag_of_holding.name=Bag of Holding