First stab at Living Armour reimplementation.

Added a lot of the upgrades, but there's still more testing/upgrades to be done/reimplemented.
This commit is contained in:
WayofTime 2020-11-28 12:04:11 -05:00
parent 06faa916c3
commit 2075fa5be3
42 changed files with 2352 additions and 2 deletions

View file

@ -56,7 +56,7 @@ e6d9cf699667aaa47efff37b2b033895dee29c15 assets/bloodmagic/blockstates/waterritu
42f26f715bddd16c069f9b51e3767b36477c8908 assets/bloodmagic/blockstates/woodtilepath.json
3c6ce233dae6c1307d9016406c324bbe844b4e1e assets/bloodmagic/blockstates/wornstonebrickpath.json
d59655f12d1724b73b77c373fb6864fcff69db12 assets/bloodmagic/blockstates/wornstonetilepath.json
c220fc49d1981be98283901bf1b50702f5c021cd assets/bloodmagic/lang/en_us.json
0529422020c4a1669969bd3ee63aee063de4954d assets/bloodmagic/lang/en_us.json
34445195b9f2459475cde53454bc8e37d32865d7 assets/bloodmagic/models/block/accelerationrune.json
bcdbccc49d4509571be6988762ab87126275a4c8 assets/bloodmagic/models/block/airritualstone.json
adf6c0b1e25451609486dc8c8cfbd9cf0f8c67f4 assets/bloodmagic/models/block/alchemicalreactionchamber.json
@ -269,6 +269,10 @@ ccbcba6e4a6450bb67f91ba17754d668ba64c0ac assets/bloodmagic/models/item/ironfragm
413fa378c40dec89cb765a7d5c8bfc9cdef1d828 assets/bloodmagic/models/item/lavacrystal.json
588c5208e3f4ef941cd8375aeceeed44484d85d3 assets/bloodmagic/models/item/lavasigil.json
5a76914a87fc9b99079bb6afed1d4cfe3e4a532e assets/bloodmagic/models/item/lightritualstone.json
bd4db65caffbc68b312607bae4258fc1b67f60fd assets/bloodmagic/models/item/livingboots.json
c80cdacad2c4b6e995fe846c11cb2124a1813d79 assets/bloodmagic/models/item/livinghelmet.json
a64aa9003209d9eeca67cd7d3f1e2f05795c8f1a assets/bloodmagic/models/item/livingleggings.json
c0c9c72a8e31c9fa2d12eb870495407255431c8b assets/bloodmagic/models/item/livingplate.json
15d8178b626da912334774142d40d1012fb21fa0 assets/bloodmagic/models/item/magicianbloodorb.json
0a3566d3c86403f24c22977dd32ffaec727a9ad3 assets/bloodmagic/models/item/masterbloodorb.json
9e377ab2c131993f96ab6fb544bda4dbba0ab87e assets/bloodmagic/models/item/masterritualstone.json
@ -322,6 +326,7 @@ fe2b201007c974229509f6900c6eb8b03d158b0a assets/bloodmagic/models/item/soulsword
29009ca92dc30e1ec4ae1d454cd3f8726d8edc3c assets/bloodmagic/models/item/stonebrickpath.json
2dc28b0e2b7ae7bb0bcf8c8e74b9ba7c800446ff assets/bloodmagic/models/item/stonetilepath.json
26cb0aae63ea4f27efd5337c90c580ddd7481b99 assets/bloodmagic/models/item/sulfur.json
1e735651ebcc0087d38dfce304e5d722d219870e assets/bloodmagic/models/item/upgradetome.json
e8fe01c5cddc268538681889f3161472a8f1c8ad assets/bloodmagic/models/item/variants/growthsigil_activated.json
20c802279de4df496057795c2e891fa54a21376f assets/bloodmagic/models/item/variants/growthsigil_deactivated.json
2778ea3a62ce6dd718a557beee7b5329bb185ff9 assets/bloodmagic/models/item/variants/icesigil_activated.json

View file

@ -60,6 +60,7 @@
"block.bloodmagic.wornstonebrickpath": "Worn Stone Path",
"block.bloodmagic.wornstonetilepath": "Tiled Worn Stone Path",
"chat.bloodmagic.damageSource": "%s's soul became too weak",
"chat.bloodmagic.living_upgrade_level_increase": "%s has leveled up to %d",
"chat.bloodmagic.ritual.activate": "A rush of energy flows through the ritual!",
"chat.bloodmagic.ritual.notValid": "You feel that these runes are not configured correctly...",
"chat.bloodmagic.ritual.prevent": "The ritual is actively resisting you!",
@ -112,6 +113,10 @@
"item.bloodmagic.lavacrystal": "Lava Crystal",
"item.bloodmagic.lavasigil": "Lava Sigil",
"item.bloodmagic.life_essence_bucket": "Bucket of Life",
"item.bloodmagic.livingboots": "Living Boots",
"item.bloodmagic.livinghelmet": "Living Helmet",
"item.bloodmagic.livingleggings": "Living Leggings",
"item.bloodmagic.livingplate": "Living Chestplate",
"item.bloodmagic.magicianbloodorb": "Magician Blood Orb",
"item.bloodmagic.masterbloodorb": "Master Blood Orb",
"item.bloodmagic.miningsigil": "Sigil of the Fast Miner",
@ -150,6 +155,7 @@
"item.bloodmagic.soulsword": "Sentient Sword",
"item.bloodmagic.steadfastcrystal": "Steadfast Will Crystal",
"item.bloodmagic.sulfur": "Sulfur",
"item.bloodmagic.upgradetome": "Living Armour Upgrade Tome",
"item.bloodmagic.vengefulcrystal": "Vengeful Will Crystal",
"item.bloodmagic.voidsigil": "Void Sigil",
"item.bloodmagic.waterscribetool": "Inscription Tool: Water",
@ -170,6 +176,41 @@
"jei.bloodmagic.recipe.requiredtier": "Tier: %d",
"jei.bloodmagic.recipe.soulforge": "Hellfire Forge",
"jei.bloodmagic.recipe.soulsdrained": "Drained: %s Will",
"living_upgrade.bloodmagic.arrowShot": "Trick Shot",
"living_upgrade.bloodmagic.arrow_protect": "Pin Cushion",
"living_upgrade.bloodmagic.battleHunger": "Battle Hungry",
"living_upgrade.bloodmagic.crippledArm": "Crippled Arm",
"living_upgrade.bloodmagic.criticalStrike": "True Strike",
"living_upgrade.bloodmagic.digSlowdown": "Weakened Pick",
"living_upgrade.bloodmagic.digging": "Dwarven Might",
"living_upgrade.bloodmagic.disoriented": "Disoriented",
"living_upgrade.bloodmagic.elytra": "Elytra",
"living_upgrade.bloodmagic.experienced": "Experienced",
"living_upgrade.bloodmagic.fallProtect": "Soft Fall",
"living_upgrade.bloodmagic.fireResist": "Gift of Ignis",
"living_upgrade.bloodmagic.graveDigger": "Grave Digger",
"living_upgrade.bloodmagic.grimReaper": "Grim Reaper's Sprint",
"living_upgrade.bloodmagic.health": "Healthy",
"living_upgrade.bloodmagic.jump": "Strong Legs",
"living_upgrade.bloodmagic.knockback": "Body Builder",
"living_upgrade.bloodmagic.meleeDamage": "Fierce Strike",
"living_upgrade.bloodmagic.meleeDecrease": "Dulled Blade",
"living_upgrade.bloodmagic.nightSight": "Nocturnal Prowess",
"living_upgrade.bloodmagic.physicalProtect": "Tough",
"living_upgrade.bloodmagic.poisonResist": "Poison Resistance",
"living_upgrade.bloodmagic.quenched": "Quenched",
"living_upgrade.bloodmagic.repair": "Repairing",
"living_upgrade.bloodmagic.revealing": "Revealing",
"living_upgrade.bloodmagic.self_sacrifice": "Tough Palms",
"living_upgrade.bloodmagic.slippery": "Loose Traction",
"living_upgrade.bloodmagic.slowHeal": "Diseased",
"living_upgrade.bloodmagic.slowness": "Limp Leg",
"living_upgrade.bloodmagic.solarPowered": "Solar Powered",
"living_upgrade.bloodmagic.speed": "Quick Feet",
"living_upgrade.bloodmagic.sprint_attack": "Charging Strike",
"living_upgrade.bloodmagic.stepAssist": "Step Assist",
"living_upgrade.bloodmagic.stormTrooper": "Storm Trooper",
"living_upgrade.bloodmagic.thaumRunicShielding": "Runic Shielding",
"ritual.bloodmagic.altarBuilderRitual": "The Assembly of the High Altar",
"ritual.bloodmagic.altarBuilderRitual.info": "Builds an altar out of the components inside of the connected inventory.",
"ritual.bloodmagic.animalGrowthRitual": "Ritual of the Shepherd",
@ -203,8 +244,10 @@
"ritual.bloodmagic.crushingRitual.info": "Breaks blocks within its crushing range and places the items into the linked chest.",
"ritual.bloodmagic.crushingRitual.steadfast.info": "(Steadfast) Causes all blocks that are broken to be picked up with silk touch. Overrides Fortune where applicable.",
"ritual.bloodmagic.crushingRitual.vengeful.info": "(Vengeful) Compresses the inventory on successful operation. Currently only does one compression per operation.",
"ritual.bloodmagic.crystalHarvestRitual": "Crack of the Fractured Crystal",
"ritual.bloodmagic.crystalHarvestRitual.crystal.info": "(Crystal) All Demon Will crystal clusters have a single crystal broken off, spawning the crystal into the world. If there is only one crystal on the cluster, it will not break it.",
"ritual.bloodmagic.crystalHarvestRitual.info": "Breaks Demon Will crystal clusters within its range, dropping the results on top of the crystals.",
"ritual.bloodmagic.crystalSplitRitual": "Resonance of the Faceted Crystal",
"ritual.bloodmagic.crystalSplitRitual.info": "Splits apart a well-grown Raw crystal cluster into seperal aspected crystal clusters.",
"ritual.bloodmagic.ellipseRitual.chest.info": "(Chest) The location of the inventory that the ritual will grab blocks from to place in the world.",
"ritual.bloodmagic.ellipseRitual.info": "Creates a hollow spheroid around the ritual using the blocks in the attached chest.",
@ -226,6 +269,7 @@
"ritual.bloodmagic.fellingRitual.chest.info": "(Chest) The location of the inventory that the ritual will place the results into.",
"ritual.bloodmagic.fellingRitual.fellingRange.info": "(Cutting) The range that the ritual will search out logs and leaves in order to cut down.",
"ritual.bloodmagic.fellingRitual.info": "A standard tree-cutting machine, this ritual will cut down all trees and leaves within its area and collect the drops.",
"ritual.bloodmagic.forsakenSoulRitual": "Gathering of the Forsaken Souls",
"ritual.bloodmagic.forsakenSoulRitual.crystal.info": "(Crystal) Demon Crystals in this range receive an increase in growth speed when a mob is killed by the ritual.",
"ritual.bloodmagic.forsakenSoulRitual.damage.info": "(Damage) Mobs within this range will be slowly damaged, and when killed will grow the crystals.",
"ritual.bloodmagic.forsakenSoulRitual.info": "Damages mobs within its damage range and when the mob dies a demon crystal within its crystal range will be grown.",
@ -360,6 +404,10 @@
"tooltip.bloodmagic.extraInfo": "&9-Hold shift for more info-",
"tooltip.bloodmagic.holdShiftForInfo": "Press shift for extra info",
"tooltip.bloodmagic.inscriber.desc": "The writing is on the wall...",
"tooltip.bloodmagic.livingarmour.extraExtraInfo": "&9-Hold shift + M for progress info-",
"tooltip.bloodmagic.livingarmour.upgrade.level": "%s (Level %d)",
"tooltip.bloodmagic.livingarmour.upgrade.points": "Upgrade points: %s / %s",
"tooltip.bloodmagic.livingarmour.upgrade.progress": "%s (%d/100)",
"tooltip.bloodmagic.orb.desc": "Stores raw Life Essence",
"tooltip.bloodmagic.orb.owner": "Added by: %s",
"tooltip.bloodmagic.ritualReader.currentState": "Current mode: %s",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "bloodmagic:item/livingboots"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "bloodmagic:item/livinghelmet"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "bloodmagic:item/livingleggings"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "bloodmagic:item/livingplate"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/handheld",
"textures": {
"layer0": "bloodmagic:item/upgradetome"
}
}

