Added the alicorn amulet

This commit is contained in:
Sollace 2019-02-17 19:22:11 +02:00
parent a35ec07dcf
commit 900f5e6de0
18 changed files with 503 additions and 22 deletions

View file

@ -1,5 +1,6 @@
package com.minelittlepony.unicopia.init;
import com.minelittlepony.unicopia.item.ItemAlicornAmulet;
import com.minelittlepony.unicopia.item.ItemApple;
import com.minelittlepony.unicopia.item.ItemAppleMultiType;
import com.minelittlepony.unicopia.item.ItemCereal;
@ -109,6 +110,7 @@ public class UItems {
public static final ItemSpell curse = new ItemCurse(Unicopia.MODID, "corrupted_gem");
public static final ItemOfHolding bag_of_holding = new ItemOfHolding(Unicopia.MODID, "bag_of_holding");
public static final ItemAlicornAmulet alicorn_amulet = new ItemAlicornAmulet(Unicopia.MODID, "alicorn_amulet");
public static final ItemSpellbook spellbook = new ItemSpellbook(Unicopia.MODID, "spellbook");
public static final Item staff_meadow_brook = new ItemStaff(Unicopia.MODID, "staff_meadow_brook").setMaxDamage(2);
@ -212,7 +214,7 @@ public class UItems {
cloud_farmland, mist_door, anvil,
bag_of_holding, spell, curse, spellbook, mug, enchanted_torch,
staff_meadow_brook,
staff_meadow_brook, alicorn_amulet,
alfalfa_seeds, alfalfa_leaves,
cereal, sugar_cereal, sugar_block,
@ -242,7 +244,7 @@ public class UItems {
cloud_farmland, mist_door, anvil,
bag_of_holding, spell, curse, spellbook, mug, enchanted_torch,
staff_meadow_brook,
staff_meadow_brook, alicorn_amulet,
alfalfa_seeds, alfalfa_leaves,
cereal, sugar_cereal, sugar_block,

View file

@ -0,0 +1,7 @@
package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.player.IPlayer;
public interface IDependable extends IMagicalItem {
void onRemoved(IPlayer player, float needfulness);
}

View file

@ -0,0 +1,239 @@
package com.minelittlepony.unicopia.item;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.minelittlepony.unicopia.UClient;
import com.minelittlepony.unicopia.player.IPlayer;
import com.minelittlepony.unicopia.player.PlayerSpeciesList;
import com.minelittlepony.unicopia.spell.SpellAffinity;
import com.minelittlepony.util.MagicalDamageSource;
import com.minelittlepony.util.vector.VecHelper;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.StringUtils;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.World;
public class ItemAlicornAmulet extends ItemArmor implements IDependable {
private static final UUID[] ARMOR_MODIFIERS = new UUID[] {
UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"),
UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"),
UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"),
UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")
};
public ItemAlicornAmulet(String domain, String name) {
super(ArmorMaterial.GOLD, 1, EntityEquipmentSlot.CHEST);
setTranslationKey(name);
setRegistryName(domain, name);
}
@Override
public SpellAffinity getAffinity() {
return SpellAffinity.BAD;
}
@Override
public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) {
return toRepair.getItem() == repair.getItem();
}
@Override
public boolean onEntityItemUpdate(EntityItem entity) {
World world = entity.world;
double x = entity.posX + world.rand.nextFloat() - 0.5;
double z = entity.posZ + world.rand.nextFloat() - 0.5;
double y = entity.posY + world.rand.nextFloat();
EnumParticleTypes particle = world.rand.nextBoolean() ? EnumParticleTypes.SMOKE_LARGE : EnumParticleTypes.FLAME;
world.spawnParticle(particle, x, y, z, 0, 0, 0);
if (world.rand.nextInt(500) == 0) {
world.playSound(null, entity.getPosition(), SoundEvents.AMBIENT_CAVE, SoundCategory.HOSTILE, 0.5F, 1);
}
Vec3d position = entity.getPositionVector();
VecHelper.findAllEntitiesInRange(entity, world, entity.getPosition(), 10)
.filter(e -> e instanceof EntityPlayer)
.sorted((a, b) -> (int)(a.getPositionVector().distanceTo(position) - b.getPositionVector().distanceTo(position)))
.findFirst()
.ifPresent(player -> interactWithPlayer(entity, (EntityPlayer)player));
return false;
}
protected void interactWithPlayer(EntityItem entity, EntityPlayer player) {
double diffX = player.posX - entity.posX;
double diffY = player.posY - entity.posY;
double diffZ = player.posZ - entity.posZ;
entity.move(MoverType.SELF, diffX / 50, diffY / 50, diffZ / 50);
if (!player.world.isRemote && !entity.isDead) {
if (player.getPositionVector().distanceTo(entity.getPositionVector()) < 3) {
if (entity.world.rand.nextInt(150) == 0) {
player.setItemStackToSlot(getEquipmentSlot(), entity.getItem());
entity.setPickupDelay(1000);
entity.setDead();
}
}
}
}
@Override
public void addInformation(ItemStack stack, @Nullable World worldIn, List<String> tooltip, ITooltipFlag flagIn) {
IPlayer iplayer = UClient.instance().getIPlayer();
if (iplayer != null) {
int attachedTime = iplayer.getInventory().getTicksAttached(this);
if (attachedTime > 0) {
tooltip.add(I18n.format(this.getTranslationKey() + ".tagline", StringUtils.ticksToElapsedTime(attachedTime)));
}
}
}
@Override
public String getItemStackDisplayName(ItemStack stack) {
if (!stack.hasTagCompound()) {
stack.setTagCompound(new NBTTagCompound());
}
NBTTagCompound compound = stack.getTagCompound();
int hideFlags = 0;
if (!compound.hasKey("HideFlags") || ((hideFlags = compound.getInteger("HideFlags")) & 2) == 0) {
compound.setInteger("HideFlags", hideFlags | 2);
}
return super.getItemStackDisplayName(stack);
}
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack) {
if (player.getHealth() < player.getMaxHealth()) {
player.heal(0.5F);
} else if (player.canEat(false)) {
player.getFoodStats().addStats(1, 0);
}
IPlayer iplayer = PlayerSpeciesList.instance().getPlayer(player);
if (iplayer.getExertion() < 1) {
iplayer.addExertion(2);
}
if (iplayer.getEnergy() < 0.005F) {
iplayer.addEnergy(2);
}
int attachedTime = iplayer.getInventory().getTicksAttached(this);
if (attachedTime == 1) {
world.playSound(null, player.getPosition(), SoundEvents.ENTITY_ELDER_GUARDIAN_CURSE, SoundCategory.PLAYERS, 3, 1);
}
if (attachedTime > 0 && attachedTime % 100 == 0) {
world.playSound(null, player.getPosition(), SoundEvents.MUSIC_NETHER, SoundCategory.PLAYERS, 3, 1);
}
if (attachedTime > 1000) {
if (world.rand.nextInt(700) == 0) {
player.dropItem(false);
}
}
if (attachedTime > 3000) {
if (world.rand.nextInt(300) == 0) {
player.motionX += world.rand.nextFloat() - 0.5F;
}
if (world.rand.nextInt(300) == 0) {
player.motionZ += world.rand.nextFloat() - 0.5F;
}
}
if (attachedTime > 6000) {
if (world.rand.nextInt(300) == 0) {
player.rotationYaw += 180;
}
}
if (attachedTime > 13000) {
if (world.rand.nextInt(300) == 0) {
DamageSource source = MagicalDamageSource.causePlayerDamage("alicorn_amulet", player);
player.attackEntityFrom(source, 0.5F);
}
}
iplayer.getInventory().enforceDependency(this);
}
@Override
public void onRemoved(IPlayer player, float needfulness) {
float attachedTime = player.getInventory().getTicksAttached(this) / 100F;
DamageSource source = MagicalDamageSource.causePlayerDamage("alicorn_amulet", player.getOwner());
DifficultyInstance difficulty = player.getWorld().getDifficultyForLocation(player.getOrigin());
float amount = (attachedTime * (1 + needfulness)) * (1 + difficulty.getClampedAdditionalDifficulty());
player.getOwner().attackEntityFrom(source, amount);
if (attachedTime > 120) {
player.getOwner().knockBack(player.getOwner(), 1, 1, 1);
}
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand) {
ActionResult<ItemStack> result = super.onItemRightClick(world, player, hand);
return result;
}
@Override
public Multimap<String, AttributeModifier> getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot) {
Multimap<String, AttributeModifier> multimap = HashMultimap.create();;
if (equipmentSlot == armorType) {
UUID modifierId = ARMOR_MODIFIERS[equipmentSlot.getIndex()];
multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(modifierId, "Armor modifier", Integer.MAX_VALUE, 0));
multimap.put(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName(), new AttributeModifier(modifierId, "Armor toughness", 20, 0));
multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(modifierId, "Strength modifier", 50, 0));
}
return multimap;
}
}

