Content: Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Background: Slate Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate Marble
Pattern: Blank Waves Notes Sharp Wood Rockface Leather Honey Vertical Triangles
Welcome to TerraFirmaCraft Forums

Register now to gain access to all of our features. Once registered and logged in, you will be able to contribute to this site by submitting your own content or replying to existing content. You'll be able to customize your profile, receive reputation points as a reward for submitting content, while also communicating with other members via your own private inbox, plus much more! This message will be removed once you have signed in.

  • Announcements

    • Dries007

      ATTENTION Forum Database Breach   03/04/2019

      There has been a breach of our database. Please make sure you change your password (use a password manager, like Lastpass).
      If you used this password anywhere else, change that too! The passwords themselves are stored hashed, but may old accounts still had old, insecure (by today's standards) hashes from back when they where created. This means they can be "cracked" more easily. Other leaked information includes: email, IP, account name.
      I'm trying my best to find out more and keep everyone up to date. Discord (http://invite.gg/TerraFirmaCraft) is the best option for up to date news and questions. I'm sorry for this, but the damage has been done. All I can do is try to make sure it doesn't happen again.
    • Claycorp

      This forum is now READ ONLY!   01/20/2020

      As of this post and forever into the future this forum has been put into READ ONLY MODE. There will be no new posts! A replacement is coming SoonTM . If you wish to stay up-to-date on whats going on or post your content. Please use the Discord or Sub-Reddit until the new forums are running.

      Any questions or comments can be directed to Claycorp on either platform.
Necoxus

[Request] Addon Devlopment Guide

136 posts in this topic

You really need to learn how to search through the codebase better, because literally all I'm doing is linking you line numbers. You are the only addon author who is currently constantly pestering with simple questions because you don't understand, so the notes must make at least some sense because none of the other addon authors are asking questions.

 

Every slot has it's own class. If you can't figure out why something won't go in the slot, maybe you should look at the class for that slot.

 

https://github.com/Deadrik/TFCraft/blob/master/src/Common/com/bioxx/tfc/Containers/Slots/SlotForge.java#L20

 

Your answer for how sand gets its tooltip was found by doing nothing more than using an IDE to search for the word "sand".

 

The item version of sand is called ItemSoil. ItemSoil extends ItemTerraBlock.

 

https://github.com/Deadrik/TFCraft/blob/master/src/Common/com/bioxx/tfc/Items/ItemBlocks/ItemTerraBlock.java#L80

 

Alternatively, TFC_ItemHeat is what contains the whole system for getting the heat color text.

 

https://github.com/Deadrik/TFCraft/blob/master/src/API/com/bioxx/tfc/api/TFC_ItemHeat.java#L10

 

You can use your IDE to see all the locations that call getHeatColor, and from there you would have found ItemTerraBlock.

Edited by Kittychanley
0

Share this post


Link to post
Share on other sites

All of which I found on phone, scanning repo while putting my son to sleep. And I barely understand Java and certainly can't code it.

0

Share this post


Link to post
Share on other sites

I've done extensive searching for anything and everything relating to how server ticks are handled and I've only came across one file from TFC the "ServerTickHandler", and my version of that does nothing to cause issues with that as it is just used to load anvil recipes. So I did more searching to see if there were other files relating to server ticks and I found another file however it was only part of the minecraft code not part of the TFC code making it something irrelevant to me as minecraft doesn't slow down servers like TFC does when players are offline.

 

So the whole point of this is to track down a bug that is causing time to roll backwards whenever my mod is installed on a server and the players go offline. Is there any other place that comes to mind that I'm overlooking that could causing this issue potentially?

 

This also contains more information about the issue: http://terrafirmacraft.com/f/topic/8734-issue-with-calendar-time-in-modded-smp-tfc/

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

onServerWorldTick is a subscribed event, meaning that if you also implement it, it can screw with TFC's implementation of it. That event is used every single in-game tick. You should not be using it to register your anvil recipes. You should be using something that only ever triggers once, like the onLoadWorld event.

0

Share this post


Link to post
Share on other sites

Ok, then I'll get started on redoing that, odd that udary doesn't have a similar problem though as I'm fairly certain that he his doing his the same way as both addons are based on the same template.

 

Thanks for the help Kitty :)

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