View file

@ -49,6 +49,7 @@ import wayoftime.bloodmagic.common.data.recipe.BloodMagicRecipeProvider;
import wayoftime.bloodmagic.common.item.BloodMagicItems;
import wayoftime.bloodmagic.common.registries.BloodMagicEntityTypes;
import wayoftime.bloodmagic.common.registries.BloodMagicRecipeSerializers;
import wayoftime.bloodmagic.core.LivingArmorRegistrar;
import wayoftime.bloodmagic.core.recipe.IngredientBloodOrb;
import wayoftime.bloodmagic.core.registry.OrbRegistry;
import wayoftime.bloodmagic.impl.BloodMagicAPI;
@ -96,6 +97,7 @@ public class BloodMagic
BloodMagicItems.ITEMS.register(modBus);
// RegistrarBloodMagic.BLOOD_ORBS.createAndRegister(modBus, "bloodorbs");
BloodMagicItems.BLOOD_ORBS.createAndRegister(modBus, "bloodorbs");
LivingArmorRegistrar.UPGRADES.createAndRegister(modBus, "upgrades");
BloodMagicItems.BASICITEMS.register(modBus);
BloodMagicBlocks.BASICBLOCKS.register(modBus);
BloodMagicBlocks.DUNGEONBLOCKS.register(modBus);
@ -165,6 +167,7 @@ public class BloodMagic
BloodMagicCorePlugin.INSTANCE.register(BloodMagicAPI.INSTANCE);
RITUAL_MANAGER.discover();
ModRituals.initHarvestHandlers();
LivingArmorRegistrar.register();
}
public void registerTileEntityTypes(RegistryEvent.Register<TileEntityType<?>> event)

View file

@ -297,6 +297,52 @@ public class GeneratorLanguage extends LanguageProvider
add("tooltip.bloodmagic.ritualReader.desc.information", "Right click on an active Master Ritual Stone to gather basic information about the ritual.");
add("tooltip.bloodmagic.ritualReader.desc.set_will_types", "Set the types of demon will that the ritual will consume from the aura by right clicking on the MRS with the same types of crystals on your hotbar.");
// Living Armour - the 'u' is important, TehNut!
add("living_upgrade.bloodmagic.arrow_protect", "Pin Cushion");
add("living_upgrade.bloodmagic.speed", "Quick Feet");
add("living_upgrade.bloodmagic.digging", "Dwarven Might");
add("living_upgrade.bloodmagic.poisonResist", "Poison Resistance");
add("living_upgrade.bloodmagic.fireResist", "Gift of Ignis");
add("living_upgrade.bloodmagic.self_sacrifice", "Tough Palms");
add("living_upgrade.bloodmagic.knockback", "Body Builder");
add("living_upgrade.bloodmagic.physicalProtect", "Tough");
add("living_upgrade.bloodmagic.health", "Healthy");
add("living_upgrade.bloodmagic.meleeDamage", "Fierce Strike");
add("living_upgrade.bloodmagic.arrowShot", "Trick Shot");
add("living_upgrade.bloodmagic.stepAssist", "Step Assist");
add("living_upgrade.bloodmagic.grimReaper", "Grim Reaper's Sprint");
add("living_upgrade.bloodmagic.solarPowered", "Solar Powered");
add("living_upgrade.bloodmagic.thaumRunicShielding", "Runic Shielding");
add("living_upgrade.bloodmagic.revealing", "Revealing");
add("living_upgrade.bloodmagic.experienced", "Experienced");
add("living_upgrade.bloodmagic.jump", "Strong Legs");
add("living_upgrade.bloodmagic.fallProtect", "Soft Fall");
add("living_upgrade.bloodmagic.graveDigger", "Grave Digger");
add("living_upgrade.bloodmagic.sprint_attack", "Charging Strike");
add("living_upgrade.bloodmagic.criticalStrike", "True Strike");
add("living_upgrade.bloodmagic.elytra", "Elytra");
add("living_upgrade.bloodmagic.nightSight", "Nocturnal Prowess");
add("living_upgrade.bloodmagic.repair", "Repairing");
add("living_upgrade.bloodmagic.slowness", "Limp Leg");
add("living_upgrade.bloodmagic.crippledArm", "Crippled Arm");
add("living_upgrade.bloodmagic.slippery", "Loose Traction");
add("living_upgrade.bloodmagic.battleHunger", "Battle Hungry");
add("living_upgrade.bloodmagic.quenched", "Quenched");
add("living_upgrade.bloodmagic.meleeDecrease", "Dulled Blade");
add("living_upgrade.bloodmagic.digSlowdown", "Weakened Pick");
add("living_upgrade.bloodmagic.stormTrooper", "Storm Trooper");
add("living_upgrade.bloodmagic.slowHeal", "Diseased");
add("living_upgrade.bloodmagic.disoriented", "Disoriented");
add("tooltip.bloodmagic.livingarmour.upgrade.level", "%s (Level %d)");
add("tooltip.bloodmagic.livingarmour.upgrade.progress", "%s (%d/100)");
add("tooltip.bloodmagic.livingarmour.upgrade.points", "Upgrade points: %s / %s");
add("tooltip.bloodmagic.livingarmour.extraExtraInfo", "&9-Hold shift + M for progress info-");
add("chat.bloodmagic.living_upgrade_level_increase", "%s has leveled up to %d");
// Guide
add("guide.bloodmagic.name", "Sanguine Scientiem");
add("guide.bloodmagic.landing_text", "\"It is my dear hope that by holding this tome in your hands, I may impart the knowledge of the lost art that is Blood Magic\"$(br)$(o)- Magus Arcana$()");
@ -464,6 +510,13 @@ public class GeneratorLanguage extends LanguageProvider
addItem(BloodMagicItems.EXPERIENCE_TOME, "Tome of Peritia");
addItem(BloodMagicItems.LIVING_HELMET, "Living Helmet");
addItem(BloodMagicItems.LIVING_PLATE, "Living Chestplate");
addItem(BloodMagicItems.LIVING_LEGGINGS, "Living Leggings");
addItem(BloodMagicItems.LIVING_BOOTS, "Living Boots");
addItem(BloodMagicItems.LIVING_TOME, "Living Armour Upgrade Tome");
// Alchemy Items
addItem(BloodMagicItems.PLANT_OIL, "Plant Oil");

View file

@ -0,0 +1,59 @@
package wayoftime.bloodmagic.common.item;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ArmorMaterial;
import net.minecraft.item.IArmorMaterial;
import net.minecraft.item.crafting.Ingredient;
public class ArmorMaterialLiving implements IArmorMaterial
{
public static final IArmorMaterial INSTANCE = new ArmorMaterialLiving();
@Override
public int getDurability(EquipmentSlotType slot)
{
return ArmorMaterial.IRON.getDurability(slot);
}
@Override
public int getDamageReductionAmount(EquipmentSlotType slot)
{
return ArmorMaterial.IRON.getDamageReductionAmount(slot);
}
@Override
public int getEnchantability()
{
return ArmorMaterial.IRON.getEnchantability();
}
@Override
public net.minecraft.util.SoundEvent getSoundEvent()
{
return ArmorMaterial.IRON.getSoundEvent();
}
@Override
public Ingredient getRepairMaterial()
{
return ArmorMaterial.IRON.getRepairMaterial();
}
@Override
public String getName()
{
return "livingarmour";
}
@Override
public float getToughness()
{
return ArmorMaterial.IRON.getToughness();
}
@Override
public float getKnockbackResistance()
{
return ArmorMaterial.IRON.getKnockbackResistance();
}
}

View file

@ -1,5 +1,6 @@
package wayoftime.bloodmagic.common.item;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
@ -7,6 +8,7 @@ import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.api.compat.EnumDemonWillType;
import wayoftime.bloodmagic.common.block.BloodMagicBlocks;
import wayoftime.bloodmagic.common.item.arc.ItemARCToolBase;
import wayoftime.bloodmagic.common.item.block.ItemBlockAlchemyTable;
@ -32,7 +34,6 @@ import wayoftime.bloodmagic.common.registration.impl.BloodOrbDeferredRegister;
import wayoftime.bloodmagic.common.registration.impl.BloodOrbRegistryObject;
import wayoftime.bloodmagic.ritual.EnumRuneType;
import wayoftime.bloodmagic.structures.ItemDungeonTester;
import wayoftime.bloodmagic.api.compat.EnumDemonWillType;
public class BloodMagicItems
{
@ -129,6 +130,13 @@ public class BloodMagicItems
public static final RegistryObject<Item> WEAK_BLOOD_SHARD = BASICITEMS.register("weakbloodshard", () -> new ItemBase());
public static final RegistryObject<Item> EXPERIENCE_TOME = BASICITEMS.register("experiencebook", () -> new ItemExperienceBook());
public static final RegistryObject<Item> LIVING_HELMET = BASICITEMS.register("livinghelmet", () -> new ItemLivingArmor(EquipmentSlotType.HEAD));
public static final RegistryObject<Item> LIVING_PLATE = BASICITEMS.register("livingplate", () -> new ItemLivingArmor(EquipmentSlotType.CHEST));
public static final RegistryObject<Item> LIVING_LEGGINGS = BASICITEMS.register("livingleggings", () -> new ItemLivingArmor(EquipmentSlotType.LEGS));
public static final RegistryObject<Item> LIVING_BOOTS = BASICITEMS.register("livingboots", () -> new ItemLivingArmor(EquipmentSlotType.FEET));
public static final RegistryObject<Item> LIVING_TOME = BASICITEMS.register("upgradetome", () -> new ItemLivingTome());
// Ritual stuffs
public static final RegistryObject<Item> WEAK_ACTIVATION_CRYSTAL = BASICITEMS.register("activationcrystalweak", () -> new ItemActivationCrystal(ItemActivationCrystal.CrystalType.WEAK));
public static final RegistryObject<Item> AWAKENED_ACTIVATION_CRYSTAL = BASICITEMS.register("activationcrystalawakened", () -> new ItemActivationCrystal(ItemActivationCrystal.CrystalType.AWAKENED));

View file

@ -0,0 +1,20 @@
package wayoftime.bloodmagic.common.item;
import com.google.common.collect.Multimap;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
public interface ExpandedArmor
{
// Multimap<String, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack);
void damageArmor(LivingEntity livingEntity, ItemStack stack, DamageSource source, float damage, EquipmentSlotType slot);
Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack);
}