View file

@ -3,9 +3,20 @@ package com.minelittlepony.unicopia.player;
import net.minecraft.item.ItemStack;
public interface IFood {
/**
* Start eating a piece of food.
* @param stack
*/
void begin(ItemStack stack);
/**
* Ends eating. Eating was cancelled.
*/
void end();
/**
* Finish eating. *burp*
*/
void finish();
}

View file

@ -0,0 +1,32 @@
package com.minelittlepony.unicopia.player;
import com.minelittlepony.unicopia.item.IDependable;
import com.minelittlepony.unicopia.item.IMagicalItem;
public interface IInventory {
/**
* Reinforces a players dependency on a certain magical artifact.
* A dependency will slowly drop over time if not reinforced
*
* Bad things might happen when it's removed.
*/
void enforceDependency(IDependable item);
/**
* Checks if the player is wearing the specified magical artifact.
*/
boolean isWearing(IMagicalItem item);
/**
* Returns how long the player has been wearing the given item.
*/
int getTicksAttached(IDependable item);
/**
* Returns how dependent the player has become on the given item.
*
* Zero means not dependent at all / not wearing.
*/
float getNeedfulness(IDependable item);
}

View file

@ -45,6 +45,11 @@ public interface IPlayer extends ICaster<EntityPlayer>, IRaceContainer<EntityPla
*/
IFood getFood();
/**
* Gets the inventory delegate for this player.
*/
IInventory getInventory();
/**
* Gets an animation interpolator.
*/