Ok so these are the changes that I made in the spoilers below, and according to my tester the problem with the ticks still exists. I did another full search for "onServerWorldTick" and it is no longer coming up in the search so then it has to be something else that's interfering with TFC's server slow down, any ideas on what that could be?

 

Before

@SubscribeEvent 

    public void onServerWorldTick(WorldTickEvent e) 

    { 

        if (e.phase == Phase.START) 

        { 

        if (e.world.provider.dimensionId == 0)

           {

                ModRecipes.initialiseAnvil(); 

           }

        } 

       else if(e.phase == Phase.END)

       {

 

        }

    }

 

After

@SubscribeEvent

    public void onLoadWorld(WorldTickEvent e) 

    { 

        if (e.phase == Phase.START) 

        { 

        if (e.world.provider.dimensionId == 0)

            {

                 ModRecipes.initialiseAnvil(); 

            }

        } 

        else if(e.phase == Phase.END)

        {

 

         }

    }

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

I'm assuming your class is still called "ServerTickHandler" ? Have you tried renaming the class itself?

0

Share this post


Link to post
Share on other sites

No I hadn't renamed it, I just renamed it to WorldLoadHandler so I'll see if that does it.

0

Share this post


Link to post
Share on other sites

Ok even with the class renamed, there is still an issue somewhere. I don't see anymore occurrences of onServerWorldTick anywhere in my addon, so what else could cause such an issue?

 

Thanks for the help again Kitty.

0

Share this post


Link to post
Share on other sites

The event system uses any method with "@SubscribeEvent", it looks for the type of the argument.

You should be using 

net.minecraftforge.event.world.WorldEvent.Load

for example:

 

@SubscribeEvent

public void onWorldLoad(WorldEvent.Load e)

 

The bold parts are important, and shouldn't change.