View file

@ -0,0 +1,163 @@
package wayoftime.bloodmagic.common.item;
import java.util.List;
import java.util.UUID;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.NonNullList;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.core.living.ILivingContainer;
import wayoftime.bloodmagic.core.living.LivingStats;
public class ItemLivingArmor extends ArmorItem implements ILivingContainer, ExpandedArmor
{
private static final int MAX_ABSORPTION = 100000;
public ItemLivingArmor(EquipmentSlotType slot)
{
super(ArmorMaterialLiving.INSTANCE, slot, new Item.Properties().maxStackSize(1).group(BloodMagic.TAB));
}
@Override
public String getArmorTexture(ItemStack stack, Entity entity, EquipmentSlotType slot, String type)
{
if (this == BloodMagicItems.LIVING_PLATE.get() || this == BloodMagicItems.LIVING_HELMET.get() || this == BloodMagicItems.LIVING_BOOTS.get())
{
return "bloodmagic:models/armor/livingarmour_layer_1.png";
}
if (this == BloodMagicItems.LIVING_LEGGINGS.get())
{
return "bloodmagic:models/armor/livingarmour_layer_2.png";
} else
{
return null;
}
}
@Override
public Multimap<Attribute, AttributeModifier> getAttributeModifiers(EquipmentSlotType slot, ItemStack stack)
{
// Multimap<Attribute, AttributeModifier> modifiers = super.getAttributeModifiers(slot, stack);
Multimap<Attribute, AttributeModifier> modifiers = HashMultimap.create();
modifiers.putAll(super.getAttributeModifiers(slot, stack));
if (slot != EquipmentSlotType.CHEST)
return modifiers;
LivingStats stats = getLivingStats(stack);
if (stats == null)
return modifiers;
stats.getUpgrades().forEach((k, v) -> {
if (k.getAttributeProvider() != null)
k.getAttributeProvider().handleAttributes(stats, modifiers, UUID.nameUUIDFromBytes(k.getKey().toString().getBytes()), k, k.getLevel(v.intValue()));
});
return modifiers;
}
// @Override
// public ArmorProperties getProperties(EntityLivingBase player, @Nonnull ItemStack armor, DamageSource source, double damage, int slot) {
// if (source == DamageSource.DROWN || source == DamageSource.OUT_OF_WORLD)
// return new ArmorProperties(-1, 0D, 0);
//
// double armorReduction;
// double damageAmount = 0.25;
// double armorPenetrationReduction = 0;
//
// if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_FEET || armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_HEAD)
// damageAmount = 3d / 20d * 0.6;
// else if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_LEGS)
// damageAmount = 6d / 20d * 0.6;
// else if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST)
// damageAmount = 0.64;
//
// if (armor.getItem() == RegistrarBloodMagicItems.LIVING_ARMOR_CHEST) {
// armorReduction = 0.24 / 0.64; // This values puts it at iron level
//
// if (!LivingUtil.hasFullSet((EntityPlayer) player))
// return new ArmorProperties(-1, damageAmount * armorReduction, MAX_ABSORPTION);
//
// LivingStats stats = getLivingStats(armor);
// double protection = 1.0D;
// if (stats != null)
// for (Map.Entry<LivingUpgrade, Integer> entry : stats.getUpgrades().entrySet())
// if (entry.getKey().getArmorProvider() != null)
// protection *= 1 - entry.getKey().getArmorProvider().getProtection((EntityPlayer) player, stats, source, entry.getKey().getLevel(entry.getValue()));
//
// armorReduction += (1 - protection) * (1 - armorReduction);
// damageAmount *= armorReduction;
// return new ArmorProperties(-1, source.isUnblockable() ? 1 - protection : damageAmount, MAX_ABSORPTION);
// } else if (source.isUnblockable())
// return new ArmorProperties(-1, damageAmount * armorPenetrationReduction, MAX_ABSORPTION);
//
// return new ArmorProperties(-1, damageAmount, MAX_ABSORPTION);
// }
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items)
{
if (!isInGroup(group))
return;
ItemStack stack = new ItemStack(this);
if (slot == EquipmentSlotType.CHEST)
updateLivingStats(stack, new LivingStats());
items.add(stack);
}
// @Override
// public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items)
// {
// if (this.isInGroup(group))
// {
// for (EnumDemonWillType type : EnumDemonWillType.values())
// {
// ItemStack stack = new ItemStack(this);
// this.setCurrentType(type, stack);
// this.setWill(type, stack, maxWill);
// items.add(stack);
// }
// }
// }
@Override
public void damageArmor(LivingEntity livingEntity, ItemStack stack, DamageSource source, float damage, EquipmentSlotType slot)
{
if (slot == EquipmentSlotType.CHEST && damage > getMaxDamage() - stack.getDamage())
{
// livingEntity.attackEntityFrom(source, amount)
// }
livingEntity.attackEntityFrom(DamageSource.MAGIC, 2.0F);
return;
}
// stack.damage((int) damage, livingEntity, entity -> {});
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag)
{
ILivingContainer.appendLivingTooltip(getLivingStats(stack), tooltip, true);
}
}

View file

@ -0,0 +1,101 @@
package wayoftime.bloodmagic.common.item;
import java.util.List;
import java.util.Map.Entry;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.core.LivingArmorRegistrar;
import wayoftime.bloodmagic.core.living.ILivingContainer;
import wayoftime.bloodmagic.core.living.LivingStats;
import wayoftime.bloodmagic.core.living.LivingUpgrade;
import wayoftime.bloodmagic.core.living.LivingUtil;
public class ItemLivingTome extends Item implements ILivingContainer
{
public ItemLivingTome()
{
super(new Item.Properties().maxStackSize(1).group(BloodMagic.TAB));
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand)
{
ItemStack held = player.getHeldItem(hand);
LivingStats armorStats = LivingStats.fromPlayer(player, true);
if (armorStats == null)
return ActionResult.resultPass(held);
LivingStats tomeStats = getLivingStats(held);
if (tomeStats == null)
return ActionResult.resultPass(held);
boolean[] flag = new boolean[] { false };
tomeStats.getUpgrades().forEach((k, v) -> {
if (armorStats.getLevel(k.getKey()) >= tomeStats.getLevel(k.getKey()))
return;
LivingUtil.applyNewExperience(player, k, v); // FIXME set levels directly, don't add experience
flag[0] = true;
});
// LivingStats.toPlayer(player, armorStats);
if (flag[0])
{
held.shrink(1);
return ActionResult.resultSuccess(held);
} else
return ActionResult.resultPass(held);
}
@Override
public void fillItemGroup(ItemGroup group, NonNullList<ItemStack> items)
{
if (!isInGroup(group))
return;
for (Entry<ResourceLocation, LivingUpgrade> entry : LivingArmorRegistrar.UPGRADE_MAP.entrySet())
{
LivingUpgrade upgrade = entry.getValue();
int exp = 0;
while ((exp = upgrade.getNextRequirement(exp)) != 0)
{
ItemStack tome = new ItemStack(this);
updateLivingStats(tome, new LivingStats().setMaxPoints(upgrade.getLevelCost(exp)).addExperience(upgrade.getKey(), exp));
items.add(tome);
}
}
// LivingArmorRegistrar.UPGRADE_MAP.forEach(upgrade -> {
// int exp = 0;
//
// while ((exp = upgrade.getNextRequirement(exp)) != 0)
// {
// ItemStack tome = new ItemStack(this);
// updateLivingStats(tome, new LivingStats().setMaxPoints(upgrade.getLevelCost(exp)).addExperience(upgrade.getKey(), exp));
// display.add(tome);
// }
// });
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag)
{
ILivingContainer.appendLivingTooltip(getLivingStats(stack), tooltip, false);
}
}

View file

@ -0,0 +1,28 @@
package wayoftime.bloodmagic.common.item;
import java.util.List;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.core.living.ILivingContainer;
public class ItemLivingTrainer extends Item implements ILivingContainer
{
public ItemLivingTrainer()
{
super(new Item.Properties().maxStackSize(1).group(BloodMagic.TAB));
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag)
{
ILivingContainer.appendLivingTooltip(getLivingStats(stack), tooltip, false);
}
}

View file

@ -0,0 +1,25 @@
package wayoftime.bloodmagic.common.registration.impl;
import java.util.function.Supplier;
import wayoftime.bloodmagic.common.registration.WrappedDeferredRegister;
import wayoftime.bloodmagic.core.living.LivingUpgrade;
public class LivingUpgradeDeferredRegister extends WrappedDeferredRegister<LivingUpgrade>
{
public LivingUpgradeDeferredRegister(String modid)
{
super(modid, LivingUpgrade.class);
}
// public BloodOrbRegistryObject<BloodOrb> register(String name, ResourceLocation rl, int tier, int capacity,
// int fillRate)
// {
// return register(name, () -> new BloodOrb(rl, tier, capacity, fillRate));
// }
public <ORB extends LivingUpgrade> LivingUpgradeRegistryObject<ORB> register(String name, Supplier<? extends ORB> sup)
{
return register(name, sup, LivingUpgradeRegistryObject::new);
}
}

View file

@ -0,0 +1,13 @@
package wayoftime.bloodmagic.common.registration.impl;
import net.minecraftforge.fml.RegistryObject;
import wayoftime.bloodmagic.common.registration.WrappedRegistryObject;
import wayoftime.bloodmagic.core.living.LivingUpgrade;
public class LivingUpgradeRegistryObject<UP extends LivingUpgrade> extends WrappedRegistryObject<UP>
{
public LivingUpgradeRegistryObject(RegistryObject<UP> registryObject)
{
super(registryObject);
}
}

View file