View file

@ -10,18 +10,13 @@ import net.minecraft.entity.Entity;
*
* @param <T> The type of owner
*/
public interface IRaceContainer<T extends Entity> extends InbtSerialisable {
public interface IRaceContainer<T extends Entity> extends InbtSerialisable, IUpdatable {
Race getPlayerSpecies();
void setPlayerSpecies(Race race);
void onDimensionalTravel(int destinationDimension);
/**
* Called to update this container's logic
*/
void onUpdate();
/**
* Called at the beginning of a player's update cycle.
*/

View file

@ -1,5 +1,12 @@
package com.minelittlepony.unicopia.player;
public interface IUpdatable<T> {
void onUpdate(T sender);
/**
* Interface for objects that receive regular updates.
*/
@FunctionalInterface
public interface IUpdatable {
/**
* Called to update the internal logic.
*/
void onUpdate();
}

View file

@ -11,10 +11,9 @@ import com.minelittlepony.unicopia.power.IPower;
import com.minelittlepony.unicopia.power.PowersRegistry;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
class PlayerAbilityDelegate implements IAbilityReceiver, IUpdatable<EntityPlayer>, InbtSerialisable {
class PlayerAbilityDelegate implements IAbilityReceiver, IUpdatable, InbtSerialisable {
private final IPlayer player;
@ -84,7 +83,7 @@ class PlayerAbilityDelegate implements IAbilityReceiver, IUpdatable<EntityPlayer
}
@Override
public void onUpdate(EntityPlayer entity) {
public void onUpdate() {
IPower<?> ability = getUsableAbility();
if (ability == null) {

View file

@ -60,6 +60,8 @@ class PlayerCapabilities implements IPlayer {
private final PlayerFood food = new PlayerFood(this);
private final PlayerInventory inventory = new PlayerInventory(this);
private final EffectSync<EntityPlayer> effectDelegate = new EffectSync<>(this, EFFECT);
private final IInterpolator interpolator = new BasicEasingInterpolator();
@ -198,8 +200,9 @@ class PlayerCapabilities implements IPlayer {
@Override
public void onUpdate() {
powers.onUpdate(entity);
gravity.onUpdate(entity);
powers.onUpdate();
gravity.onUpdate();
inventory.onUpdate();
if (hasEffect()) {
if (entity.getEntityWorld().isRemote) {
@ -270,6 +273,11 @@ class PlayerCapabilities implements IPlayer {
return food;
}
@Override
public IInventory getInventory() {
return inventory;
}
@Override
public void onEat(ItemStack stack, @Nullable ItemFood food) {
if (getPlayerSpecies() == Race.CHANGELING) {

View file

@ -10,10 +10,12 @@ class PlayerFood implements IFood {
private ItemStack eatingStack = ItemStack.EMPTY;
public PlayerFood(IPlayer player) {
this.player = player;
}
@Override
public void begin(ItemStack stack) {
eatingStack = ItemStack.EMPTY;
@ -38,5 +40,4 @@ class PlayerFood implements IFood {
player.onEat(eatingStack, (ItemFood)eatingStack.getItem());
}
}
}

View file

@ -21,7 +21,7 @@ import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtSerialisable, IFlyingPredicate, IPlayerHeightPredicate {
class PlayerGravityDelegate implements IUpdatable, IGravity, InbtSerialisable, IFlyingPredicate, IPlayerHeightPredicate {
private final IPlayer player;
@ -98,7 +98,8 @@ class PlayerGravityDelegate implements IUpdatable<EntityPlayer>, IGravity, InbtS
@Override
public void onUpdate(EntityPlayer entity) {
public void onUpdate() {
EntityPlayer entity = player.getOwner();
entity.capabilities.allowFlying = checkCanFly(player);

View file

@ -0,0 +1,155 @@
package com.minelittlepony.unicopia.player;
import java.util.Iterator;
import java.util.Map;
import com.google.common.collect.Maps;
import com.minelittlepony.unicopia.item.IDependable;
import com.minelittlepony.unicopia.item.IMagicalItem;
import com.minelittlepony.unicopia.util.serialisation.InbtSerialisable;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
public class PlayerInventory implements IInventory, IUpdatable, InbtSerialisable {
private final Map<IDependable, Entry> dependencies = Maps.newHashMap();
private final IPlayer player;
PlayerInventory(IPlayer player) {
this.player = player;
}
@Override
public synchronized void enforceDependency(IDependable item) {
if (dependencies.containsKey(item)) {
dependencies.get(item).reinforce();
} else {
dependencies.put(item, new Entry(item));
}
}
@Override
public synchronized int getTicksAttached(IDependable item) {
if (dependencies.containsKey(item)) {
return dependencies.get(item).ticksAttached;
}
return 0;
}
@Override
public synchronized float getNeedfulness(IDependable item) {
if (dependencies.containsKey(item)) {
return dependencies.get(item).needfulness;
}
return 0;
}
@Override
public synchronized void onUpdate() {
Iterator<Map.Entry<IDependable, Entry>> iterator = dependencies.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<IDependable, Entry> entry = iterator.next();
Entry item = entry.getValue();
item.onUpdate();
if (item.needfulness <= 0.001) {
iterator.remove();
}
}
}
@Override
public boolean isWearing(IMagicalItem item) {
for (ItemStack i : player.getOwner().getArmorInventoryList()) {
if (!i.isEmpty() && i.getItem() == item) {
return true;
}
}
return false;
}
@Override
public void writeToNBT(NBTTagCompound compound) {
NBTTagList items = new NBTTagList();
for (Entry entry : dependencies.values()) {
items.appendTag(entry.toNBT());
}
compound.setTag("dependencies", items);
}
@SuppressWarnings("unchecked")
@Override
public void readFromNBT(NBTTagCompound compound) {
dependencies.clear();
compound.getTagList("dependencies", 10).forEach(res -> {
Entry entry = new Entry();
entry.readFromNBT((NBTTagCompound)res);
if (entry.item != null) {
dependencies.put(entry.item, entry);
}
});
}
class Entry implements IUpdatable, InbtSerialisable {
int ticksAttached = 0;
float needfulness = 1;
IDependable item;
Entry() {
}
Entry(IDependable key) {
this.item = key;
}
void reinforce() {
needfulness = Math.min(30, needfulness + 1);
}
@Override
public void onUpdate() {
if (isWearing(item)) {
ticksAttached ++;
needfulness *= 0.9F;
} else {
item.onRemoved(player, needfulness);
needfulness = 0;
}
}
@Override
public void writeToNBT(NBTTagCompound compound) {
compound.setInteger("ticksAttached", ticksAttached);
compound.setFloat("needfulness", needfulness);
compound.setString("item", ((Item)item).getRegistryName().toString());
}
@Override
public void readFromNBT(NBTTagCompound compound) {
ticksAttached = compound.getInteger("ticksAttached");
needfulness = compound.getFloat("needfulness");
Item item = Item.getByNameOrId(compound.getString("item"));
this.item = item instanceof IDependable ? (IDependable)item : null;
}
}
}

View file

@ -6,7 +6,6 @@ import java.util.Random;
import com.google.common.collect.Queues;
import com.minelittlepony.jumpingcastle.Exceptions;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.player.IUpdatable;
import com.minelittlepony.unicopia.structure.CloudDungeon;
import com.minelittlepony.unicopia.structure.GroundDungeon;
@ -20,7 +19,7 @@ import net.minecraft.world.gen.structure.MapGenStructureIO;
import net.minecraftforge.fml.common.IWorldGenerator;
import net.minecraftforge.fml.common.registry.GameRegistry;
public class UWorld implements IWorldGenerator, IUpdatable<World> {
public class UWorld implements IWorldGenerator {
private static final UWorld instance = new UWorld();
@ -52,7 +51,6 @@ public class UWorld implements IWorldGenerator, IUpdatable<World> {
MapGenStructureIO.registerStructureComponent(GroundDungeon.class, "unicopia:ground_dungeon");
}
@Override
public void onUpdate(World world) {
synchronized (locker) {
Runnable task;

View file

@ -29,6 +29,8 @@ item.cloud_anvil.name=Anvilhead Anvil
item.staff_meadow_brook.name=Meadow Brook's Staff
item.staff_meadow_brook.tagline=It's a big stick
item.alicorn_amulet.name=The Alicorn Amulet
item.alicorn_amulet.tagline=Time Worn: %s
item.gem.name=Gem
item.gem.enchanted.name=Gem of %s
@ -227,6 +229,7 @@ unicopia.power.disguise=Secondary Changeling ability
unicopia.gui.title.bagofholding=Bag of Holding
death.attack.alicorn_amulet=%1$s was driven insane
death.attack.darkness=%1$s went missing
death.attack.feed=%1$s was drained of all life
death.attack.feed.player=%1$s died to feed %2$s
@ -244,7 +247,7 @@ death.attack.food_poisoning=%1$s died of food poisoning
death.attack.food_poisoning.player=%1$s poisoned %1$s' to death
advancements.adventure.bag_of_holding.title=Read the Manual
advancements.adventure.bag_of_holding.description=Successfuly die using the Bag of Holding
advancements.adventure.bag_of_holding.description=Successfully die using the Bag of Holding
advancements.adventure.bag_of_holding_2.title=Oops! I did it again
advancements.adventure.bag_of_holding_2.description=Die by the Bag of Holding a second time

View file

@ -0,0 +1,18 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:items/alicorn_amulet"
},
"display": {
"thirdperson": {
"rotation": [ -90, 0, 0 ],
"translation": [ 0, 1, -3 ],
"scale": [ 0.55, 0.55, 0.55 ]
},
"firstperson": {
"rotation": [ 0, -135, 25 ],
"translation": [ 0, 4, 2 ],
"scale": [ 1.7, 1.7, 1.7 ]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 B