(Unless you want another event, in which case you should only change the argument. The method name doesn't matter.)

You can also register for the same event multiple times, if you need that for some reason.

 

Class name doesn't matter.

 

I tend to stick with one (or two) event handler class like this:

Two in the case of Client only events, to prevent the server from crashing when it tries to load client events.

public class EventHandler{    @SubscribeEvent    public void onWorldLoad(WorldEvent.Load e)    {        // Do stuff here    }}

To register the event handler do in your @mod class

What eventbus you need to register your handler with depends on what events you'd like to catch. To be safe, register it with both. BUT ONLY ONCE!

@Mod.EventHandlerpublic void preInit(FMLPreInitializationEvent event){    MinecraftForge.EVENT_BUS.register(new EventHandler());    FMLCommonHandler.instance().bus().register(new EventHandler());    if (event.getSide().isClient())    {        MinecraftForge.EVENT_BUS.register(new ClientEventHandler());        FMLCommonHandler.instance().bus().register(new ClientEventHandler());    }}

Also, by using the "if (event.getSide().isClient())" you can avoid having to use a client proxy.

Edited by Dries007
1

Share this post


Link to post
Share on other sites

When I run the debug client config I get this message and it asks me to select a folder however when I select one it just asks the same question again and again. (Select an mcp config dir for the deobfuscator)

 

I've went back and double check everything and it appears to be setup the same as your guide says.

 

Edit: I was using the latest 79.20 that was on github being that it hasn't been released here yet, I'm retrying this with 79.19.

Using .23 I was getting the same issue.

I found the solution here: http://www.minecraftforge.net/forum/index.php?topic=29607.0

Selecting that as the folder allowed me to launch TFC.

 

Might be common knowledge, but I didn't see the solution posted here.

 

As for the server, after attempting to run it the first time, you must go into the server folder and edit eula.txt to agree to the eula.

Edited by Starcitsura
1

Share this post


Link to post
Share on other sites

Just wanted to ask here to see if anyone has any solutions or if anyone has delt with this issue before. So inside of the dev environment everything works correctly textures transition and it all looks great. In the exported mod itself once the player begins using the item and the texture goes to transition the texture becomes broken(purple/black).

 

Icon Code

@Override

@SideOnly(Side.CLIENT)

public void registerIcons(IIconRegister par1IconRegister)

{

this.itemIcon = par1IconRegister.registerIcon("tfcm:CrossBow");

 

CrossBow_loading_0 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_0");

CrossBow_loading_1 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_1");

CrossBow_loading_2 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_2");

CrossBow_loaded = par1IconRegister.registerIcon("tfcm:CrossBow_loaded");

CrossBow_Unloaded = par1IconRegister.registerIcon("tfcm:CrossBow");

}

 

@Override

@SideOnly(Side.CLIENT)

public IIcon getItemIconForUseDuration(int par1)

{

return iconArray[par1];

}

 

@Override

public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining)

{

        if (usingItem != null && usingItem.getItem() == this)

        {

            int j = usingItem.getMaxItemUseDuration() - useRemaining;

            float force = j / getUseSpeed(player);

 

if (force >= 1.80) // Fully loaded

            {

return CrossBow_loaded;

}

else if (force > 0.90)

            {

return CrossBow_loading_2;

            }

else if (force > 0.30)

            {

                return CrossBow_loading_1;

            }

else if (force > 0) // Beginning to load

            {

                return CrossBow_loading_0;

            }

        }

        else if(stack.stackTagCompound != null)

        {

        if(stack.getTagCompound().getBoolean("load") == true)

        {

        return CrossBow_loaded; //While loaded

        }

        else

        {

        return CrossBow_Unloaded;

        }

        }

        

        return getIcon(stack, renderPass);

}

0

Share this post


Link to post
Share on other sites

It might be a silly question, but are you sure all of the texture files are included in the exported mod? Is it possible that they work in development because you put the textures in the bin folder, but you forgot about the actual source code folder that is actually used for compilation outside of dev?

0

Share this post


Link to post
Share on other sites

I checked all of the file names, locations, everything, and I opened the exported jar and it contains the right files. I've been narrowing down the issues and I've came to the conclusion that it has to do with the item class, more specifically the getIcon method in it. My problem is that I lack experience with that method and with items that change textures.I suspect it has something to with how values are passed from one method to another that there is a gap somewhere but if there is I haven't gotten it narrowed down that far.

 

Crossbow Item Class

public class ItemCustomCrossbow extends ItemBow implements ISize

{

private IIcon[] iconArray;

 

public static IIcon CrossBow_loaded;

public static IIcon CrossBow_loading_0;

public static IIcon CrossBow_loading_1;

public static IIcon CrossBow_loading_2;

 

public ItemCustomCrossbow()

{

super();

this.maxStackSize = 1;

this.setMaxDamage(800);

}

 

//Creates NBT tags when item is crafted and stores them to that item stack.

public void onCreated(ItemStack itemStack, World world, EntityPlayer player) 

{

itemStack.stackTagCompound = new NBTTagCompound();

itemStack.stackTagCompound.setBoolean("load", false);

itemStack.stackTagCompound.setInteger("ammo", 0);

itemStack.stackTagCompound.setFloat("forceMult", 0);

 

}

 

//Activates when player right clicks with crossbow.

@Override

public ItemStack onItemRightClick(ItemStack is, World world, EntityPlayer player)

{

//Check to see if player is in creative mode or has enchantments.

boolean hasAmmo = this.hasAmmo(is, player);

 

//To try to prevent crashing, from cheated in crossbows.

if(is.stackTagCompound != null)

{

//Load the crossbow if its unloaded, and has ammo.

if(hasAmmo == true && is.getTagCompound().getBoolean("load") == false)

{

ArrowNockEvent event = new ArrowNockEvent(player, is);

MinecraftForge.EVENT_BUS.post(event);

if (event.isCanceled())

{

return event.result;

}

 

player.setItemInUse(is, this.getMaxItemUseDuration(is));

}

 

//If Crossbow is already loaded

if(is.getTagCompound().getBoolean("load") == true)

{

this.fireCrossbow(is, world, player, is.getTagCompound().getFloat("forceMult"));

}

}

 

return is;

}

 

@Override

public void onPlayerStoppedUsing(ItemStack is, World world, EntityPlayer player, int inUseCount)

{

boolean load = is.getTagCompound().getBoolean("load");

int ammo = is.getTagCompound().getInteger("ammo");

 

int j = this.getMaxItemUseDuration(is) - inUseCount;

float forceMult = j / getUseSpeed(player);

 

if(load == false)

{

if (forceMult < 1.80F)

{

return;

}

if (forceMult > 1.80F)

{

forceMult = 1.80F;

 

switch(ammo)

{

case 1: player.inventory.consumeInventoryItem(ModItems.itemBolt_Copper);

break;

case 2: player.inventory.consumeInventoryItem(ModItems.itemBolt_BismuthBronze);

break;

case 3: player.inventory.consumeInventoryItem(ModItems.itemBolt_Bronze);

break;

case 4: player.inventory.consumeInventoryItem(ModItems.itemBolt_BlackBronze);

break;

case 5: player.inventory.consumeInventoryItem(ModItems.itemBolt_WroughtIron);

break;

case 6: player.inventory.consumeInventoryItem(ModItems.itemBolt_Steel);

break;

case 7: player.inventory.consumeInventoryItem(ModItems.itemBolt_BlackSteel);

break;

case 8: player.inventory.consumeInventoryItem(ModItems.itemBolt_BlueSteel);

break;

case 9: player.inventory.consumeInventoryItem(ModItems.itemBolt_RedSteel);

break;

}

 

is.stackTagCompound.setFloat("forceMult", forceMult);

is.stackTagCompound.setBoolean("load", true);

}

}

}

 

//Checks to see if player has ammo, and what type of ammo he/she has.

//Selects the lowest tier of ammo first.

public boolean hasAmmo(ItemStack is, EntityPlayer player) 

{

is.getTagCompound().getInteger("ammo");

 

for(int i = 0; i <= 8; i++)

{

if(player.inventory.hasItem(ModItems.itemBolt_Copper))

{

is.stackTagCompound.setInteger("ammo", 1);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_BismuthBronze))

{

is.stackTagCompound.setInteger("ammo", 2);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_Bronze))

{

is.stackTagCompound.setInteger("ammo", 3);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_BlackBronze))

{

is.stackTagCompound.setInteger("ammo", 4);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_WroughtIron))

{

is.stackTagCompound.setInteger("ammo", 5);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_Steel))