@ -0,0 +1,182 @@
package wayoftime.bloodmagic.core;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.Attributes;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.BloodMagic;
import wayoftime.bloodmagic.common.registration.impl.LivingUpgradeDeferredRegister;
import wayoftime.bloodmagic.common.registration.impl.LivingUpgradeRegistryObject;
import wayoftime.bloodmagic.core.living.LivingUpgrade;
import wayoftime.bloodmagic.gson.Serializers;
public class LivingArmorRegistrar
{
public static final LivingUpgradeDeferredRegister UPGRADES = new LivingUpgradeDeferredRegister(BloodMagic.MODID);
public static final Map<ResourceLocation, LivingUpgrade> UPGRADE_MAP = new HashMap<>();
// public static final DefaultedRegistry<LivingUpgrade> UPGRADES = (DefaultedRegistry<LivingUpgrade>) createRegistry("livingarmor:upgrades", LivingUpgrade.DUMMY.getKey().toString(), () -> LivingUpgrade.DUMMY);
// private static final Map<String, ResourceLocation> DEFINITIONS = ((Supplier<Map<String, ResourceLocation>>) () -> {
// Map<String, ResourceLocation> def = new HashMap<>();
// def.put("arrow_protect", Paths.get(MinecraftForge.getInstance().getConfigDirectory().getAbsolutePath(), "livingarmor", "arrow_protect.json"));
// def.put("arrow_shot", Paths.get(FabricLoader.getInstance().getConfigDirectory().getAbsolutePath(), "livingarmor", "arrow_shot.json"));
// def.put("critical_strike", Paths.get(FabricLoader.getInstance().getConfigDirectory().getAbsolutePath(), "livingarmor", "critical_strike.json"));
// def.put("jump", Paths.get(FabricLoader.getInstance().getConfigDirectory().getAbsolutePath(), "livingarmor", "jump.json"));
// return def;
// }).get();
private static final Map<String, ResourceLocation> DEFINITIONS = ((Supplier<Map<String, ResourceLocation>>) () -> {
Map<String, ResourceLocation> def = new HashMap<>();
def.put("arrow_protect", BloodMagic.rl("arrow_protect"));
def.put("arrow_shot", BloodMagic.rl("arrow_shot"));
def.put("critical_strike", BloodMagic.rl("critical_strike"));
def.put("jump", BloodMagic.rl("jump"));
def.put("health", BloodMagic.rl("health"));
def.put("experience", BloodMagic.rl("experienced"));
def.put("sprint_attack", BloodMagic.rl("sprint_attack"));
def.put("self_sacrifice", BloodMagic.rl("self_sacrifice"));
def.put("speed", BloodMagic.rl("speed"));
return def;
}).get();
// private static final Map<String, Path> DEFINITIONS =
// ResourceUtil.gatherResources("/data", "living_armor", p ->
// FilenameUtils.getExtension(p.toFile().getName()).equals("json"))
// .stream()
// .collect(Collectors.toMap(key -> FilenameUtils.getBaseName(key.toFile().getName()), value -> value));
private static final Gson GSON = new GsonBuilder().serializeNulls().create();
// public static final ItemLivingArmor LIVING_HELMET = new ItemLivingArmor(EquipmentSlotType.HEAD);
// public static final ItemLivingArmor LIVING_CHESTPLATE = new ItemLivingArmor(EquipmentSlotType.CHEST);
// public static final ItemLivingArmor LIVING_LEGGINGS = new ItemLivingArmor(EquipmentSlotType.LEGS);
// public static final ItemLivingArmor LIVING_BOOTS = new ItemLivingArmor(EquipmentSlotType.FEET);
// public static final ItemLivingTrainer TRAINER = new ItemLivingTrainer();
// public static final ItemLivingTome TOME = new ItemLivingTome();
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_ARROW_PROTECT = UPGRADES.register("arrow_protect", () -> parseDefinition("arrow_protect").withArmorProvider((player, stats, source, upgrade, level) -> {
if (source.isProjectile())
{
return upgrade.getBonusValue("protection", level).doubleValue();
}
return 0;
}));
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_HEALTH = UPGRADES.register("health", () -> parseDefinition("health").withAttributeProvider((stats, attributeMap, uuid, upgrade, level) -> {
attributeMap.put(Attributes.MAX_HEALTH, new AttributeModifier(uuid, "Health Modifier", upgrade.getBonusValue("hp", level).intValue(), AttributeModifier.Operation.ADDITION));
}));
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_EXPERIENCE = UPGRADES.register("experienced", () -> parseDefinition("experienced"));
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_SPRINT_ATTACK = UPGRADES.register("sprint_attack", () -> parseDefinition("sprint_attack").withDamageProvider((player, weapon, damage, stats, attackedEntity, upgrade, level) -> {
if (player.isSprinting())
{
return damage * upgrade.getBonusValue("damage_boost", level).doubleValue();
}
return 0;
}));
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_SELF_SACRIFICE = UPGRADES.register("self_sacrifice", () -> parseDefinition("self_sacrifice"));
public static final LivingUpgradeRegistryObject<LivingUpgrade> UPGRADE_SPEED = UPGRADES.register("speed", () -> parseDefinition("speed"));
// public static final LivingUpgrade UPGRADE_ARROW_PROTECT = parseDefinition("arrow_protect").withArmorProvider((player, stats, source, upgrade, level) -> {
// if (source.isProjectile())
// {
// return upgrade.getBonusValue("protection", level).doubleValue();
// }
// return 0;
// });
// public static final LivingUpgrade UPGRADE_ARROW_SHOT = parseDefinition("arrow_shot");
// public static final LivingUpgrade UPGRADE_CRITICAL_STRIKE = parseDefinition("critical_strike").withAttributeProvider((stats, attributeMap, uuid, upgrade, level) -> {
// attributeMap.put(Attributes.ATTACK_DAMAGE, new AttributeModifier(uuid, "Weapon modifier", upgrade.getBonusValue("damage_boost", level).doubleValue(), AttributeModifier.Operation.ADDITION));
//// attributeMap.put(EntityAttributes.ATTACK_DAMAGE.getId(), AttributeModifiers.create(upgrade, "damage_boost", upgrade.getBonusValue("damage_boost", level).doubleValue(), EntityAttributeModifier.Operation.ADDITION));
//// attributeMap.put(EntityAttributes.ATTACK_DAMAGE.getId(), AttributeModifiers.create(upgrade, "damage_boost", level, EntityAttributeModifier.Operation.ADDITION));
// });
// public static final LivingUpgrade UPGRADE_JUMP = parseDefinition("jump");
public static void register()
{
registerUpgrade(UPGRADE_ARROW_PROTECT.get());
registerUpgrade(UPGRADE_HEALTH.get());
registerUpgrade(UPGRADE_EXPERIENCE.get());
registerUpgrade(UPGRADE_SPRINT_ATTACK.get());
registerUpgrade(UPGRADE_SELF_SACRIFICE.get());
registerUpgrade(UPGRADE_SPEED.get());
// Registry.register(UPGRADES, UPGRADE_ARROW_PROTECT.getKey(), UPGRADE_ARROW_PROTECT);
// Registry.register(UPGRADES, UPGRADE_ARROW_SHOT.getKey(), UPGRADE_ARROW_SHOT);
// Registry.register(UPGRADES, UPGRADE_CRITICAL_STRIKE.getKey(), UPGRADE_CRITICAL_STRIKE);
// Registry.register(UPGRADES, UPGRADE_JUMP.getKey(), UPGRADE_JUMP);
// Registry.register(Registry.ITEM, new ResourceLocation("livingarmor", "living_helmet"), LIVING_HELMET);
// Registry.register(Registry.ITEM, new Identifier("livingarmor", "living_chestplate"), LIVING_CHESTPLATE);
// Registry.register(Registry.ITEM, new Identifier("livingarmor", "living_leggings"), LIVING_LEGGINGS);
// Registry.register(Registry.ITEM, new Identifier("livingarmor", "living_boots"), LIVING_BOOTS);
// Registry.register(Registry.ITEM, new Identifier("livingarmor", "trainer"), TRAINER);
// Registry.register(Registry.ITEM, new Identifier("livingarmor", "tome"), TOME);
}
public static void registerUpgrade(LivingUpgrade upgrade)
{
UPGRADE_MAP.put(upgrade.getKey(), upgrade);
}
public static LivingUpgrade parseDefinition(String fileName)
{
ResourceLocation path = DEFINITIONS.get(fileName);
if (path == null)
return LivingUpgrade.DUMMY;
try
{
URL schematicURL = LivingUpgrade.class.getResource(resLocToResourcePath(path));
System.out.println("Attempting to load Living Armour Upgrade: " + schematicURL + ", path: " + resLocToResourcePath(path));
return Serializers.GSON.fromJson(Resources.toString(schematicURL, Charsets.UTF_8), LivingUpgrade.class);
// return GSON.fromJson(IOUtils.toString(path.toUri(), StandardCharsets.UTF_8), LivingUpgrade.class);
} catch (Exception e)
{
e.printStackTrace();
return LivingUpgrade.DUMMY;
}
// Path path = DEFINITIONS.get(fileName);
// if (path == null)
// return LivingUpgrade.DUMMY;
//
// try
// {
// return GSON.fromJson(IOUtils.toString(path.toUri(), StandardCharsets.UTF_8), LivingUpgrade.class);
// } catch (Exception e)
// {
// e.printStackTrace();
// return LivingUpgrade.DUMMY;
// }
}
public static String resLocToResourcePath(ResourceLocation resourceLocation)
{
return "/data/" + resourceLocation.getNamespace() + "/living_armor/" + resourceLocation.getPath() + ".json";
}
// private static <T> Registry<T> createRegistry(String registryId, String defaultId, Supplier<T> defaultProvider)
// {
// try
// {
// Method _createRegistry = Registry.class.getDeclaredMethod("create", String.class, String.class, Supplier.class); // FIXME
// // yarn
// // name
// _createRegistry.setAccessible(true);
// return (Registry<T>) _createRegistry.invoke(null, registryId, defaultId, defaultProvider);
// } catch (Exception e)
// {
// e.printStackTrace();
// MutableRegistry<T> registry = new DefaultedRegistry(defaultId, null, null);
// registry.add(new ResourceLocation(defaultId), defaultProvider.get());
// return registry;
// }
// }
}

View file

@ -0,0 +1,60 @@
package wayoftime.bloodmagic.core.living;
import java.util.List;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public interface ILivingContainer
{
default LivingStats getLivingStats(ItemStack stack)
{
if (!stack.hasTag() || !stack.getTag().contains("livingStats"))
return null;
return LivingStats.fromNBT(stack.getTag().getCompound("livingStats"));
}
default void updateLivingStats(ItemStack stack, LivingStats stats)
{
if (stats == null)
{
if (stack.hasTag())
stack.getTag().remove("livingStats");
return;
}
if (!stack.hasTag())
stack.setTag(new CompoundNBT());
stack.getTag().put("livingStats", stats.serialize());
}
@OnlyIn(Dist.CLIENT)
static void appendLivingTooltip(LivingStats stats, List<ITextComponent> tooltip, boolean trainable)
{
if (stats != null)
{
if (trainable)
tooltip.add(new TranslationTextComponent("tooltip.bloodmagic.livingarmour.upgrade.points", stats.getUsedPoints(), stats.getMaxPoints()).mergeStyle(TextFormatting.GOLD));
stats.getUpgrades().forEach((k, v) -> {
if (k.getLevel(v.intValue()) <= 0)
return;
boolean sneaking = Screen.hasShiftDown();
// if (!InputUtil.isKeyPressed(MinecraftClient.getInstance().getWindow().getHandle(), 340) || k.getNextRequirement(v) == 0)
if (!sneaking || k.getNextRequirement(v.intValue()) == 0)
tooltip.add(new TranslationTextComponent("%s %s", new TranslationTextComponent(k.getTranslationKey()), new TranslationTextComponent("enchantment.level." + k.getLevel(v.intValue()))));
else
tooltip.add(new TranslationTextComponent("%s %s", new TranslationTextComponent(k.getTranslationKey()), (": " + v.intValue() + "/" + k.getNextRequirement(v.intValue()))));
});
}
}
}

