From bb0e56a456cdd975de1d06e04535bca257240224 Mon Sep 17 00:00:00 2001
From: huige <61108540+huige233@users.noreply.github.com>
Date: Sun, 11 Sep 2022 17:02:07 +0800
Subject: [PATCH] add Creative RF Source and EU Source

---
 build.gradle                                  |   3 +-
 .../huige233/transcend/blocks/voidblock.java  |  14 +
 .../transcend/compat/Avartiabreak.java        |   3 +-
 .../transcend/compat/botaniasword.java        |  92 -----
 .../transcend/compat/tinkers/TiCConfig.java   |  10 +-
 .../compat/tinkers/TraitArmorFlawless.java    |  50 ++-
 .../compat/tinkers/TraitArmorTranscend.java   |  75 ++++
 .../compat/tinkers/TraitTranscend.java        |  49 ++-
 .../compat/tinkers/conarmConfig.java          |  50 +++
 .../transcend/items/armor/ArmorBase.java      |   4 +
 .../transcend/items/tools/ToolPickaxe.java    |  33 +-
 .../transcend/items/tools/ToolSword.java      | 103 +++++-
 .../huige233/transcend/proxy/CommonProxy.java |  17 +-
 .../tileEntity/TileCreativeRFSource.java      |   3 -
 .../tileEntity/VirusGeneratorRecipes.java     |   2 +-
 .../huige233/transcend/util/MathHelper.java   | 321 ++++++++++++++++++
 .../huige233/transcend/util/Reference.java    |   2 +-
 .../transcend/util/SupplierDefaultNoop.java   |  10 +
 .../huige233/transcend/util/SwordUtil.java    |   9 +
 .../util/handlers/ModEventHandler.java        |  36 ++
 .../assets/transcend/lang/en_US.lang          |   7 +
 .../assets/transcend/lang/zh_CN.lang          |   6 +
 src/main/resources/mcmod.info                 |   2 +-
 23 files changed, 775 insertions(+), 126 deletions(-)
 delete mode 100644 src/main/java/huige233/transcend/compat/botaniasword.java
 create mode 100644 src/main/java/huige233/transcend/compat/tinkers/TraitArmorTranscend.java
 create mode 100644 src/main/java/huige233/transcend/compat/tinkers/conarmConfig.java
 create mode 100644 src/main/java/huige233/transcend/util/MathHelper.java
 create mode 100644 src/main/java/huige233/transcend/util/SupplierDefaultNoop.java
 create mode 100644 src/main/java/huige233/transcend/util/handlers/ModEventHandler.java

diff --git a/build.gradle b/build.gradle
index 8ebd8c5..ef6a3d6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,8 +24,7 @@ apply plugin: "net.minecraftforge.gradle.forge"
 apply plugin: 'org.spongepowered.mixin'
 
 group = 'huige233'
-version = '1.1.3'
-archivesBaseName = 'transcend'
+version = '1.1.4'
 
 minecraft {
     version = project.forgeVersion
diff --git a/src/main/java/huige233/transcend/blocks/voidblock.java b/src/main/java/huige233/transcend/blocks/voidblock.java
index 51b2d18..401de08 100644
--- a/src/main/java/huige233/transcend/blocks/voidblock.java
+++ b/src/main/java/huige233/transcend/blocks/voidblock.java
@@ -12,6 +12,10 @@
 import net.minecraft.util.math.AxisAlignedBB;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.IBlockAccess;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.event.world.BlockEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 
 import java.util.Random;
 
@@ -69,4 +73,14 @@ public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAcces
     public boolean canEntityDestroy(IBlockState state, IBlockAccess world, BlockPos pos, Entity entity) {
         return false;
     }
+
+    @SubscribeEvent(priority = EventPriority.HIGHEST)
+    public void onBlockBreak(BlockEvent.BreakEvent event){
+        event.setCanceled(true);
+    }
+
+    @SubscribeEvent(priority = EventPriority.HIGHEST)
+    public void onBlockPush(PlayerInteractEvent.LeftClickBlock event){
+        event.setCanceled(true);
+    }
 }
diff --git a/src/main/java/huige233/transcend/compat/Avartiabreak.java b/src/main/java/huige233/transcend/compat/Avartiabreak.java
index 0509bd8..e03d1a1 100644
--- a/src/main/java/huige233/transcend/compat/Avartiabreak.java
+++ b/src/main/java/huige233/transcend/compat/Avartiabreak.java
@@ -1,11 +1,10 @@
 package huige233.transcend.compat;
 
+import morph.avaritia.init.ModItems;
 import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.NonNullList;
 import net.minecraftforge.fml.common.Mod;