{

is.stackTagCompound.setInteger("ammo", 6);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_BlackSteel))

{

is.stackTagCompound.setInteger("ammo", 7);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_BlueSteel))

{

is.stackTagCompound.setInteger("ammo", 8);

return true;

}

if(player.inventory.hasItem(ModItems.itemBolt_RedSteel))

{

is.stackTagCompound.setInteger("ammo", 9);

return true;

}

}

return false;

}

 

public void fireCrossbow(ItemStack is, World world, EntityPlayer player, float forceMult)

{

int ammo = is.getTagCompound().getInteger("ammo");

 

float ammoMult = 0;

 

EntityArrow entityarrow = null;

 

switch(ammo)

{

case 1: 

ammoMult = 0.5F; //Copper

entityarrow = new EntityBoltCopper(world, player, 2);

break;

case 2: 

ammoMult = 0.55F; //Bismuth Bronze

entityarrow = new EntityBoltBismuthBronze(world, player, 2);

break;

case 3: 

ammoMult = 0.6F; //Bronze

entityarrow = new EntityBoltBronze(world, player, 2);

break;

case 4: 

ammoMult = 0.65F; //Black Bronze

entityarrow = new EntityBoltBlackBronze(world, player, 2);

break;

case 5: 

ammoMult = 0.7F; //Wrought Iron

entityarrow = new EntityBoltWroughtIron(world, player, 2);

break;

case 6: 

ammoMult = 0.85F; //Steel

entityarrow = new EntityBoltSteel(world, player, 2);

break;

case 7: 

ammoMult = 0.9F; //Black Steel

entityarrow = new EntityBoltBlackSteel(world, player, 2);

break; 

case 8: 

ammoMult = 1.0F; //Blue Steel

entityarrow = new EntityBoltBlueSteel(world, player, 2);

break;

case 9: 

ammoMult = 1.0F; //Red Steel

entityarrow = new EntityBoltRedSteel(world, player, 2);

break;

}

 

entityarrow.setDamage((325.0) * ammoMult);

 

is.damageItem(1, player);

world.playSoundAtEntity(player, "random.bow", 1.0F, 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + forceMult * 0.5F);

if (!world.isRemote)

{

world.spawnEntityInWorld(entityarrow);

}

 

is.getTagCompound().setInteger("ammo", 0);

is.stackTagCompound.setFloat("forceMult", 0);

is.stackTagCompound.setBoolean("load", false);

}

 