View file

@ -0,0 +1,150 @@
package wayoftime.bloodmagic.core.living;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.core.LivingArmorRegistrar;
public class LivingStats
{
public static final int DEFAULT_UPGRADE_POINTS = 100;
private final Map<LivingUpgrade, Double> upgrades;
private int maxPoints = DEFAULT_UPGRADE_POINTS;
public LivingStats(Map<LivingUpgrade, Double> upgrades)
{
this.upgrades = upgrades;
}
public LivingStats()
{
this(Maps.newHashMap());
}
public Map<LivingUpgrade, Double> getUpgrades()
{
return ImmutableMap.copyOf(upgrades);
}
public LivingStats addExperience(ResourceLocation key, double experience)
{
// LivingUpgrade upgrade = LivingArmorRegistrar.UPGRADES.getOrDefault(key);
LivingUpgrade upgrade = LivingArmorRegistrar.UPGRADE_MAP.getOrDefault(key, LivingUpgrade.DUMMY);
double current = upgrades.getOrDefault(upgrade, 0d);
System.out.println("Upgrade: " + upgrade);
if (upgrade.getNextRequirement((int) current) == 0)
return this;
upgrades.put(upgrade, current + experience);
return this;
}
public int getLevel(ResourceLocation key)
{
LivingUpgrade upgrade = LivingArmorRegistrar.UPGRADE_MAP.getOrDefault(key, LivingUpgrade.DUMMY);
// LivingUpgrade upgrade = LivingArmorRegistrar.UPGRADES.getOrDefault(key);
return upgrade.getLevel(upgrades.getOrDefault(upgrade, 0d).intValue());
}
public int getUsedPoints()
{
int total = 0;
for (Map.Entry<LivingUpgrade, Double> applied : upgrades.entrySet())
{
double experience = applied.getValue();
int level = applied.getKey().getLevel((int) experience);
int cost = applied.getKey().getLevelCost(level);
total += cost;
}
return total;
}
public int getMaxPoints()
{
return maxPoints;
}
public LivingStats setMaxPoints(int maxPoints)
{
this.maxPoints = maxPoints;
return this;
}
public CompoundNBT serialize()
{
CompoundNBT compound = new CompoundNBT();
ListNBT statList = new ListNBT();
upgrades.forEach((k, v) -> {
CompoundNBT upgrade = new CompoundNBT();
upgrade.putString("key", k.getKey().toString());
upgrade.putDouble("exp", v);
statList.add(upgrade);
});
compound.put("upgrades", statList);
compound.putInt("maxPoints", maxPoints);
return compound;
}
public void deserialize(CompoundNBT nbt)
{
ListNBT statList = nbt.getList("upgrades", 10);
statList.forEach(tag -> {
if (!(tag instanceof CompoundNBT))
return;
LivingUpgrade upgrade = LivingArmorRegistrar.UPGRADE_MAP.getOrDefault(new ResourceLocation(((CompoundNBT) tag).getString("key")), LivingUpgrade.DUMMY);
if (upgrade == LivingUpgrade.DUMMY)
return;
double experience = ((CompoundNBT) tag).getDouble("exp");
upgrades.put(upgrade, experience);
});
maxPoints = nbt.getInt("maxPoints");
}
public static LivingStats fromNBT(CompoundNBT statTag)
{
LivingStats stats = new LivingStats();
stats.deserialize(statTag);
return stats;
}
public static LivingStats fromPlayer(PlayerEntity player)
{
return fromPlayer(player, false);
}
public static LivingStats fromPlayer(PlayerEntity player, boolean createNew)
{
if (!LivingUtil.hasFullSet(player))
return null;
ItemStack chest = player.getItemStackFromSlot(EquipmentSlotType.CHEST);
LivingStats stats = ((ILivingContainer) chest.getItem()).getLivingStats(chest);
return stats == null && createNew ? new LivingStats() : stats;
}
public static void toPlayer(PlayerEntity player, LivingStats stats)
{
if (!LivingUtil.hasFullSet(player))
return;
ItemStack chest = player.getItemStackFromSlot(EquipmentSlotType.CHEST);
((ILivingContainer) chest.getItem()).updateLivingStats(chest, stats);
}
}

View file

@ -0,0 +1,267 @@
package wayoftime.bloodmagic.core.living;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.function.Consumer;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Util;
import net.minecraftforge.registries.ForgeRegistryEntry;
@JsonAdapter(LivingUpgrade.Deserializer.class)
public class LivingUpgrade extends ForgeRegistryEntry<LivingUpgrade>
{
public static final LivingUpgrade DUMMY = new LivingUpgrade(new ResourceLocation("dummy"), levels -> levels.add(new Level(0, 0)));
private final ResourceLocation key;
private final Set<ResourceLocation> incompatible;
private final TreeMap<Integer, Integer> experienceToLevel;
private final Map<Integer, Integer> levelToCost;
private final Map<String, Bonus> bonuses;
private boolean isNegative;
private String translationKey = null;
private IAttributeProvider attributeProvider;
private IArmorProvider armorProvider;
private IDamageProvider damageProvider;
public LivingUpgrade(ResourceLocation key, Consumer<List<Level>> experienceMapper)
{
this.key = key;
this.incompatible = Sets.newHashSet();
this.experienceToLevel = Maps.newTreeMap();
this.levelToCost = Maps.newHashMap();
this.bonuses = Maps.newHashMap();
List<Level> levels = Lists.newArrayList();
experienceMapper.accept(levels);
for (int i = 0; i < levels.size(); i++)
{
Level level = levels.get(i);
experienceToLevel.put(level.experienceNeeded, i + 1);
levelToCost.put(i + 1, level.upgradeCost);
}
}
public LivingUpgrade withBonusSet(String id, Consumer<List<Number>> modifiers)
{
// List<Number> values = DefaultedList.of();
List<Number> values = new ArrayList<Number>();
modifiers.accept(values);
if (values.size() != levelToCost.size())
throw new RuntimeException("Bonus size and level size must be the same.");
bonuses.put(id, new Bonus(id, values));
return this;
}
public Number getBonusValue(String id, int level)
{
List<Number> modifiers = bonuses.getOrDefault(id, Bonus.DEFAULT).modifiers;
if (modifiers.isEmpty() || level == 0)
return 0;
return modifiers.get(level - 1);
}
public LivingUpgrade withAttributeProvider(IAttributeProvider attributeProvider)
{
this.attributeProvider = attributeProvider;
return this;
}
public IAttributeProvider getAttributeProvider()
{
return attributeProvider;
}
public LivingUpgrade withArmorProvider(IArmorProvider armorProvider)
{
this.armorProvider = armorProvider;
return this;
}
public IArmorProvider getArmorProvider()
{
return armorProvider;
}
public LivingUpgrade withDamageProvider(IDamageProvider damageProvider)
{
this.damageProvider = damageProvider;
return this;
}
public IDamageProvider getDamageProvider()
{
return damageProvider;
}
public String getTranslationKey()
{
return translationKey == null ? translationKey = Util.makeTranslationKey("living_upgrade", key)
: translationKey;
}
public boolean isNegative()
{
return isNegative;
}
public boolean isCompatible(ResourceLocation otherUpgrade)
{
return !incompatible.contains(otherUpgrade);
}
public LivingUpgrade addIncompatibility(ResourceLocation key, ResourceLocation... otherKeys)
{
incompatible.add(key);
Collections.addAll(incompatible, otherKeys);
return this;
}
public int getLevel(int experience)
{
Map.Entry<Integer, Integer> floor = experienceToLevel.floorEntry(experience);
return floor == null ? 0 : floor.getValue();
}
public int getNextRequirement(int experience)
{
Integer ret = experienceToLevel.ceilingKey(experience + 1);
return ret == null ? 0 : ret;
}
public int getLevelCost(int level)
{
return levelToCost.getOrDefault(level, 0);
}
public ResourceLocation getKey()
{
return key;
}
public LivingUpgrade asDowngrade()
{
this.isNegative = true;
return this;
}
@Override
public String toString()
{
return key.toString();
}
public interface IAttributeProvider
{
void handleAttributes(LivingStats stats, Multimap<Attribute, AttributeModifier> modifiers, UUID uuid, LivingUpgrade upgrade, int level);
}
public interface IArmorProvider
{
double getProtection(PlayerEntity player, LivingStats stats, DamageSource source, LivingUpgrade upgrade, int level);
}
public interface IDamageProvider
{
double getAdditionalDamage(PlayerEntity player, ItemStack weapon, double damage, LivingStats stats, LivingEntity attacked, LivingUpgrade upgrade, int level);
}
public static class Level
{
@SerializedName("xp")
private final int experienceNeeded;
@SerializedName("cost")
private final int upgradeCost;
public Level(int experienceNeeded, int upgradeCost)
{
this.experienceNeeded = experienceNeeded;
this.upgradeCost = upgradeCost;
}
}
public static class Bonus
{
private static final Bonus DEFAULT = new Bonus("null", Collections.emptyList());
private final String id;
private final List<Number> modifiers;
public Bonus(String id, List<Number> modifiers)
{
this.id = id;
this.modifiers = modifiers;
}
public String getId()
{
return id;
}
}
public static class Deserializer implements JsonDeserializer<LivingUpgrade>
{
@Override
public LivingUpgrade deserialize(JsonElement element, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
JsonObject json = element.getAsJsonObject();
ResourceLocation id = new ResourceLocation(json.getAsJsonPrimitive("id").getAsString());
List<Level> levels = context.deserialize(json.getAsJsonArray("levels"), new TypeToken<List<Level>>()
{
}.getType());
boolean negative = json.has("negative") && json.getAsJsonPrimitive("negative").getAsBoolean();
LivingUpgrade upgrade = new LivingUpgrade(id, upgradeLevels -> upgradeLevels.addAll(levels));
if (negative)
upgrade.asDowngrade();
if (json.has("incompatibilities"))
{
String[] incompatibilities = context.deserialize(json.getAsJsonArray("incompatibilities"), String[].class);
for (String incompatible : incompatibilities)
upgrade.addIncompatibility(new ResourceLocation(incompatible));
}
if (json.has("bonuses"))
{
Map<String, Number[]> bonuses = context.deserialize(json.getAsJsonObject("bonuses"), new TypeToken<Map<String, Number[]>>()
{
}.getType());
bonuses.forEach((k, v) -> upgrade.withBonusSet(k, numbers -> Collections.addAll(numbers, v)));
}
return upgrade;
}
}
}