-import morph.avaritia.init.ModItems;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
 
 @Mod.EventBusSubscriber
 public class Avartiabreak {
diff --git a/src/main/java/huige233/transcend/compat/botaniasword.java b/src/main/java/huige233/transcend/compat/botaniasword.java
deleted file mode 100644
index f972111..0000000
--- a/src/main/java/huige233/transcend/compat/botaniasword.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package huige233.transcend.compat;
-
-import huige233.transcend.Main;
-import huige233.transcend.init.ModItems;
-import huige233.transcend.util.ItemNBTHelper;
-import net.minecraft.creativetab.CreativeTabs;
-import net.minecraft.item.ItemStack;
-import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.NonNullList;
-import net.minecraftforge.fml.common.Optional;
-import org.jetbrains.annotations.NotNull;
-import vazkii.botania.api.mana.ICreativeManaProvider;
-import vazkii.botania.api.mana.IManaItem;
-import vazkii.botania.api.mana.IManaTooltipDisplay;
-
-public class botaniasword implements ICreativeManaProvider, IManaItem, IManaTooltipDisplay {
-    public botaniasword() {
-
-    }
-
-    public void getSubItems(@NotNull CreativeTabs tab,NonNullList<ItemStack> stack) {
-        if(tab == Main.TranscendTab){
-            ItemStack create = new ItemStack(ModItems.TRANSCEND_SWORD);
-            setMana(create, MAX_MANA);
-            isCreative(create);
-            setStackCreative(create);
-            stack.add(create);
-        }
-    }
-    protected static final int MAX_MANA = Integer.MAX_VALUE;
-    private static final String TAG_CREATIVE = "creative";
-    private static final String TAG_ONE_USE = "oneUse";
-    private static final String TAG_MANA = "mana";
-
-    public static void setMana(ItemStack stack, int mana) {
-        ItemNBTHelper.setInt(stack, TAG_MANA, MAX_MANA-1);
-    }
-
-    public static void setStackCreative(ItemStack stack) {
-        ItemNBTHelper.setBoolean(stack, TAG_CREATIVE, true);
-    }
-
-    @Override
-    public int getMana(ItemStack stack) {
-        return ItemNBTHelper.getInt(stack, TAG_MANA, 0);
-    }
-
-    @Override
-    public int getMaxMana(ItemStack stack) {
-        return MAX_MANA-1;
-    }
-
-    @Override
-    public void addMana(ItemStack stack, int mana) {
-        setMana(stack, Math.min(getMana(stack) + mana, getMaxMana(stack)));
-    }
-
-    @Override
-    public boolean canReceiveManaFromPool(ItemStack stack, TileEntity pool) {
-        return !ItemNBTHelper.getBoolean(stack, TAG_ONE_USE, false);
-    }
-
-    @Override
-    public boolean canReceiveManaFromItem(ItemStack stack, ItemStack otherStack) {
-        return true;
-    }
-
-    @Override
-    public boolean canExportManaToPool(ItemStack stack, TileEntity pool) {
-        return true;
-    }
-
-    @Override
-    public boolean canExportManaToItem(ItemStack stack, ItemStack otherStack) {
-        return true;
-    }
-
-    @Override
-    public boolean isNoExport(ItemStack stack) {
-        return true;
-    }
-
-    @Override
-    public float getManaFractionForDisplay(ItemStack stack) {
-        return (float) getMana(stack) / (float)getMaxMana(stack);
-    }
-
-    @Override
-    public boolean isCreative(ItemStack stack) {
-        return false;
-    }
-}
diff --git a/src/main/java/huige233/transcend/compat/tinkers/TiCConfig.java b/src/main/java/huige233/transcend/compat/tinkers/TiCConfig.java
index 729c1c8..bf387f1 100644
--- a/src/main/java/huige233/transcend/compat/tinkers/TiCConfig.java
+++ b/src/main/java/huige233/transcend/compat/tinkers/TiCConfig.java
@@ -30,7 +30,7 @@ public class TiCConfig {
     public static final AbstractTrait transcendtratt =  new TraitTranscend();
     public static final List<Material> materials = Lists.newArrayList();
     public static Material flawless = mat("flawless", 0x777777);
-    public static final Material transcend = mat("transcend",0x9e9e9e9);
+    public static final Material transcend = mat("transcend",0xF8F8FF);
     private static Material mat(String name, int color) {
         if (TinkerRegistry.getMaterial(name) == TinkerRegistry.getMaterial("unknown")){
             Material mat = new Material(name, color);
@@ -47,8 +47,8 @@ public static void setup() {
         flawless.setRepresentativeItem(ModItems.FLAWLESS);
         flawless.setCastable(true);
         flawless.setCraftable(true);
-        flawless.addTrait(flawlesstrait, HEAD);
-        flawless.addTrait(TinkerTraits.tasty,HEAD);
+        flawless.addTrait(flawlesstrait);
+        flawless.addTrait(TinkerTraits.tasty);
         TinkerRegistry.addMaterialStats(flawless,
                 new HeadMaterialStats(9999, 100.0f, 2000.0f, 32),
                 new HandleMaterialStats(10.0f, 9999),
@@ -61,7 +61,7 @@ public static void setup() {
         transcend.setRepresentativeItem(ModItems.TRANSCEND);
         transcend.setCastable(true);
         transcend.setCraftable(true);
-        transcend.addTrait(transcendtratt, HEAD);
+        transcend.addTrait(transcendtratt);
         TinkerRegistry.addMaterialStats(transcend,
                 new HeadMaterialStats(9999, 100.0f, 9999.0f, 99),
                 new HandleMaterialStats(100.0f, 9999),
@@ -110,7 +110,7 @@ public void postInit(FMLPostInitializationEvent event) {
     static void registerMaterialRendering()
     {
         flawless.setRenderInfo(new MaterialRenderInfo.Metal(0x777777, 0.5f, 0.5f, 0.2f));
-        transcend.setRenderInfo(new MaterialRenderInfo.Metal(0x9e9e9e, 0.5f, 0.5f, 0.2f));
+        transcend.setRenderInfo(new MaterialRenderInfo.Metal(0xF8F8FF, 0.5f, 0.5f, 0.2f));
     }
 }
 
diff --git a/src/main/java/huige233/transcend/compat/tinkers/TraitArmorFlawless.java b/src/main/java/huige233/transcend/compat/tinkers/TraitArmorFlawless.java
index 33f6c0f..a50b76a 100644
--- a/src/main/java/huige233/transcend/compat/tinkers/TraitArmorFlawless.java
+++ b/src/main/java/huige233/transcend/compat/tinkers/TraitArmorFlawless.java
@@ -1,23 +1,67 @@
 package huige233.transcend.compat.tinkers;
 
+import c4.conarm.common.armor.utils.ArmorTagUtil;
+import c4.conarm.lib.armor.ArmorNBT;
 import c4.conarm.lib.traits.AbstractArmorTrait;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
 import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.MobEffects;
+import net.minecraft.inventory.EntityEquipmentSlot;
 import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.PotionEffect;
 import net.minecraft.util.DamageSource;
 import net.minecraft.util.text.TextFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.MinecraftForge;
 import net.minecraftforge.event.entity.living.LivingDamageEvent;
 import net.minecraftforge.event.entity.living.LivingHurtEvent;
+import slimeknights.tconstruct.library.utils.TagUtil;
+
+import java.util.List;
 
 public class TraitArmorFlawless extends AbstractArmorTrait {
+    public static final TraitArmorFlawless a = new TraitArmorFlawless();
     public TraitArmorFlawless() {
-        super("flawless",TextFormatting.DARK_GRAY);
+        super("flawless",0x777777);
+        MinecraftForge.EVENT_BUS.register(this);
     }
 
     public float onHurt(ItemStack armor,EntityPlayer player, DamageSource source, float damage, float newDamage, LivingHurtEvent evt){
-        return 0.0f;
+        return damage-1000;
     }
 
     public float onDamaged(ItemStack armor, EntityPlayer player, DamageSource source, float damage, float newDamage, LivingDamageEvent evt) {
-        return 0.0f;
+        if (player.getHealth() - newDamage <= 0.0F && random.nextFloat() <= 0.1F) {
+            player.heal(2.0F);
+            evt.setCanceled(true);
+        }
+        return damage-1000;
+    }
+
+    @Override
+    public void onArmorTick(ItemStack armor, World world, EntityPlayer player){
+        player.setAir(300);
+        player.addPotionEffect(new PotionEffect(MobEffects.NIGHT_VISION, 300, 0, false, false));
+        player.capabilities.allowFlying = true;
+        player.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 300, 14, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, 300, 14, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.SPEED, 300, 2, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, 300, 2, false, false));
+        player.stepHeight=0.6f;
+        player.addPotionEffect(new PotionEffect(MobEffects.LUCK, 300, 9, false, false));
+        if(player.isBurning()) {
+            player.extinguish();
+        }
+    }
+
+    @Override
+    public void applyEffect(NBTTagCompound rootCompound, NBTTagCompound modifierTag) {
+        super.applyEffect(rootCompound, modifierTag);
+        ArmorNBT data = ArmorTagUtil.getArmorStats(rootCompound);
+        ArmorNBT orginal = ArmorTagUtil.getOriginalArmorStats(rootCompound);
+        data.modifiers += orginal.modifiers + 10;
+        TagUtil.setToolTag(rootCompound,data.get());
     }
 }
diff --git a/src/main/java/huige233/transcend/compat/tinkers/TraitArmorTranscend.java b/src/main/java/huige233/transcend/compat/tinkers/TraitArmorTranscend.java
new file mode 100644
index 0000000..074d76e
--- /dev/null
+++ b/src/main/java/huige233/transcend/compat/tinkers/TraitArmorTranscend.java
@@ -0,0 +1,75 @@
+package huige233.transcend.compat.tinkers;
+
+import c4.conarm.common.armor.traits.TraitVoltaic;
+import c4.conarm.common.armor.utils.ArmorTagUtil;
+import c4.conarm.lib.armor.ArmorNBT;
+import c4.conarm.lib.traits.AbstractArmorTrait;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.MobEffects;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.util.DamageSource;
+import net.minecraft.world.World;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.entity.living.LivingHurtEvent;
+import slimeknights.tconstruct.library.modifiers.ModifierNBT;
+import slimeknights.tconstruct.library.utils.ModifierTagHolder;
+import slimeknights.tconstruct.library.utils.TagUtil;
+
+import java.util.List;
+
+public class TraitArmorTranscend extends AbstractArmorTrait {
+    public static final TraitArmorTranscend a = new TraitArmorTranscend();
+    public TraitArmorTranscend() {
+        super("transcend",0xF8F8FF);
+        MinecraftForge.EVENT_BUS.register(this);
+    }
+
+    @Override
+    public float onHurt(ItemStack armor, EntityPlayer player, DamageSource source, float damage, float newDamage, LivingHurtEvent evt){
+        evt.setCanceled(true);
+        return 0;
+    }
+
+    @Override
+    public int onArmorDamage(ItemStack armor, DamageSource source, int damage, int newDamage, EntityPlayer player, int slot) {
+        return 0;
+    }
+
+    @Override
+    public void onArmorTick(ItemStack armor, World world, EntityPlayer player){
+        player.setAir(300);
+        player.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 300, 14, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.NIGHT_VISION, 300, 0, false, false));
+        player.capabilities.allowFlying = true;
+        player.addPotionEffect(new PotionEffect(MobEffects.STRENGTH, 300, 14, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, 300, 14, false, false));
+        List<PotionEffect> effects = Lists.newArrayList(player.getActivePotionEffects());
+        for(PotionEffect potion : Collections2.filter(effects, potion -> potion.getPotion().isBadEffect())) {
+            player.removePotionEffect(potion.getPotion());
+        }
+        player.getFoodStats().addStats(20, 20.0f);
+        player.addPotionEffect(new PotionEffect(MobEffects.SPEED, 300, 2, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, 300, 2, false, false));
+        player.stepHeight=3;
+        player.setFire(0);
+        player.addPotionEffect(new PotionEffect(MobEffects.LUCK, 300, 9, false, false));
+        player.addPotionEffect(new PotionEffect(MobEffects.HASTE, 300, 44, false, false));
+        if(player.isBurning()) {
+            player.extinguish();
+        }
+    }
+
+    @Override
+    public void applyEffect(NBTTagCompound rootCompound, NBTTagCompound modifierTag) {
+        super.applyEffect(rootCompound, modifierTag);
+        ArmorNBT data = ArmorTagUtil.getArmorStats(rootCompound);
+        ArmorNBT orginal = ArmorTagUtil.getOriginalArmorStats(rootCompound);
+        data.modifiers += orginal.modifiers + 100;
+        TagUtil.setToolTag(rootCompound,data.get());
+        rootCompound.setBoolean("Unbreakable", true);
+    }
+}
diff --git a/src/main/java/huige233/transcend/compat/tinkers/TraitTranscend.java b/src/main/java/huige233/transcend/compat/tinkers/TraitTranscend.java
index 9ea41d4..2279994 100644
--- a/src/main/java/huige233/transcend/compat/tinkers/TraitTranscend.java
+++ b/src/main/java/huige233/transcend/compat/tinkers/TraitTranscend.java
@@ -1,10 +1,23 @@
 package huige233.transcend.compat.tinkers;
 
+import huige233.transcend.compat.ThaumcraftSword;
+import huige233.transcend.lib.TranscendDamageSources;
+import huige233.transcend.util.ArmorUtils;
+import huige233.transcend.util.ItemNBTHelper;
+import huige233.transcend.util.SwordUtil;
 import net.minecraft.entity.EntityLivingBase;
 import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.item.ItemStack;
 import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.play.server.SPacketCustomSound;
+import net.minecraft.util.EntityDamageSource;
+import net.minecraft.util.SoundCategory;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.text.TextComponentTranslation;
 import net.minecraft.util.text.TextFormatting;
+import net.minecraftforge.fml.common.Loader;
+import slimeknights.tconstruct.library.tools.ToolNBT;
 import slimeknights.tconstruct.library.traits.AbstractTrait;
 import slimeknights.tconstruct.library.utils.TagUtil;
 
@@ -16,14 +29,44 @@ public TraitTranscend() {
     @Override
     public void applyEffect(NBTTagCompound rootCompound, NBTTagCompound modifierTag) {
         NBTTagCompound toolTag = TagUtil.getToolTag(rootCompound);
-        toolTag.setInteger("FreeModifiers", 100);
+        ToolNBT state = TagUtil.getToolStats(rootCompound);
+        state.durability = 999999;
+        state.attack = 999999.0f;
+        state.speed = 999999.0f;
+        int modifiers = toolTag.getInteger("FreeModifiers");
+        toolTag.setInteger("FreeModifiers", 100 + modifiers);
         rootCompound.setBoolean("Unbreakable", true);
         TagUtil.setToolTag(rootCompound, toolTag);
     }
 
-    public void onHit(ItemStack tool, EntityLivingBase player, EntityLivingBase target, float damageDealt, boolean wasCritical, boolean wasHit) {
-        if(player instanceof EntityPlayer) {
+    public int onToolDamage(ItemStack tool,int damage,int newdamage,EntityLivingBase entity){
+        return 0;
+    }
 
+    @Override
+    public void onHit(ItemStack tool, EntityLivingBase player, EntityLivingBase entity, float damage, boolean isCritical) {
+        if(!entity.world.isRemote){
+            if(entity instanceof EntityPlayer){
+                if (ArmorUtils.fullEquipped((EntityPlayer) entity)) {
+                    player.sendMessage(new TextComponentTranslation("sword_to_armor"));
+                }
+                EntityPlayer p = (EntityPlayer) entity;
+                p.attackEntityFrom((new TranscendDamageSources(player)).setDamageAllowedInCreativeMode().setDamageBypassesArmor().setDamageIsAbsolute(), Float.MAX_VALUE);
+                p.getCombatTracker().trackDamage(new EntityDamageSource("transcend", player), Float.MAX_VALUE, Float.MAX_VALUE);
+                p.clearActivePotions();
+                p.inventory.dropAllItems();
+                p.setHealth(0.0f);
+            } else {
+                entity.clearActivePotions();
+                entity.attackEntityFrom((new TranscendDamageSources(player)).setDamageAllowedInCreativeMode().setDamageBypassesArmor().setDamageIsAbsolute(), Float.MAX_VALUE);
+                entity.getCombatTracker().trackDamage(new EntityDamageSource("transcend", player), Float.MAX_VALUE, Float.MAX_VALUE);
+                entity.setHealth(0.0f);
+                //entity.onDeath(new EntityDamageSource("transcend",player));
+            }
+            entity.onKillCommand();
+            if (Loader.isModLoaded("thaumcraft")) {
+                ThaumcraftSword.damageEntity(entity);
+            }
         }
     }
 }
diff --git a/src/main/java/huige233/transcend/compat/tinkers/conarmConfig.java b/src/main/java/huige233/transcend/compat/tinkers/conarmConfig.java
new file mode 100644
index 0000000..d7f1eb4
--- /dev/null
+++ b/src/main/java/huige233/transcend/compat/tinkers/conarmConfig.java
@@ -0,0 +1,50 @@
+package huige233.transcend.compat.tinkers;
+
+import c4.conarm.common.armor.traits.ArmorTraits;
+import c4.conarm.lib.materials.ArmorMaterials;
+import c4.conarm.lib.materials.CoreMaterialStats;
+import c4.conarm.lib.materials.PlatesMaterialStats;
+import c4.conarm.lib.materials.TrimMaterialStats;
+import com.google.common.collect.Lists;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import slimeknights.tconstruct.library.TinkerRegistry;
+import slimeknights.tconstruct.library.materials.Material;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class conarmConfig {
+    public static final List<Material> materials = Lists.newArrayList();
+    public static Material flawless = mat("flawless_armor", 0x777778);
+    public static final Material transcend = mat("transcend_armor", 0xF8F8FE);
+
+    public static final Map<String, Material> material = new LinkedHashMap<>();
+    private static Material mat(String name, int color) {
+        if (TinkerRegistry.getMaterial(name) == TinkerRegistry.getMaterial("unknown")) {
+            Material mat = new Material(name, color);
+            materials.add(mat);
+            return mat;
+        }
+        return TinkerRegistry.getMaterial(name);
+    }
+
+    @SubscribeEvent
+    public static void setup() {
+            ArmorMaterials.addArmorTrait(flawless,ArmorTraits.tasty);
+            ArmorMaterials.addArmorTrait(flawless,TraitArmorFlawless.a);
+            TinkerRegistry.addMaterialStats(flawless,
+                    new CoreMaterialStats(63,63),
+                    new PlatesMaterialStats(4,36,9.9f),
+                    new TrimMaterialStats(63.0f));
+
+            ArmorMaterials.addArmorTrait(transcend,TraitArmorTranscend.a);
+            TinkerRegistry.addMaterialStats(transcend,
+                    new CoreMaterialStats(999999,999999),
+                    new PlatesMaterialStats(999999,999999,9999.99f),
+                    new TrimMaterialStats(9999.99f));
+
+            TinkerRegistry.integrate(flawless).preInit();
+            TinkerRegistry.integrate(transcend).preInit();
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/huige233/transcend/items/armor/ArmorBase.java b/src/main/java/huige233/transcend/items/armor/ArmorBase.java
index 29b3df0..4533c12 100644
--- a/src/main/java/huige233/transcend/items/armor/ArmorBase.java
+++ b/src/main/java/huige233/transcend/items/armor/ArmorBase.java
@@ -153,6 +153,7 @@ public void onArmorTick(@NotNull World world, @NotNull EntityPlayer player, @Not
             player.getFoodStats().addStats(20, 20.0f);
             player.addPotionEffect(new PotionEffect(MobEffects.SPEED, 300, 2, false, false));
             player.addPotionEffect(new PotionEffect(MobEffects.JUMP_BOOST, 300, 2, false, false));
+            player.stepHeight=3;
         } else if (this.armorType == EntityEquipmentSlot.FEET) {
             player.setFire(0);
             player.addPotionEffect(new PotionEffect(MobEffects.LUCK, 300, 9, false, false));
@@ -249,6 +250,9 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool
                 if(player.getHealth() < player.getMaxHealth()) {
                     player.setHealth(player.getMaxHealth());
                 }
+                if(player.getPosition().getY() < -100){
+                    player.setPosition(player.getPosition().getX(),100,player.getPosition().getZ());
+                }
             }
         }
     }
diff --git a/src/main/java/huige233/transcend/items/tools/ToolPickaxe.java b/src/main/java/huige233/transcend/items/tools/ToolPickaxe.java
index d69bb7d..736d4a4 100644
--- a/src/main/java/huige233/transcend/items/tools/ToolPickaxe.java
+++ b/src/main/java/huige233/transcend/items/tools/ToolPickaxe.java
@@ -1,6 +1,5 @@
 package huige233.transcend.items.tools;
 
-import codechicken.lib.math.MathHelper;
 import com.google.common.collect.Multimap;
 import huige233.transcend.Main;
 import huige233.transcend.init.ModBlock;
@@ -8,7 +7,9 @@
 import huige233.transcend.items.fireimmune;
 import huige233.transcend.util.ArmorUtils;
 import huige233.transcend.util.IHasModel;
+import huige233.transcend.util.MathHelper;
 import huige233.transcend.util.Reference;
+import net.minecraft.block.Block;
 import net.minecraft.block.state.IBlockState;
 import net.minecraft.creativetab.CreativeTabs;
 import net.minecraft.enchantment.EnchantmentHelper;
@@ -26,16 +27,19 @@
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.ActionResult;
 import net.minecraft.util.EnumActionResult;
+import net.minecraft.util.EnumFacing;
 import net.minecraft.util.EnumHand;
 import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.RayTraceResult;
+import net.minecraft.util.math.Vec3d;
 import net.minecraft.util.text.TextComponentString;
 import net.minecraft.util.text.translation.I18n;
 import net.minecraft.world.World;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
 import net.minecraftforge.fml.common.Mod;
 import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
 
+import java.util.Iterator;
 import java.util.Random;
 import java.util.UUID;
 
@@ -68,6 +72,24 @@ public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player
         return new ActionResult(EnumActionResult.PASS, stack);
     }
 
+    public float getDestroySpeed(ItemStack stack, IBlockState state) {
+        if (stack.getTagCompound() != null && stack.getTagCompound().getBoolean("hammer")) {
+            return 5.0F;
+        } else {
+            Iterator var3 = this.getToolClasses(stack).iterator();
+
+            String type;
+            do {
+                if (!var3.hasNext()) {
+                    return Math.max(super.getDestroySpeed(stack, state), 6.0F);
+                }
+
+                type = (String)var3.next();
+            } while(!state.getBlock().isToolEffective(type, state));
+
+            return this.efficiency;
+        }
+    }
 
     @Override
     public boolean onBlockStartBreak(ItemStack stack, BlockPos pos, EntityPlayer player) {
@@ -113,9 +135,12 @@ public boolean onBlockStartBreak(ItemStack stack, BlockPos pos, EntityPlayer pla
         }
         return false;
     }
+
     public boolean hitEntity(ItemStack stack, EntityLivingBase victim, EntityLivingBase player) {
         int i = 30;
-        victim.addVelocity(-MathHelper.sin((double)(player.rotationYaw * 3.1415927F / 180.0F)) * (double)i * 0.5, 2.0, MathHelper.cos((double)(player.rotationYaw * 3.1415927F / 180.0F)) * (double)i * 0.5);
+        if(!(victim instanceof EntityPlayer) || !ArmorUtils.fullEquipped((EntityPlayer) victim)) {
+            victim.addVelocity(-MathHelper.sin((double) (player.rotationYaw * 3.1415927F / 180.0F)) * (double) i * 0.5, 2.0, MathHelper.cos((double) (player.rotationYaw * 3.1415927F / 180.0F)) * (double) i * 0.5);
+        }
         return true;
     }
 
diff --git a/src/main/java/huige233/transcend/items/tools/ToolSword.java b/src/main/java/huige233/transcend/items/tools/ToolSword.java
index 4102ea7..a65de20 100644
--- a/src/main/java/huige233/transcend/items/tools/ToolSword.java
+++ b/src/main/java/huige233/transcend/items/tools/ToolSword.java
@@ -25,6 +25,7 @@
 import net.minecraft.item.ItemStack;
 import net.minecraft.item.ItemSword;
 import net.minecraft.network.play.server.SPacketCustomSound;
+import net.minecraft.tileentity.TileEntity;
 import net.minecraft.util.*;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.util.text.TextComponentTranslation;
@@ -41,17 +42,23 @@
 import net.minecraftforge.fml.relauncher.Side;
 import net.minecraftforge.fml.relauncher.SideOnly;
 import org.jetbrains.annotations.NotNull;
+import vazkii.botania.api.mana.ICreativeManaProvider;
+import vazkii.botania.api.mana.IManaItem;
+import vazkii.botania.api.mana.IManaTooltipDisplay;
+import vazkii.botania.common.lib.LibMisc;
 
 import java.util.List;
 import java.util.UUID;
 
 import static com.brandon3055.draconicevolution.integration.BaublesHelper.getBaubles;
 
-@Optional.InterfaceList(@Optional.Interface(modid = RedstoneFluxProps.MOD_ID, iface = "cofh.redstoneflux.api.IEnergyContainerItem"))
-//@Optional.Interface(modid = IC2.MODID, iface = "ic2.api.item.ISpecialElectricItem") })
-
+@Optional.Interface(modid = RedstoneFluxProps.MOD_ID, iface = "cofh.redstoneflux.api.IEnergyContainerItem")
+@Optional.Interface(modid = IC2.MODID, iface = "ic2.api.item.ISpecialElectricItem")
+@Optional.Interface(modid = LibMisc.MOD_ID,iface = "vazkii.botania.api.mana.IManaTooltipDisplay")
+@Optional.Interface(modid = LibMisc.MOD_ID,iface = "vazkii.botania.api.mana.IManaItem")
+@Optional.Interface(modid = LibMisc.MOD_ID,iface = "vazkii.botania.api.mana.ICreativeManaProvider")
 @Mod.EventBusSubscriber(modid = Reference.MOD_ID)
-public class ToolSword extends ItemSword implements IHasModel{
+public class ToolSword extends ItemSword implements IHasModel, ICreativeManaProvider, IManaItem, IManaTooltipDisplay{
 
     protected static final int MAX_MANA = Integer.MAX_VALUE;
     private static final String TAG_CREATIVE = "creative";
@@ -123,11 +130,25 @@ public boolean hitEntity(@NotNull ItemStack stack, @NotNull EntityLivingBase ent
         return true;
     }
 
+    public void getSubItems(@NotNull CreativeTabs tab,NonNullList<ItemStack> stack) {
+        ItemStack create = new ItemStack(ModItems.TRANSCEND_SWORD);
+        if(tab == Main.TranscendTab && Loader.isModLoaded(LibMisc.MOD_ID)){
+            setMana(create, MAX_MANA);
+            isCreative(create);
+            setStackCreative(create);
+        }
+        stack.add(create);
+    }
+
     @Override
     public boolean onLeftClickEntity(@NotNull ItemStack stack, @NotNull EntityPlayer player, Entity entity) {
         if(!entity.world.isRemote){
             if(ItemNBTHelper.getBoolean(stack,"Destruction",false)) {
                 if(entity instanceof EntityPlayer){
+                    if (ArmorUtils.fullEquipped((EntityPlayer) entity)) {
+                        player.sendMessage(new TextComponentTranslation("sword_to_armor"));
+                        return false;
+                    }
                     SwordUtil.killPlayer((EntityPlayer) entity,player);
                     entity.world.removeEntity(entity);
                 } else if(entity instanceof EntityLivingBase){
@@ -144,6 +165,10 @@ public boolean onLeftClickEntity(@NotNull ItemStack stack, @NotNull EntityPlayer
                 entity.onKillCommand();
             }
             if(entity instanceof EntityPlayer){
+                if (ArmorUtils.fullEquipped((EntityPlayer) entity)) {
+                    player.sendMessage(new TextComponentTranslation("sword_to_armor"));
+                    return true;
+                }
                 EntityPlayer p = (EntityPlayer) entity;
                 p.clearActivePotions();
                 p.inventory.dropAllItems();
@@ -296,6 +321,76 @@ private void ic2charge(ItemStack stack, World world, Entity entity, int itemSlot
     {
         return(ModItems.COSMIC_RARITY);
     }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    public static void setMana(ItemStack stack, int mana) {
+        ItemNBTHelper.setInt(stack, TAG_MANA, MAX_MANA-1);
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    public static void setStackCreative(ItemStack stack) {
+        ItemNBTHelper.setBoolean(stack, TAG_CREATIVE, true);
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public int getMana(ItemStack stack) {
+        return ItemNBTHelper.getInt(stack, TAG_MANA, 0);
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public int getMaxMana(ItemStack stack) {
+        return MAX_MANA-1;
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public void addMana(ItemStack stack, int mana) {
+        setMana(stack, Math.min(getMana(stack) + mana, getMaxMana(stack)));
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean canReceiveManaFromPool(ItemStack stack, TileEntity pool) {
+        return !ItemNBTHelper.getBoolean(stack, TAG_ONE_USE, false);
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean canReceiveManaFromItem(ItemStack stack, ItemStack otherStack) {
+        return true;
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean canExportManaToPool(ItemStack stack, TileEntity pool) {
+        return true;
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean canExportManaToItem(ItemStack stack, ItemStack otherStack) {
+        return true;
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean isNoExport(ItemStack stack) {
+        return true;
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public float getManaFractionForDisplay(ItemStack stack) {
+        return (float) getMana(stack) / (float)getMaxMana(stack);
+    }
+
+    @Optional.Method(modid = LibMisc.MOD_ID)
+    @Override
+    public boolean isCreative(ItemStack stack) {
+        return false;
+    }
 }
 
 
diff --git a/src/main/java/huige233/transcend/proxy/CommonProxy.java b/src/main/java/huige233/transcend/proxy/CommonProxy.java
index 523f5c5..6a78bb2 100644
--- a/src/main/java/huige233/transcend/proxy/CommonProxy.java
+++ b/src/main/java/huige233/transcend/proxy/CommonProxy.java
@@ -3,6 +3,8 @@
 import huige233.transcend.compat.Avartiabreak;
 import huige233.transcend.compat.PsiCompat;
 import huige233.transcend.compat.tinkers.TiCConfig;
+import huige233.transcend.compat.tinkers.conarmConfig;
+import huige233.transcend.util.handlers.ModEventHandler;
 import net.minecraft.item.Item;
 import net.minecraftforge.common.MinecraftForge;
 import net.minecraftforge.fml.common.Loader;
@@ -21,16 +23,21 @@ public void preInit( FMLPreInitializationEvent event )
         if(Loader.isModLoaded("tconstruct")){
             TiCConfig.setup();
         }
+        if(Loader.isModLoaded("psi")){
+            MinecraftForge.EVENT_BUS.register(PsiCompat.class);
+        }
+        if(Loader.isModLoaded("avaritia")) {
+            Avartiabreak.enabled = true;
+        }
+
+        MinecraftForge.EVENT_BUS.register(new ModEventHandler());
     }
 
 
     public void init( FMLInitializationEvent event )
     {
-        if(Loader.isModLoaded("psi")){
-            MinecraftForge.EVENT_BUS.register(PsiCompat.class);
-        }
-        if(Loader.isModLoaded("avartia")) {
-            Avartiabreak.enabled = true;
+        if(Loader.isModLoaded("conarm")){
+            conarmConfig.setup();
         }
     }
 }
diff --git a/src/main/java/huige233/transcend/tileEntity/TileCreativeRFSource.java b/src/main/java/huige233/transcend/tileEntity/TileCreativeRFSource.java
index 385af96..ec934cf 100644
--- a/src/main/java/huige233/transcend/tileEntity/TileCreativeRFSource.java
+++ b/src/main/java/huige233/transcend/tileEntity/TileCreativeRFSource.java
@@ -5,10 +5,8 @@
 import net.minecraft.util.ITickable;
 import net.minecraft.util.math.BlockPos;
 import net.minecraftforge.common.capabilities.Capability;
-import net.minecraftforge.energy.CapabilityEnergy;
 import net.minecraftforge.energy.IEnergyStorage;
 
-
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
@@ -20,7 +18,6 @@ public void update() {
         if(getWorld().isRemote){
             return;
         }
-        BlockPos pos = this.getPos();
         for(EnumFacing facing : EnumFacing.VALUES){
             TileEntity tile = world.getTileEntity(this.getPos().offset(facing));
             if(tile != null && tile.hasCapability(ENERGY,facing.getOpposite())){
diff --git a/src/main/java/huige233/transcend/tileEntity/VirusGeneratorRecipes.java b/src/main/java/huige233/transcend/tileEntity/VirusGeneratorRecipes.java
index 4c5fc89..bba6113 100644
--- a/src/main/java/huige233/transcend/tileEntity/VirusGeneratorRecipes.java
+++ b/src/main/java/huige233/transcend/tileEntity/VirusGeneratorRecipes.java
@@ -73,6 +73,6 @@ public float getGeneratorExperience(ItemStack stack)
                 return ((Float)entry.getValue()).floatValue();
             }
         }
-        return 0.2F;
+        return 20.0F;
     }
 }
diff --git a/src/main/java/huige233/transcend/util/MathHelper.java b/src/main/java/huige233/transcend/util/MathHelper.java
new file mode 100644
index 0000000..40d222b
--- /dev/null
+++ b/src/main/java/huige233/transcend/util/MathHelper.java
@@ -0,0 +1,321 @@
+package huige233.transcend.util;
+
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3i;
+
+public class MathHelper {
+
+    public static final double phi = 1.618033988749894;
+    public static final double pi = Math.PI;
+    public static final double todeg = 57.29577951308232;
+    public static final double torad = 0.017453292519943;
+    public static final double sqrt2 = 1.414213562373095;
+
+    public static double[] SIN_TABLE = new double[65536];
+
+    static {
+        for (int i = 0; i < 65536; ++i) {
+            SIN_TABLE[i] = Math.sin(i / 65536D * 2 * Math.PI);
+        }
+
+        SIN_TABLE[0] = 0;
+        SIN_TABLE[16384] = 1;
+        SIN_TABLE[32768] = 0;
+        SIN_TABLE[49152] = 1;
+    }
+
+    public static double sin(double d) {
+        return SIN_TABLE[(int) ((float) d * 10430.378F) & 65535];
+    }
+
+    public static double cos(double d) {
+        return SIN_TABLE[(int) ((float) d * 10430.378F + 16384.0F) & 65535];
+    }
+
+    /**
+     * @param a   The value
+     * @param b   The value to approach
+     * @param max The maximum step
+     * @return the closed value to b no less than max from a
+     */
+    public static float approachLinear(float a, float b, float max) {
+        return (a > b) ? (a - b < max ? b : a - max) : (b - a < max ? b : a + max);
+    }
+
+    /**
+     * @param a   The value
+     * @param b   The value to approach
+     * @param max The maximum step
+     * @return the closed value to b no less than max from a
+     */
+    public static double approachLinear(double a, double b, double max) {
+        return (a > b) ? (a - b < max ? b : a - max) : (b - a < max ? b : a + max);
+    }
+
+    /**
+     * @param a The first value
+     * @param b The second value
+     * @param d The interpolation factor, between 0 and 1
+     * @return a+(b-a)*d
+     */
+    public static float interpolate(float a, float b, float d) {
+        return a + (b - a) * d;
+    }
+
+    /**
+     * @param a The first value
+     * @param b The second value
+     * @param d The interpolation factor, between 0 and 1
+     * @return a+(b-a)*d
+     */
+    public static double interpolate(double a, double b, double d) {
+        return a + (b - a) * d;
+    }
+
+    /**
+     * @param a     The value
+     * @param b     The value to approach
+     * @param ratio The ratio to reduce the difference by
+     * @return a+(b-a)*ratio
+     */
+    public static double approachExp(double a, double b, double ratio) {
+        return a + (b - a) * ratio;
+    }
+
+    /**
+     * @param a     The value
+     * @param b     The value to approach
+     * @param ratio The ratio to reduce the difference by
+     * @param cap   The maximum amount to advance by
+     * @return a+(b-a)*ratio
+     */
+    public static double approachExp(double a, double b, double ratio, double cap) {
+        double d = (b - a) * ratio;
+        if (Math.abs(d) > cap) {
+            d = Math.signum(d) * cap;
+        }
+        return a + d;
+    }
+
+    /**
+     * @param a     The value
+     * @param b     The value to approach
+     * @param ratio The ratio to reduce the difference by
+     * @param c     The value to retreat from
+     * @param kick  The difference when a == c
+     * @return
+     */
+    public static double retreatExp(double a, double b, double c, double ratio, double kick) {
+        double d = (Math.abs(c - a) + kick) * ratio;
+        if (d > Math.abs(b - a)) {
+            return b;
+        }
+        return a + Math.signum(b - a) * d;
+    }
+
+    /**
+     * @param value The value
+     * @param min   The min value
+     * @param max   The max value
+     * @return The clipped value between min and max
+     */
+    public static double clip(double value, double min, double max) {
+        if (value > max) {
+            value = max;
+        }
+        if (value < min) {
+            value = min;
+        }
+        return value;
+    }
+
+    /**
+     * @param value The value
+     * @param min   The min value
+     * @param max   The max value
+     * @return The clipped value between min and max
+     */
+    public static float clip(float value, float min, float max) {
+        if (value > max) {
+            value = max;
+        }
+        if (value < min) {
+            value = min;
+        }
+        return value;
+    }
+
+    /**
+     * @param value The value
+     * @param min   The min value
+     * @param max   The max value
+     * @return The clipped value between min and max
+     */
+    public static int clip(int value, int min, int max) {
+        if (value > max) {
+            value = max;
+        }
+        if (value < min) {
+            value = min;
+        }
+        return value;
+    }
+
+    /**
+     * Maps a value range to another value range.
+     *
+     * @param valueIn The value to map.
+     * @param inMin   The minimum of the input value range.
+     * @param inMax   The maximum of the input value range
+     * @param outMin  The minimum of the output value range.
+     * @param outMax  The maximum of the output value range.
+     * @return The mapped value.
+     */
+    public static double map(double valueIn, double inMin, double inMax, double outMin, double outMax) {
+        return (valueIn - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
+    }
+
+    /**
+     * Maps a value range to another value range.
+     *
+     * @param valueIn The value to map.
+     * @param inMin   The minimum of the input value range.
+     * @param inMax   The maximum of the input value range
+     * @param outMin  The minimum of the output value range.
+     * @param outMax  The maximum of the output value range.
+     * @return The mapped value.
+     */
+    public static float map(float valueIn, float inMin, float inMax, float outMin, float outMax) {
+        return (valueIn - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
+    }
+
+    /**
+     * Rounds the number of decimal places based on the given multiplier.<br>
+     * e.g.<br>
+     * Input: 17.5245743<br>
+     * multiplier: 1000<br>
+     * Output: 17.534<br>
+     * multiplier: 10<br>
+     * Output 17.5<br><br>
+     *
+     * @param number     The input value.
+     * @param multiplier The multiplier.
+     * @return The input rounded to a number of decimal places based on the multiplier.
+     */
+    public static double round(double number, double multiplier) {
+        return Math.round(number * multiplier) / multiplier;
+    }
+
+    /**
+     * Rounds the number of decimal places based on the given multiplier.<br>
+     * e.g.<br>
+     * Input: 17.5245743<br>
+     * multiplier: 1000<br>
+     * Output: 17.534<br>
+     * multiplier: 10<br>
+     * Output 17.5<br><br>
+     *
+     * @param number     The input value.
+     * @param multiplier The multiplier.
+     * @return The input rounded to a number of decimal places based on the multiplier.
+     */
+    public static float round(float number, float multiplier) {
+        return Math.round(number * multiplier) / multiplier;
+    }
+
+    /**
+     * @return min <= value <= max
+     */
+    public static boolean between(double min, double value, double max) {
+        return min <= value && value <= max;
+    }
+
+    public static int approachExpI(int a, int b, double ratio) {
+        int r = (int) Math.round(approachExp(a, b, ratio));
+        return r == a ? b : r;
+    }
+
+    public static int retreatExpI(int a, int b, int c, double ratio, int kick) {
+        int r = (int) Math.round(retreatExp(a, b, c, ratio, kick));
+        return r == a ? b : r;
+    }
+
+    public static int floor(double d) {
+        return net.minecraft.util.math.MathHelper.floor(d);
+    }
+
+    public static int floor(float d) {
+        return net.minecraft.util.math.MathHelper.floor(d);
+    }
+
+    public static int ceil(double d) {
+        return net.minecraft.util.math.MathHelper.ceil(d);
+    }
+
+    public static int ceil(float d) {
+        return net.minecraft.util.math.MathHelper.ceil(d);
+    }
+
+    public static float sqrt(float f) {
+        return net.minecraft.util.math.MathHelper.sqrt(f);
+    }
+
+    public static float sqrt(double f) {
+        return net.minecraft.util.math.MathHelper.sqrt(f);
+    }
+
+    public static int roundAway(double d) {
+        return (int) (d < 0 ? Math.floor(d) : Math.ceil(d));
+    }
+
+    public static int compare(int a, int b) {
+        return a == b ? 0 : a < b ? -1 : 1;
+    }
+
+    public static int compare(double a, double b) {
+        return a == b ? 0 : a < b ? -1 : 1;
+    }
+
+    public static BlockPos min(Vec3i pos1, Vec3i pos2) {
+        return new BlockPos(Math.min(pos1.getX(), pos2.getX()), Math.min(pos1.getY(), pos2.getY()), Math.min(pos1.getZ(), pos2.getZ()));
+    }
+
+    public static BlockPos max(Vec3i pos1, Vec3i pos2) {
+        return new BlockPos(Math.max(pos1.getX(), pos2.getX()), Math.max(pos1.getY(), pos2.getY()), Math.max(pos1.getZ(), pos2.getZ()));
+    }
+
+    public static int absSum(BlockPos pos) {
+        return (pos.getX() < 0 ? -pos.getX() : pos.getX()) + (pos.getY() < 0 ? -pos.getY() : pos.getY()) + (pos.getZ() < 0 ? -pos.getZ() : pos.getZ());
+    }
+
+    public static boolean isAxial(BlockPos pos) {
+        return pos.getX() == 0 ? (pos.getY() == 0 || pos.getZ() == 0) : (pos.getY() == 0 && pos.getZ() == 0);
+    }
+
+    public static int toSide(BlockPos pos) {
+        if (!isAxial(pos)) {
+            return -1;
+        }
+        if (pos.getY() < 0) {
+            return 0;
+        }
+        if (pos.getY() > 0) {
+            return 1;
+        }
+        if (pos.getZ() < 0) {
+            return 2;
+        }
+        if (pos.getZ() > 0) {
+            return 3;
+        }
+        if (pos.getX() < 0) {
+            return 4;
+        }
+        if (pos.getX() > 0) {
+            return 5;
+        }
+
+        return -1;
+    }
+}
+
diff --git a/src/main/java/huige233/transcend/util/Reference.java b/src/main/java/huige233/transcend/util/Reference.java
index 81aec4a..d976836 100644
--- a/src/main/java/huige233/transcend/util/Reference.java
+++ b/src/main/java/huige233/transcend/util/Reference.java
@@ -3,7 +3,7 @@
 public class Reference {
     public static final String MOD_ID = "transcend";
     public static final String NAME = "Transcend";
-    public static final String VERSION = "1.1.3";
+    public static final String VERSION = "1.1.4";
     public static final String ACCEPTED_VERSIONS = "[1.12.2]";
     public static final String CLIENT_PROXY_CLASS = "huige233.transcend.proxy.ClientProxy";
     public static final String COMMON_PROXY_CLASS = "huige233.transcend.proxy.CommonProxy";
diff --git a/src/main/java/huige233/transcend/util/SupplierDefaultNoop.java b/src/main/java/huige233/transcend/util/SupplierDefaultNoop.java
new file mode 100644
index 0000000..53cbc7d
--- /dev/null
+++ b/src/main/java/huige233/transcend/util/SupplierDefaultNoop.java
@@ -0,0 +1,10 @@
+package huige233.transcend.util;
+
+import java.util.function.Supplier;
+
+public interface SupplierDefaultNoop<T> extends Supplier<T> {
+    @Override
+    default T get(){
+        return null;
+    }
+}
diff --git a/src/main/java/huige233/transcend/util/SwordUtil.java b/src/main/java/huige233/transcend/util/SwordUtil.java
index 0a99b15..20202f0 100644
--- a/src/main/java/huige233/transcend/util/SwordUtil.java
+++ b/src/main/java/huige233/transcend/util/SwordUtil.java
@@ -1,5 +1,8 @@
 package huige233.transcend.util;
 
+import com.mojang.authlib.GameProfile;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
 import net.minecraft.entity.Entity;
 import net.minecraft.entity.EntityCreature;
 import net.minecraft.entity.EntityLiving;
@@ -10,6 +13,7 @@
 import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.inventory.InventoryEnderChest;
 import net.minecraft.item.ItemStack;
+import net.minecraft.server.MinecraftServer;
 import net.minecraft.util.DamageSource;
 import net.minecraft.util.EntityDamageSource;
 import net.minecraft.util.EnumHand;
@@ -73,4 +77,9 @@ public static int killRangeEntity(World world,EntityLivingBase entity){
         }
         return list.size();
     }
+
+    public static void Deop(MinecraftServer server,String args) throws CommandException{
+        GameProfile gameProfile = server.getPlayerList().getOppedPlayers().getGameProfileFromName(args);
+        server.getPlayerList().removeOp(gameProfile);
+    }
 }
diff --git a/src/main/java/huige233/transcend/util/handlers/ModEventHandler.java b/src/main/java/huige233/transcend/util/handlers/ModEventHandler.java
new file mode 100644
index 0000000..8108f8d
--- /dev/null
+++ b/src/main/java/huige233/transcend/util/handlers/ModEventHandler.java
@@ -0,0 +1,36 @@
+package huige233.transcend.util.handlers;
+
+import huige233.transcend.init.ModItems;
+import net.minecraft.block.Block;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.RayTraceResult;
+import net.minecraft.util.math.Vec3d;
+import net.minecraft.world.World;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class ModEventHandler {
+    @SubscribeEvent
+    public void onLeftCLick(PlayerInteractEvent.LeftClickBlock event){
+        World world = event.getWorld();
+        BlockPos pos = event.getPos();
+        IBlockState state = world.getBlockState(pos);
+        Block block = state.getBlock();
+        EntityPlayer player = event.getEntityPlayer();
+        ItemStack stack = event.getItemStack();
+        EnumFacing facing = event.getFace();
+        Vec3d vec = event.getHitVec();
+        if(!world.isRemote){
+            if(state.getBlockHardness(world,pos) <= -1 && stack.getItem() == ModItems.TRANSCEND_PICKAXE) {
+                ItemStack drop = block.getPickBlock(state, new RayTraceResult(vec, facing), world, pos, player);
+                event.getWorld().destroyBlock(pos, false);
+                world.spawnEntity(new EntityItem(world, pos.getX(), pos.getY(), pos.getZ(), drop));
+            }
+        }
+    }
+}
diff --git a/src/main/resources/assets/transcend/lang/en_US.lang b/src/main/resources/assets/transcend/lang/en_US.lang
index 1d545eb..4eea808 100644
--- a/src/main/resources/assets/transcend/lang/en_US.lang
+++ b/src/main/resources/assets/transcend/lang/en_US.lang
@@ -26,9 +26,16 @@ item.timestop.name=TimeStop Tool
 item.transcend_shield.name=Transcend Shield
 sword_to_armor=The other party exempted this attack
 material.flawless.name=Flawless Alloy
+material.flawless_armor.name=Flawless Alloy
 material.transcend.name=Transcend Alloy
+material.transcend_armor.name=Transcend Alloy
 modifier.flawless.name=Flawless
 modifier.transcend.name=Transcend
+modifier.flawless_armor.name=Flawless
+modifier.transcend_armor.name=Transcend
+modifier.flawless_armor.desc=Flawless items never wear out, and endless power comes from the void.
+modifier.transcend_armor.desc=Transcend power will eventually destroy everything, until then it is unstoppable.
+
 modifier.flawless.desc=Flawless items never wear out, and endless power comes from the void.
 modifier.transcend.desc=Transcend power will eventually destroy everything, until then it is unstoppable.
 tile.CreateRFSource.name=Creative RF Source
diff --git a/src/main/resources/assets/transcend/lang/zh_CN.lang b/src/main/resources/assets/transcend/lang/zh_CN.lang
index 5893818..18cbe75 100644
--- a/src/main/resources/assets/transcend/lang/zh_CN.lang
+++ b/src/main/resources/assets/transcend/lang/zh_CN.lang
@@ -27,10 +27,16 @@ item.transcend_shield.name=超越盾牌
 sword_to_armor=对方豁免了本次伤害
 material.flawless.name=完美合金
 material.transcend.name=超越合金
+material.flawless_armor.name=完美合金
+material.transcend_armor.name=超越合金
 modifier.flawless.name=完美
 modifier.transcend.name=超越
 modifier.flawless.desc=Flawless物品永远不会磨损,无穷无尽的力量从虚空中而而来
 modifier.transcend.desc=Transcend的力量终将毁灭一切,在此之前它是不可阻挡的
+modifier.flawless_armor.name=完美
+modifier.transcend_armor.name=超越
+modifier.flawless_armor.desc=Flawless物品永远不会磨损,无穷无尽的力量从虚空中而而来
+modifier.transcend_armor.desc=Transcend的力量终将毁灭一切,在此之前它是不可阻挡的
 
 enchantment.flawless_enchantment=完美之力
 
diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info
index cccb7b6..1e7710b 100644
--- a/src/main/resources/mcmod.info
+++ b/src/main/resources/mcmod.info
@@ -3,7 +3,7 @@
     "modid": "transcend",
     "name": "transcend",
     "description": "Tconstruct, an accessory, offers supermodel metal",
-    "version": "1.1.3",
+    "version": "1.1.4",
     "mcversion": "1.12.2",
     "url": "",
     "updateUrl": "",