public float getUseSpeed(EntityPlayer player)

{

float speed = 60.0f;

ItemStack[] armor = player.inventory.armorInventory;

if(armor[0] != null && armor[0].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[0].getItem()).getWeight(armor[0]).multiplier;

if(armor[1] != null && armor[1].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[1].getItem()).getWeight(armor[1]).multiplier;

if(armor[2] != null && armor[2].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[2].getItem()).getWeight(armor[2]).multiplier;

if(armor[3] != null && armor[3].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[3].getItem()).getWeight(armor[3]).multiplier;

 

return speed;

}

 

@SuppressWarnings({ "unchecked", "rawtypes" })

@Override

public void addInformation(ItemStack is, EntityPlayer player, List arraylist, boolean flag) 

{

ItemTerra.addSizeInformation(is, arraylist);

 

if(is.stackTagCompound != null)

{

if(is.getTagCompound().getBoolean("load") == true)

{

arraylist.add("Condition: Loaded");

}

else

{

arraylist.add("Condition: Unloaded");

}

}

}

 

@Override

public EnumSize getSize(ItemStack is) {

return EnumSize.LARGE;

}

 

@Override

public EnumWeight getWeight(ItemStack is) {

return EnumWeight.HEAVY;

}

 

@Override

public boolean canStack() {

return false;

}

 

@Override

public EnumItemReach getReach(ItemStack is) {

return EnumItemReach.SHORT;

}

 

@Override

@SideOnly(Side.CLIENT)

public void registerIcons(IIconRegister par1IconRegister)

{

this.itemIcon = par1IconRegister.registerIcon("tfcm:CrossBow");

CrossBow_loaded = par1IconRegister.registerIcon("tfcm:CrossBow_loaded");

CrossBow_loading_0 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_0");

CrossBow_loading_1 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_1");

CrossBow_loading_2 = par1IconRegister.registerIcon("tfcm:CrossBow_loading_2");

}

 

@Override

@SideOnly(Side.CLIENT)

public IIcon getItemIconForUseDuration(int par1)

{

return iconArray[par1];

}

 

@SideOnly(Side.CLIENT)

public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining)

{

        if(stack.stackTagCompound != null)

        {

        if(stack.getTagCompound().getBoolean("load") == true)

        {

        return CrossBow_loaded; //While loaded

        }

        else if (usingItem != null && usingItem.getItem() == ModItems.itemCrossBow)

            {

            int j = usingItem.getMaxItemUseDuration() - useRemaining;

                float force = j / getUseSpeed(player);

           

    if (force >= 1.80) // Fully loaded

                {

    return CrossBow_loaded;

    }

    else if (force > 0.90)

                {

    return CrossBow_loading_2;

                }

    else if (force > 0.30)

                {

                    return CrossBow_loading_1;

                }

    else if (force > 0) // Beginning to load

                {

                    return CrossBow_loading_0;

                }

            }

        }

        

        return getIcon(stack, renderPass);

}

}

 

0

Share this post


Link to post
Share on other sites

You don't ever put the different textures in your iconArray.. so getItemIconForUseDuration isn't actually returning anything because there's nothing in that array.

0

Share this post


Link to post
Share on other sites

When I made the crossbow I based it largely off of the longbow class, for the sake of learning something what is assigning the textures to the array in the longbow class?

 

Edit: There isn't anything assigning textures to the array, however that doesn't matter in this instance because that array is completely unnecessary; don't ask me why it is there. Somewhere along the line when I was coding the longbow I just used a different tactic for assigning the textures, even with changing the crossbow to register textures with the string tactic it still has the same problem when its exported.

 

public class ItemCustomLongbow extends ItemBow implements ISize