View file

@ -0,0 +1,176 @@
package wayoftime.bloodmagic.core.living;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.Multimap;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ArmorItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.common.MinecraftForge;
import wayoftime.bloodmagic.common.item.ItemLivingTrainer;
import wayoftime.bloodmagic.core.util.PlayerUtil;
import wayoftime.bloodmagic.event.LivingEquipmentEvent;
public class LivingUtil
{
public static LivingStats applyNewExperience(PlayerEntity player, LivingUpgrade upgrade, double experience)
{
LivingStats stats = LivingStats.fromPlayer(player, true);
if (stats == null)
return null;
if (!canTrain(player, upgrade, upgrade.getLevel((int) experience)))
return stats;
LivingEquipmentEvent.GainExperience event = new LivingEquipmentEvent.GainExperience(player, stats, upgrade, experience);
// EventResult result = LivingEquipmentEvent.EXPERIENCE_GAIN.invoker().gainExperience(event);
MinecraftForge.EVENT_BUS.post(event);
if (event.isCanceled())
return stats;
experience = event.getExperience();
double currentExperience = stats.getUpgrades().getOrDefault(upgrade, 0d);
double requiredForLevel = upgrade.getNextRequirement((int) currentExperience) - currentExperience;
// If we're going to level up from this, check points
if (requiredForLevel <= experience)
{
int currentPoints = stats.getUsedPoints();
// If we're already capped or somehow over the cap, we don't want to add
// experience
if (currentPoints >= stats.getMaxPoints())
return stats;
int nextPointCost = upgrade.getLevelCost(upgrade.getLevel((int) currentExperience) + 1);
// If there's no more levels in this upgrade, we don't want to add experience
if (nextPointCost == -1)
return stats;
// If applying this new level will go over our cap, we don't want to add
// experience
if (currentPoints + nextPointCost > stats.getMaxPoints())
return stats;
}
int newLevel = upgrade.getLevel((int) (currentExperience + experience));
if (upgrade.getLevel((int) currentExperience) != newLevel)
{
LivingEquipmentEvent.LevelUp levelUpEvent = new LivingEquipmentEvent.LevelUp(player, stats, upgrade);
// LivingEquipmentEvent.LEVEL_UP.invoker().levelUp(levelUpEvent);
MinecraftForge.EVENT_BUS.post(levelUpEvent);
player.sendStatusMessage(new TranslationTextComponent("chat.bloodmagic.living_upgrade_level_increase", new TranslationTextComponent(upgrade.getTranslationKey()), newLevel), true);
}
System.out.println("Adding experience!");
stats.addExperience(upgrade.getKey(), experience);
LivingStats.toPlayer(player, stats);
return stats;
}
public static double getDamageReceivedForArmour(PlayerEntity player, DamageSource source, double damage)
{
// System.out.println("Initial damage from " + source + ": " + damage);
LivingStats stats = LivingStats.fromPlayer(player, true);
if (stats == null)
return damage;
Map<LivingUpgrade, Double> upgrades = stats.getUpgrades();
for (Entry<LivingUpgrade, Double> entry : upgrades.entrySet())
{
LivingUpgrade upgrade = entry.getKey();
if (upgrade.getArmorProvider() == null)
{
continue;
}
int level = upgrade.getLevel(entry.getValue().intValue());
damage *= 1 - upgrade.getArmorProvider().getProtection(player, stats, source, upgrade, level);
}
// System.out.println("Final damage: " + damage);
return damage;
}
public static double getAdditionalDamage(PlayerEntity player, ItemStack weapon, LivingEntity attackedEntity, double damage)
{
// System.out.println("Initial damage from " + source + ": " + damage);
LivingStats stats = LivingStats.fromPlayer(player, true);
if (stats == null)
return 0;
double additionalDamage = 0;
Map<LivingUpgrade, Double> upgrades = stats.getUpgrades();
for (Entry<LivingUpgrade, Double> entry : upgrades.entrySet())
{
LivingUpgrade upgrade = entry.getKey();
if (upgrade.getArmorProvider() == null)
{
continue;
}
int level = upgrade.getLevel(entry.getValue().intValue());
if (upgrade.getDamageProvider() == null)
{
continue;
}
additionalDamage += upgrade.getDamageProvider().getAdditionalDamage(player, weapon, damage, stats, attackedEntity, upgrade, level);
}
// System.out.println("Final damage: " + damage);
return additionalDamage;
}
public static boolean canTrain(PlayerEntity player, LivingUpgrade upgrade, int currentLevel)
{
ItemStack trainer = PlayerUtil.findItem(player, stack -> stack.getItem() instanceof ItemLivingTrainer && stack.hasTag() && stack.getTag().contains("livingStats"));
if (trainer.isEmpty())
return true;
String mode = trainer.getTag().getString("livingLock");
LivingStats stats = ((ILivingContainer) trainer.getItem()).getLivingStats(trainer);
int levelLimit = stats.getLevel(upgrade.getKey());
if (mode.equalsIgnoreCase("whitelist"))
{
return levelLimit != 0 && levelLimit > currentLevel;
} else if (mode.equalsIgnoreCase("blacklist"))
{
return levelLimit == 0;
}
return true;
}
public static boolean hasFullSet(PlayerEntity player)
{
for (ItemStack stack : player.inventory.armorInventory)
if (stack.isEmpty() || !(stack.getItem() instanceof ILivingContainer))
return false;
return true;
}
public static void applyAttributes(Multimap<Attribute, AttributeModifier> attributes, ItemStack stack, PlayerEntity player, EquipmentSlotType slot)
{
if (player == null || !hasFullSet(player))
return;
Multimap<Attribute, AttributeModifier> newAttributes = ((ArmorItem) stack.getItem()).getAttributeModifiers(slot, stack);
// newAttributes.values().forEach(e -> e.setSerialize(false));
attributes.putAll(newAttributes);
}
}

View file

@ -0,0 +1,15 @@
package wayoftime.bloodmagic.core.living;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.DamageSource;
public class ProjectileArmorProvider implements LivingUpgrade.IArmorProvider
{
@Override
public double getProtection(PlayerEntity player, LivingStats stats, DamageSource source, LivingUpgrade upgrade, int level)
{
// TODO Auto-generated method stub
return 0;
}
}

View file

@ -0,0 +1,57 @@
package wayoftime.bloodmagic.core.util;
import java.util.function.Predicate;
import com.google.common.collect.Multimap;
import net.minecraft.entity.ai.attributes.Attribute;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import wayoftime.bloodmagic.common.item.ExpandedArmor;
import wayoftime.bloodmagic.core.living.LivingUtil;
public class PlayerUtil
{
public static ItemStack findItem(PlayerEntity player, Predicate<ItemStack> requirements)
{
// Check offhand first
ItemStack offHand = player.getHeldItemOffhand();
if (requirements.test(offHand))
return offHand;
// Check inventory next
for (int slot = 0; slot < player.inventory.getSizeInventory(); slot++)
{
ItemStack foundStack = player.inventory.getStackInSlot(slot);
if (!foundStack.isEmpty() && requirements.test(foundStack))
return foundStack;
}
return ItemStack.EMPTY;
}
public static Multimap<Attribute, AttributeModifier> handle(PlayerEntity player, Multimap<Attribute, AttributeModifier> existing)
{
ItemStack chest = player.getItemStackFromSlot(EquipmentSlotType.CHEST);
boolean hasFullSet = LivingUtil.hasFullSet(player);
if (hasFullSet && existing == null)
{
existing = ((ExpandedArmor) chest.getItem()).getAttributeModifiers(EquipmentSlotType.CHEST, chest);
player.getAttributeManager().reapplyModifiers(existing);
}
if (!hasFullSet && existing != null)
{
player.getAttributeManager().removeModifiers(existing);
existing = null;
}
return existing;
}
}

View file

@ -0,0 +1,78 @@
package wayoftime.bloodmagic.core.util;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.io.IOUtils;
import net.minecraft.util.ResourceLocation;
import wayoftime.bloodmagic.BloodMagic;
public class ResourceUtil
{
public static Set<Path> gatherResources(String home, String following, Predicate<Path> predicate)
{
FileSystem fileSystem = null;
try
{
URL url = ResourceUtil.class.getResource(home);
if (url != null)
{
URI uri = url.toURI();
Path path;
if (uri.getScheme().equals("file"))
{
path = Paths.get(ResourceUtil.class.getResource(home + "/" + following).toURI());
} else
{
if (!uri.getScheme().equals("jar"))
{
BloodMagic.LOGGER.error("Unsupported URI scheme {}", uri.getScheme());
return Collections.emptySet();
}
try
{
fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap());
} catch (FileSystemAlreadyExistsException e)
{
fileSystem = FileSystems.getFileSystem(uri);
}
path = fileSystem.getPath(home + "/" + following);
}
return Files.walk(path).filter(predicate).collect(Collectors.toSet());
}
} catch (IOException | URISyntaxException e)
{
e.printStackTrace();
} finally
{
IOUtils.closeQuietly(fileSystem);
}
return Collections.emptySet();
}
public static Set<Path> gatherResources(String home, String following)
{
return gatherResources(home, following, p -> true);
}
public static ResourceLocation addContext(ResourceLocation rl, String context)
{
return new ResourceLocation(rl.getNamespace(), context + rl.getPath());
}
}

View file

@ -0,0 +1,27 @@
package wayoftime.bloodmagic.core.util;
public final class Value<T>
{
private T value;
private Value(T t)
{
this.value = t;
}
public T get()
{
return value;
}
public Value<T> set(T t)
{
this.value = t;
return this;
}
public static <T> Value<T> of(T t)
{
return new Value<>(t);
}
}

View file

@ -0,0 +1,96 @@
package wayoftime.bloodmagic.event;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraftforge.eventbus.api.Event;
import wayoftime.bloodmagic.core.living.LivingStats;
import wayoftime.bloodmagic.core.living.LivingUpgrade;
public class LivingEquipmentEvent extends Event
{
// public static final Event<OnExperienceGain> EXPERIENCE_GAIN = EventFactory.createArrayBacked(OnExperienceGain.class, handlers -> e -> {
// for (OnExperienceGain gain : handlers) if (gain.gainExperience(e) == EventResult.CANCEL)
// return EventResult.CANCEL;
//
// return EventResult.PASS;
// });
// public static final Event<OnLevelUp> LEVEL_UP = EventFactory.createArrayBacked(OnLevelUp.class, handlers -> e -> {
// for (OnLevelUp levelUp : handlers) levelUp.levelUp(e);
// });
//
// public interface OnExperienceGain
// {
// EventResult gainExperience(GainExperience event);
// }
//
// public interface OnLevelUp
// {
// void levelUp(LevelUp event);
// }
private final PlayerEntity player;
private final LivingStats stats;
private LivingEquipmentEvent(PlayerEntity player, LivingStats stats)
{
this.player = player;
this.stats = stats;
}
public PlayerEntity getPlayer()
{
return player;
}
public LivingStats getStats()
{
return stats;
}
public static class GainExperience extends LivingEquipmentEvent
{
private final LivingUpgrade upgrade;
private double experience;
public GainExperience(PlayerEntity player, LivingStats stats, LivingUpgrade upgrade, double experience)
{
super(player, stats);
this.upgrade = upgrade;
this.experience = experience;
}
public LivingUpgrade getUpgrade()
{
return upgrade;
}
public double getExperience()
{
return experience;
}
public void setExperience(double experience)
{
this.experience = experience;
}
}
public static class LevelUp extends LivingEquipmentEvent
{
private final LivingUpgrade upgrade;
public LevelUp(PlayerEntity player, LivingStats stats, LivingUpgrade upgrade)
{
super(player, stats);
this.upgrade = upgrade;
}
public LivingUpgrade getUpgrade()
{
return upgrade;
}
}
}

View file

@ -0,0 +1,30 @@
package wayoftime.bloodmagic.event;
import net.minecraftforge.eventbus.api.Event;
public class LivingEvent extends Event
{
// public static final Event<Jump> JUMP = EventFactory.createArrayBacked(Jump.class, handlers -> e -> {
// for (Jump handler : handlers) if (handler.onJump(e) == EventResult.CANCEL)
// return EventResult.CANCEL;
//
// return EventResult.PASS;
// });
// public static final Event<Damage> DAMAGE = EventFactory.createArrayBacked(Damage.class, handlers -> (e, s, d) -> {
// for (Damage handler : handlers) if (handler.onDamage(e, s, d) == EventResult.CANCEL)
// return EventResult.CANCEL;
//
// return EventResult.PASS;
// });
//
// public interface Jump
// {
// EventResult onJump(LivingEntity livingEntity);
// }
//
// public interface Damage
// {
// EventResult onDamage(LivingEntity livingEntity, DamageSource source, Value<Float> damage);
// }
}

View file

@ -623,4 +623,112 @@ public class Utils
return added;
}
// public static float getModifiedDamage(LivingEntity attackedEntity, DamageSource source, float amount)
// {
// if (!attackedEntity.isInvulnerableTo(source))
// {
// if (amount <= 0)
// return 0;
//
// amount = applyArmor(attackedEntity, Iterables.toArray(attackedEntity.getEquipmentAndArmor(), ItemStack.class), source, amount);
// if (amount <= 0)
// return 0;
// amount = applyPotionDamageCalculations(attackedEntity, source, amount);
//
// return amount;
// }
//
// return 0;
// }
//
// public static float applyArmor(LivingEntity entity, ItemStack[] inventory, DamageSource source, double damage)
// {
// damage *= 25;
// ArrayList<ArmorProperties> dmgVals = new ArrayList<>();
// for (int x = 0; x < inventory.length; x++)
// {
// ItemStack stack = inventory[x];
// if (stack.isEmpty())
// {
// continue;
// }
// ArmorProperties prop = null;
// if (stack.getItem() instanceof ISpecialArmor)
// {
// ISpecialArmor armor = (ISpecialArmor) stack.getItem();
// prop = armor.getProperties(entity, stack, source, damage / 25D, x).copy();
// } else if (stack.getItem() instanceof ArmorItem && !source.isUnblockable())
// {
// ArmorItem armor = (ArmorItem) stack.getItem();
// prop = new ArmorProperties(0, armor.damageReduceAmount / 25D, Integer.MAX_VALUE);
// }
// if (prop != null)
// {
// prop.Slot = x;
// dmgVals.add(prop);
// }
// }
// if (dmgVals.size() > 0)
// {
// ArmorProperties[] props = dmgVals.toArray(new ArmorProperties[dmgVals.size()]);
// int level = props[0].Priority;
// double ratio = 0;
// for (ArmorProperties prop : props)
// {
// if (level != prop.Priority)
// {
// damage -= (damage * ratio);
// ratio = 0;
// level = prop.Priority;
// }
// ratio += prop.AbsorbRatio;
//
// }
// damage -= (damage * ratio);
// }
//
// return (float) (damage / 25.0F);
// }
//
// public static float applyPotionDamageCalculations(LivingEntity attackedEntity, DamageSource source, float damage)
// {
// Effect resistance = Effects.RESISTANCE;
//
// if (source.isDamageAbsolute())
// {
// return damage;
// } else
// {
// if (attackedEntity.isPotionActive(resistance) && source != DamageSource.OUT_OF_WORLD)
// {
// int i = (attackedEntity.getActivePotionEffect(resistance).getAmplifier() + 1) * 5;
// int j = 25 - i;
// float f = damage * (float) j;
// damage = f / 25.0F;
// }
//
// if (damage <= 0.0F)
// {
// return 0.0F;
// } else
// {
// int k = EnchantmentHelper.getEnchantmentModifierDamage(attackedEntity.getArmorInventoryList(), source);
//
// if (k > 20)
// {
// k = 20;
// }
//
// if (k > 0 && k <= 20)
// {
// int l = 25 - k;
// float f1 = damage * (float) l;
// damage = f1 / 25.0F;
// }
//
// return damage;
// }
// }
// }
}

View file

@ -1,19 +1,30 @@
package wayoftime.bloodmagic.util.handler.event;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.enchantment.Enchantments;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.ToolType;
import net.minecraftforge.event.entity.living.LivingDamageEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.living.LivingHealEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.entity.player.PlayerXpEvent;
import net.minecraftforge.event.world.BlockEvent.BlockToolInteractEvent;
@ -26,10 +37,14 @@ import wayoftime.bloodmagic.common.item.BloodOrb;
import wayoftime.bloodmagic.common.item.IBindable;
import wayoftime.bloodmagic.common.item.IBloodOrb;
import wayoftime.bloodmagic.common.item.ItemExperienceBook;
import wayoftime.bloodmagic.core.LivingArmorRegistrar;
import wayoftime.bloodmagic.core.data.Binding;
import wayoftime.bloodmagic.core.data.SoulNetwork;
import wayoftime.bloodmagic.core.living.LivingStats;
import wayoftime.bloodmagic.core.living.LivingUtil;
import wayoftime.bloodmagic.demonaura.WorldDemonWillHandler;
import wayoftime.bloodmagic.event.ItemBindEvent;
import wayoftime.bloodmagic.event.SacrificeKnifeUsedEvent;
import wayoftime.bloodmagic.network.DemonAuraClientPacket;
import wayoftime.bloodmagic.potion.BMPotionUtils;
import wayoftime.bloodmagic.potion.BloodMagicPotions;
@ -100,6 +115,95 @@ public class GenericHandler
// }
}
@SubscribeEvent
// Called when an entity is set to be hurt. Called before vanilla armour
// calculations.
public void onLivingHurt(LivingHurtEvent event)
{
Entity sourceEntity = event.getSource().getTrueSource();
LivingEntity living = event.getEntityLiving();
if (sourceEntity instanceof PlayerEntity)
{
PlayerEntity sourcePlayer = (PlayerEntity) sourceEntity;
if (LivingUtil.hasFullSet(sourcePlayer))
{
ItemStack mainWeapon = sourcePlayer.getActiveItemStack();
double additionalDamage = LivingUtil.getAdditionalDamage(sourcePlayer, mainWeapon, living, event.getAmount());
event.setAmount((float) (event.getAmount() + additionalDamage));
}
}
if (living instanceof PlayerEntity)
{
PlayerEntity player = (PlayerEntity) living;
if (LivingUtil.hasFullSet(player))
{
event.setAmount((float) LivingUtil.getDamageReceivedForArmour(player, event.getSource(), event.getAmount()));
}
}
}
@SubscribeEvent
// Called after armour calculations (including LivingHurtEvent) are parsed.
// Damage that the player should receive after armour/absorption hearts.
public void onLivingDamage(LivingDamageEvent event)
{
Entity sourceEntity = event.getSource().getTrueSource();
LivingEntity living = event.getEntityLiving();
if (sourceEntity instanceof PlayerEntity)
{
PlayerEntity sourcePlayer = (PlayerEntity) sourceEntity;
if (LivingUtil.hasFullSet(sourcePlayer))
{
if (sourcePlayer.isSprinting())
{
LivingUtil.applyNewExperience(sourcePlayer, LivingArmorRegistrar.UPGRADE_SPRINT_ATTACK.get(), event.getAmount());
}
}
}
if (living instanceof PlayerEntity)
{
PlayerEntity player = (PlayerEntity) living;
if (LivingUtil.hasFullSet(player))
{
if (event.getSource().isProjectile())
{
// LivingStats stats = LivingStats.fromPlayer(player);
// stats.addExperience(LivingArmorRegistrar.TEST_UPGRADE.get().getKey(), 10);
LivingUtil.applyNewExperience(player, LivingArmorRegistrar.UPGRADE_ARROW_PROTECT.get(), event.getAmount());
}
}
}
}
@SubscribeEvent(priority = EventPriority.HIGHEST)
public void onExperiencePickupHighest(PlayerXpEvent.PickupXp event)
{
LivingEntity living = event.getEntityLiving();
if (living instanceof PlayerEntity)
{
PlayerEntity player = (PlayerEntity) living;
if (LivingUtil.hasFullSet(player))
{
LivingStats stats = LivingStats.fromPlayer(player);
double expModifier = 1 + LivingArmorRegistrar.UPGRADE_EXPERIENCE.get().getBonusValue("exp", stats.getLevel(LivingArmorRegistrar.UPGRADE_EXPERIENCE.get().getKey())).doubleValue();
System.out.println("Experience modifier: " + expModifier);
int xp = event.getOrb().xpValue;
event.getOrb().xpValue = ((int) Math.floor(xp * expModifier) + (player.world.rand.nextDouble() < (xp * expModifier) % 1
? 1
: 0));
LivingUtil.applyNewExperience(player, LivingArmorRegistrar.UPGRADE_EXPERIENCE.get(), event.getOrb().getXpValue());
}
}
}
@SubscribeEvent
public void onHoe(BlockToolInteractEvent event)
{
@ -185,4 +289,85 @@ public class GenericHandler
}
}
}
@SubscribeEvent
public void onHeal(LivingHealEvent event)
{
LivingEntity living = event.getEntityLiving();
if (living instanceof PlayerEntity)
{
PlayerEntity player = (PlayerEntity) living;
if (LivingUtil.hasFullSet(player))
{
LivingUtil.applyNewExperience(player, LivingArmorRegistrar.UPGRADE_HEALTH.get(), event.getAmount());
}
}
}
@SubscribeEvent
public void onSelfSacrifice(SacrificeKnifeUsedEvent event)
{
if (LivingUtil.hasFullSet(event.player))
{
LivingStats stats = LivingStats.fromPlayer(event.player);
double bonus = LivingArmorRegistrar.UPGRADE_SELF_SACRIFICE.get().getBonusValue("self_mod", stats.getLevel(LivingArmorRegistrar.UPGRADE_SELF_SACRIFICE.get().getKey())).doubleValue();
event.lpAdded = (int) Math.round(event.lpAdded * (1 + bonus));
LivingUtil.applyNewExperience(event.player, LivingArmorRegistrar.UPGRADE_SELF_SACRIFICE.get(), event.healthDrained);
}
}
public static Map<UUID, Double> posXMap = new HashMap<>();
public static Map<UUID, Double> posZMap = new HashMap<>();
@SubscribeEvent(priority = EventPriority.HIGHEST)
public void onEntityUpdate(LivingEvent.LivingUpdateEvent event)
{
if (event.getEntity().world.isRemote)
{
return;
}
if (event.getEntityLiving() instanceof PlayerEntity)
{
PlayerEntity player = (PlayerEntity) event.getEntityLiving();
float percentIncrease = 0;
if (LivingUtil.hasFullSet(player))
{
LivingStats stats = LivingStats.fromPlayer(player);
percentIncrease += LivingArmorRegistrar.UPGRADE_SPEED.get().getBonusValue("speed_modifier", stats.getLevel(LivingArmorRegistrar.UPGRADE_SPEED.get().getKey())).doubleValue();
if (player.isSprinting())
{
int speedTime = LivingArmorRegistrar.UPGRADE_SPEED.get().getBonusValue("speed_time", stats.getLevel(LivingArmorRegistrar.UPGRADE_SPEED.get().getKey())).intValue();
if (speedTime > 0)
{
int speedLevel = LivingArmorRegistrar.UPGRADE_SPEED.get().getBonusValue("speed_level", stats.getLevel(LivingArmorRegistrar.UPGRADE_SPEED.get().getKey())).intValue();
player.addPotionEffect(new EffectInstance(Effects.SPEED, speedTime, speedLevel, true, false));
}
}
double distance = 0;
if (posXMap.containsKey(player.getUniqueID()))
{
distance = Math.sqrt((player.getPosX() - posXMap.get(player.getUniqueID())) * (player.getPosX() - posXMap.get(player.getUniqueID())) + (player.getPosZ() - posZMap.get(player.getUniqueID())) * (player.getPosZ() - posZMap.get(player.getUniqueID())));
}
// System.out.println("Distance travelled: " + distance);
if (player.isOnGround() && distance > 0 && distance < 50)
{
distance *= (1 + percentIncrease);
LivingUtil.applyNewExperience(player, LivingArmorRegistrar.UPGRADE_SPEED.get(), distance);
}
}
if (percentIncrease > 0 && (player.isOnGround()) && (Math.abs(player.moveForward) > 0 || Math.abs(player.moveStrafing) > 0))
{
player.travel(new Vector3d(player.moveStrafing * percentIncrease, 0, player.moveForward * percentIncrease));
}
posXMap.put(player.getUniqueID(), player.getPosX());
posZMap.put(player.getUniqueID(), player.getPosZ());
}
}
}