{

private IIcon[] iconArray;

 

public static IIcon LongBow_pulling_0; // No pull

public static IIcon LongBow_pulling_1; //Right Click Animation

public static IIcon LongBow_pulling_2;

public static IIcon LongBow_pulling_3;

 

public ItemCustomLongbow()

{

super();

this.maxStackSize = 1;

this.setMaxDamage(800);

}

 

public boolean consumeArrowInQuiver(EntityPlayer player, boolean shouldConsume)

{

ItemStack quiver = ((InventoryPlayerTFC) player.inventory).extraEquipInventory[0];

if(quiver != null && quiver.getItem() instanceof ItemQuiver)

{

if(((ItemQuiver)quiver.getItem()).consumeAmmo(quiver, EnumAmmo.ARROW, shouldConsume) != null)

{

return true;

}

}

return false;

}

 

@Override

public ItemStack onItemRightClick(ItemStack is, World world, EntityPlayer player)

{

ArrowNockEvent event = new ArrowNockEvent(player, is);

MinecraftForge.EVENT_BUS.post(event);

if (event.isCanceled())

return event.result;

 

if (player.capabilities.isCreativeMode || player.inventory.hasItem(TFCItems.arrow) || consumeArrowInQuiver(player, false))

player.setItemInUse(is, this.getMaxItemUseDuration(is));

 

return is;

}

 

@Override

public void onPlayerStoppedUsing(ItemStack is, World world, EntityPlayer player, int inUseCount)

{

int j = this.getMaxItemUseDuration(is) - inUseCount;

double drawSpeed = ModOptions.LongbowDrawSpeedMult;

 

ArrowLooseEvent event = new ArrowLooseEvent(player, is, j);

MinecraftForge.EVENT_BUS.post(event);

if (event.isCanceled())

return;

j = event.charge;

 

//Check to see if player is in creative mode or has enchantments.

boolean flag = player.capabilities.isCreativeMode || EnchantmentHelper.getEnchantmentLevel(Enchantment.infinity.effectId, is) > 0;

//First we run the normal ammo check to see if the arrow is in the players inventory

boolean hasAmmo = flag || player.inventory.hasItem(TFCItems.arrow);

boolean hasAmmoInQuiver = false;

//If there was no ammo in the inventory then we need to check if there is a quiver and if there is ammo inside of it.

if(!hasAmmo)

{

hasAmmoInQuiver = consumeArrowInQuiver(player, false);

}

 

if (hasAmmo || hasAmmoInQuiver)

{

float forceMult = j / getUseSpeed(player);

 

if (forceMult < 0.25D * drawSpeed)

return;

 

if (forceMult > 1.00F * drawSpeed)

forceMult = (float) (1.00F * drawSpeed);

 

EntityProjectileTFC entityarrow = new EntityProjectileTFC(world, player, forceMult * 3.0F);

entityarrow.setDamage((forceMult * 275.0));

if (forceMult == 1.00F * drawSpeed)

entityarrow.setIsCritical(true);

 

int k = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, is);

 

if (k > 0)

entityarrow.setDamage(entityarrow.getDamage() + k * 0.5D + 0.5D);

 

int l = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, is);

 

if (l > 0)

entityarrow.setKnockbackStrength(l);

 

if (EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, is) > 0)

entityarrow.setFire(100);

 

is.damageItem(1, player);

world.playSoundAtEntity(player, "random.bow", 1.0F, 1.0F / (itemRand.nextFloat() * 0.4F + 1.2F) + forceMult * 0.5F);

 

if (flag)

entityarrow.canBePickedUp = 2;

else if(hasAmmo)

player.inventory.consumeInventoryItem(TFCItems.arrow);

else if(hasAmmoInQuiver)

consumeArrowInQuiver(player, true);

 

if (!world.isRemote)

world.spawnEntityInWorld(entityarrow);

}

}

 

public float getUseSpeed(EntityPlayer player)

{

float speed = 60.0f;

ItemStack[] armor = player.inventory.armorInventory;

if(armor[0] != null && armor[0].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[0].getItem()).getWeight(armor[0]).multiplier;

if(armor[1] != null && armor[1].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[1].getItem()).getWeight(armor[1]).multiplier;

if(armor[2] != null && armor[2].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[2].getItem()).getWeight(armor[2]).multiplier;

if(armor[3] != null && armor[3].getItem() instanceof ISize)

speed += 20.0f / ((ISize)armor[3].getItem()).getWeight(armor[3]).multiplier;

 

return speed;

}

 