View file

@ -0,0 +1,29 @@
{
"id": "bloodmagic:arrow_protect",
"levels": [
{ "xp": 30, "cost": 4 },
{ "xp": 200, "cost": 9 },
{ "xp": 400, "cost": 16 },
{ "xp": 800, "cost": 30 },
{ "xp": 1500, "cost": 60 },
{ "xp": 2500, "cost": 90 },
{ "xp": 3500, "cost": 125 },
{ "xp": 5000, "cost": 165 },
{ "xp": 7000, "cost": 210 },
{ "xp": 15000, "cost": 250 }
],
"bonuses": {
"protection": [
0.1,
0.3,
0.4,
0.6,
0.7,
0.75,
0.77,
0.8,
0.83,
0.85
]
}
}

View file

@ -0,0 +1,10 @@
{
"id": "bloodmagic:arrow_shot",
"levels": [
{ "xp": 50, "cost": 20 },
{ "xp": 200, "cost": 50 },
{ "xp": 700, "cost": 90 },
{ "xp": 1500, "cost": 160 },
{ "xp": 3000, "cost": 290 }
]
}

View file

@ -0,0 +1,19 @@
{
"id": "bloodmagic:critical_strike",
"levels": [
{ "xp": 200, "cost": 5 },
{ "xp": 800, "cost": 12 },
{ "xp": 1300, "cost": 22 },
{ "xp": 2500, "cost": 35 },
{ "xp": 3000, "cost": 49 }
],
"bonuses": {
"damage_boost": [
0.1,
0.2,
0.3,
0.4,
0.5
]
}
}

View file

@ -0,0 +1,53 @@
{
"id": "bloodmagic:digging",
"levels": [
{ "xp": 128, "cost": 5 },
{ "xp": 512, "cost": 10 },
{ "xp": 1024, "cost": 18 },
{ "xp": 2048, "cost": 32 },
{ "xp": 8192, "cost": 60 },
{ "xp": 16000, "cost": 90 },
{ "xp": 32000, "cost": 140 },
{ "xp": 50000, "cost": 180 },
{ "xp": 80000, "cost": 240 },
{ "xp": 150000, "cost": 300 }
],
"bonuses": {
"speed_time": [
0,
50,
60,
100,
100,
100,
100,
150,
150,
150
],
"speed_level": [
0,
0,
0,
1,
1,
1,
1,
1,
2,
2
],
"speed_modifier": [
1.1,
1.2,
1.3,
1.4,
1.5,
1.6,
1.8,
2,
2.2,
2.5
]
}
}

View file

@ -0,0 +1,29 @@
{
"id": "bloodmagic:experienced",
"levels": [
{ "xp": 100, "cost": 7 },
{ "xp": 400, "cost": 13 },
{ "xp": 1000, "cost": 22 },
{ "xp": 1600, "cost": 40 },
{ "xp": 3200, "cost": 65 },
{ "xp": 5000, "cost": 90 },
{ "xp": 7000, "cost": 130 },
{ "xp": 9200, "cost": 180 },
{ "xp": 11500, "cost": 250 },
{ "xp": 14000, "cost": 350 }
],
"bonuses": {
"exp": [
0.15,
0.3,
0.45,
0.6,
0.75,
0.9,
1.05,
1.2,
1.35,
1.5
]
}
}

View file

@ -0,0 +1,19 @@
{
"id": "bloodmagic:fall_protect",
"levels": [
{ "xp": 30, "cost": 2 },
{ "xp": 200, "cost": 5 },
{ "xp": 400, "cost": 9 },
{ "xp": 800, "cost": 15 },
{ "xp": 1500, "cost": 25 }
],
"bonuses": {
"protection": [
0.2,
0.4,
0.6,
0.8,
1
]
}
}

View file

@ -0,0 +1,26 @@
{
"id": "bloodmagic:fire_resist",
"levels": [
{ "xp": 1200, "cost": 2 },
{ "xp": 3600, "cost": 6 },
{ "xp": 12000, "cost": 14 },
{ "xp": 24000, "cost": 25 },
{ "xp": 30000, "cost": 40 }
],
"bonuses": {
"cooldown_time": [
6000,
4800,
4800,
3600,
2400
],
"resist_duration": [
600,
600,
800,
1000,
1200
]
}
}

View file

@ -0,0 +1,29 @@
{
"id": "bloodmagic:health",
"levels": [
{ "xp": 80, "cost": 5 },
{ "xp": 200, "cost": 12 },
{ "xp": 340, "cost": 20 },
{ "xp": 540, "cost": 35 },
{ "xp": 800, "cost": 49 },
{ "xp": 1600, "cost": 78 },
{ "xp": 2800, "cost": 110 },
{ "xp": 5000, "cost": 160 },
{ "xp": 7600, "cost": 215 },
{ "xp": 10000, "cost": 320 }
],
"bonuses": {
"hp": [
4,
8,
12,
16,
20,
26,
32,
38,
44,
50
]
}
}

View file

@ -0,0 +1,41 @@
{
"id": "bloodmagic:jump",
"levels": [
{ "xp": 10, "cost": 3 },
{ "xp": 20, "cost": 6 },
{ "xp": 30, "cost": 11 },
{ "xp": 40, "cost": 23 },
{ "xp": 40, "cost": 37 },
{ "xp": 40, "cost": 50 },
{ "xp": 40, "cost": 70 },
{ "xp": 40, "cost": 100 },
{ "xp": 40, "cost": 140 },
{ "xp": 40, "cost": 200 }
],
"bonuses": {
"jump": [
0.1,
0.2,
0.3,
0.4,
0.5,
0.7,
0.75,
0.9,
1.1,
1.3
],
"fall": [
0.1,
0.2,
0.3,
0.4,
0.5,
0.6,
0.7,
0.75,
0.8,
0.85
]
}
}

View file

@ -0,0 +1,29 @@
{
"id": "bloodmagic:self_sacrifice",
"levels": [
{ "xp": 30, "cost": 7 },
{ "xp": 200, "cost": 13 },
{ "xp": 400, "cost": 22 },
{ "xp": 700, "cost": 40 },
{ "xp": 1100, "cost": 65 },
{ "xp": 1500, "cost": 90 },
{ "xp": 2000, "cost": 130 },
{ "xp": 2800, "cost": 180 },
{ "xp": 3600, "cost": 250 },
{ "xp": 5000, "cost": 350 }
],
"bonuses": {
"self_mod": [
0.15,
0.3,
0.45,
0.6,
0.75,
0.9,
1.05,
1.2,
1.35,
1.5
]
}
}

View file

@ -0,0 +1,53 @@
{
"id": "bloodmagic:speed",
"levels": [
{ "xp": 200, "cost": 3 },
{ "xp": 1000, "cost": 7 },
{ "xp": 2000, "cost": 13 },
{ "xp": 4000, "cost": 26 },
{ "xp": 7000, "cost": 42 },
{ "xp": 15000, "cost": 60 },
{ "xp": 25000, "cost": 90 },
{ "xp": 35000, "cost": 130 },
{ "xp": 50000, "cost": 180 },
{ "xp": 70000, "cost": 250 }
],
"bonuses": {
"speed_time": [
0,
0,
0,
0,
0,
20,
60,
60,
100,
200
],
"speed_level": [
0,
0,
0,
0,
0,
0,
0,
1,
1,
2
],
"speed_modifier": [
0.1,
0.2,
0.3,
0.4,
0.5,
0.7,
0.9,
1.1,
1.3,
1.5
]
}
}

View file

@ -0,0 +1,26 @@
{
"id": "bloodmagic:sprint_attack",
"levels": [
{ "xp": 200, "cost": 3 },
{ "xp": 800, "cost": 7 },
{ "xp": 1300, "cost": 15 },
{ "xp": 2500, "cost": 25 },
{ "xp": 3800, "cost": 40 }
],
"bonuses": {
"damage_boost": [
0.5,
0.75,
1,
1.25,
1.5
],
"kb": [
1,
2,
3,
4,
5
]
}
}