@SuppressWarnings({ "unchecked", "rawtypes" })

@Override

public void addInformation(ItemStack is, EntityPlayer player, List arraylist, boolean flag) 

{

ItemTerra.addSizeInformation(is, arraylist);

}

 

@Override

public EnumSize getSize(ItemStack is)

{

return EnumSize.HUGE;

}

 

@Override

public EnumWeight getWeight(ItemStack is)

{

return EnumWeight.LIGHT;

}

 

@Override

public boolean canStack()

{

return false;

}

 

@Override

public EnumItemReach getReach(ItemStack is) 

{

return EnumItemReach.SHORT;

}

 

@Override

@SideOnly(Side.CLIENT)

public void registerIcons(IIconRegister par1IconRegister)

{

this.itemIcon = par1IconRegister.registerIcon("tfcm:LongBow");

LongBow_pulling_0 = par1IconRegister.registerIcon("tfcm:LongBow_pulling_0");

LongBow_pulling_1 = par1IconRegister.registerIcon("tfcm:LongBow_pulling_1");

LongBow_pulling_2 = par1IconRegister.registerIcon("tfcm:LongBow_pulling_2");

LongBow_pulling_3 = par1IconRegister.registerIcon("tfcm:LongBow_pulling_3");

}

 

@Override

@SideOnly(Side.CLIENT)

public IIcon getItemIconForUseDuration(int par1)

{

return iconArray[par1];

}

 

@Override

public IIcon getIcon(ItemStack stack, int renderPass, EntityPlayer player, ItemStack usingItem, int useRemaining)

{

        if (usingItem != null && usingItem.getItem() == this)

        {

            int j = usingItem.getMaxItemUseDuration() - useRemaining;

            double drawSpeed = ModOptions.LongbowDrawSpeedMult;

            float force = j / getUseSpeed(player);

 

if (force >= 1.00 * drawSpeed) // Fully drawn

            {

return LongBow_pulling_3;

}

else if (force > 0.50 * drawSpeed)

            {

return LongBow_pulling_2;

            }

else if (force > 0.25 * drawSpeed) // Minimum required force to fire

            {

                return LongBow_pulling_1;

            }

else if (force > 0)

            {

                return LongBow_pulling_0;

            }

        }

        return getIcon(stack, renderPass);

}

}

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

In the future it would probably be better to use a website like pastebin or something to post your code, because without the indentations it's almost impossible to read.

0

Share this post


Link to post
Share on other sites

So I've been doing some more digging and playing around with the heat system and heat recipes. I successfully created a recipe that changes one item to another via the fire pit/forge, and I also have some other items that extends ItemTerra and implement ISmeltable much like the ingot item. Those items can be placed in the crucible and melted down to return the correct amount of metal of the type I specify. The whole purpose of the metal item is to be worked on the anvil to yield another item, so should I create a heat recipe to allow it to be placed in the forge and be heated to working temperature? I'm assuming there is a better method than this to specify that the item needs to be allowed into the forge, cause the heat recipe method I theorized has flaws, if there isn't another way it would be nice if it was added to the api.

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

I'm a bit confused at what your problem actually is, and what flaws you would be thinking of. Perhaps you should take a look at the code for the forge slot, as it makes it fairly obvious what the requirements are for an item to be allowed to be put in the input slots of the forge.

0

Share this post


Link to post
Share on other sites

My issue is that I have an item that isn't being allowed into the forge to be heated, I'll look more into the slot thing but from briefing looking at it my item is not ore or food so it shouldn't be a problem, but like I said I'll look further into that.

 

I was basically wondering if there was a simple way of telling the forge "hey this item needs to be heated up.", the problem with using a heat recipe to effectively trick the forge into allowing the item is that I'm for sure what to return for the output of the heat recipe as the ingot molds use lots data to specify what type of metal, how much and its temperature. I think that would just be a pain to code and would be somewhat messy.

 

The reason I say trick the forge is that the objective of the recipe wouldn't be to turn into something else it would be to allow it to be heated to a working temperature.

 

Btw I'm assuming that by using the setMetal(the one that uses a string name, and a value) method the system would automatically get information on working, welding, and melting temperatures which seems to be the case with the crucible but its hard to tell from that alone.

0

Share this post


Link to post
Share on other sites

The forge has a lot more restrictions on input other than just "not food and not ore"

 

Perhaps you should look at the code for knife blades, since it sounds like what you are trying to do is similar to what was done for wrought iron knife blades.

 

If the item is made out of an already existing metal, then you can find the raw entry for that in the heat registry, which already contains info for melting temperature. Working and welding temperature are just percentages of melting temps.

 

Wouldn't the objective of the recipe be for it turn into molten metal? Anything that can be heated to working temperature can obviously be heated to melting temperature, and you need to account for players who will do that.

0

Share this post


Link to post
Share on other sites

What I'm trying to do is basically create an item that works a lot like an ingot, except it can't be placed on the ground. Which is why my item code is largely based off of the ingot code.

 

Thanks for the suggestion I'll look into the knife blades and see if that helps, and I saw the heat registry bit but I hadn't dug into yet so I'll do that. I know that the user error is common and the item would indeed end up melting at some point but I wasn't for sure if the result was handled on my end or if it was an automatic thing.

 

I see the melted metal item class, but I yet to find an example of how such a recipe would be set up as it would have to give the item damage when its created to correspond with the correct amount of units and I'm assuming it would check for a ceramic mold somewhere to see if it actually yields a result or not. As molds are consumed from the forge to create the melted metal item in the game.

 

Edit: After looking into the other part of the forge slot its checking the heat list of information and if there isn't heat information don't allow it, which makes complete sense. Just for clarification the file I'm looking at is: https://github.com/Deadrik/TFCraft/blob/master/src/Common/com/bioxx/tfc/Containers/Slots/SlotForge.java#L20 or should I be looking at another file as to what is allowed into the forge?

Edited by Powerman913717
0

Share this post


Link to post
Share on other sites

That is the correct location. If you look into the tile entity class of the forge, you'll see that it already handles all of the stuff for creating the unshaped melted metal, like checking for the mold and such. You just need to register what metal it melts into, and how many units. All of that is done with a combination of the ISmeltable interface and the HeatRegistry.


Here's the entry where the wrought iron knife blade is registered to turn into an unshaped wrought iron ingot.

 

https://github.com/Deadrik/TFCraft/blob/master/src/Common/com/bioxx/tfc/Core/ItemHeat.java#L254

 

If you look at ItemMiscToolHead you can see how ISmeltable is used to register the metal (and therefore all the heat information) and the units.

 

Don't forget the can weld, can work, etc tooltips too. You can see how we do it in ItemTerra. https://github.com/Deadrik/TFCraft/blob/master/src/Common/com/bioxx/tfc/Items/ItemTerra.java#L189


As a side note, never assume that anything is automatic. Code isn't magic, you have to explicitly tell it to do everything. If you ever want to make an assumption that something is automatic (i.e. somebody else already wrote the code to handle it), you should always thoroughly test it out in game, and actually go find the code that handles it first to confirm that it is.

0

Share this post


Link to post
Share on other sites

Thanks for all of the information I'll get to work on adding those recipes then. :D

 

Also I'll regard that tip in the future. 

0

Share this post


Link to post
Share on other sites

It has come to my attention that some other addons may be having the time reversion bug that my addon experienced a while ago, this is caused by an issue in the addon template created by Bletch.

 

To correct the issue go to your mod file, which the file named after your addon. Scroll down to line 49 which reads as "proxy.registerTickHandler();". Open up that method.

The code inside that method will read as "FMLCommonHandler.instance().bus().register(new ServerTickHandler());", due to the file for the template being named the same thing eclipse can become confused and register TFC's handler again which is what causes the bug.

To correct this simply name your handler something slightly different, and change the line to have your handler. Ex. "FMLCommonHandler.instance().bus().register(new YourServerTickHandler());"

I hope this is helpful, took me a while to track down the issue of this bug. :)

0

Share this post


Link to post
Share on other sites