Jump to content

[1.9] Guns


Jedispencer21

Recommended Posts

So I have never tried to make a gun before, so what I am wondering is, what would be the best way to make the gun, such as bullets, making guns have a fire and reload speed, being able to customize the guns with different parts, and such. Also with the customizing, each part would supposedly change the look of the gun's model, how would I go about making the model based on what parts are on the gun?

Link to comment
Share on other sites

There are several tutorials for this, namely one on the minecraft forge wiki. This tutorial deals with the gun and bullets. To extend reload time, fire rate, etc, use NBT timers stored on your item that count up or down every tick, and when the user fires, the gun checks to see if the timer has reached the max time, then it will proceed to shoot, otherwise it will do nothing.

Creator of the MyFit, MagiCraft, Tesseract gun, and Papa's Wingeria mod.

Link to comment
Share on other sites

don't forget that you have two options for "bullets" you can actually make an entity that travels through the world like the arrow does or you can just look at what is currently at the target location and damage it.

Current Project: Armerger 

Planned mods: Light Drafter  | Ore Swords

Looking for help getting a mod off the ground? Coding  | Textures

Link to comment
Share on other sites

The only thing is, is that its not an actual crafting table, more like a table with slots that you add the pieces to, and you can remove those pieces as well, and it results with a gun with those parts.

 

Give the gun an inventory using the Capability system and have the table use it.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Create an implementation of

ICapabilitySerializable

that provides an

IItemHandler

instance (probably an

ItemStackHandler

). Override

Item#initCapabilities

to return a new instance of the provider. This gives your item an

IItemHandler

inventory that's stored in memory with the

ItemStack

and not written to NBT until it needs to be (unlike the old way of giving items inventories, which was using an

IInventory

read from and written to NBT every time it was accessed).

 

To get this inventory from an

ItemStack

of your

Item

, use the

ICapabilityProvider#getCapability

method inherited by

ItemStack

.

 

I don't have any examples of this exact use case, but I do have several of my own capabilities in my mod. You can see their APIs here and implementations here.

 

ItemSlingshot

and

ItemLastUseTimeModel

attach the

ILastUseTime

capability to themselves to track their last use time.

 

The

IMaxHealth

capability is attached to all living entities in

CapabilityMaxHealth.EventHandler

to provide bonus max health and used by

ItemMaxHealth{Getter/Setter}

,

BlockMaxHealth{Getter/Setter}

and

CommandMaxHealth{Add/Base/Get/Set}

.

 

The

IPigSpawner

capability is attached to

ItemPigSpawner

by itself and to

Items.CLAY_BALL

in

CapabilityPigSpawner.EventHandler

to allow them to spawn pigs and used by

BlockPigSpawnerRefiller

.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Lets see if I fully understand. What I have to do is create a new class that implements ICapabilitySerializable? And what do you mean provide an IItemHandler instance, would I create a new instance or what? Then in the item class for the gun in the initCapabilities method I return the instance?

Link to comment
Share on other sites

What I have to do is create a new class that implements ICapabilitySerializable?

Yes. This provides your

IItemHandler

instance from

ItemStack#getCapability

and reads from/writes to NBT.

 

And what do you mean provide an IItemHandler instance, would I create a new instance or what?

Yes, either of

ItemStackHandler

or your own

IItemHandler

implementation. You need to create a new instance of this for every instance of your provider (

ICapabilitySerializable

) class.

 

Then in the item class for the gun in the initCapabilities method I return the instance?

Return a new instance of your provider class every time the

Item#initCapabilities

method is called.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Alright, so I have this:

 

 

public class ItemGun extends Item

{

public ItemGun()

{

this.setMaxStackSize(1);

}

 

public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt)

{

return new CapabilitiesGunParts.ProviderGunParts();

}

}

 

public class CapabilitiesGunParts

{

@CapabilityInject(IItemHandler.class)

public static final Capability<IItemHandler> GUN_PART_CAPABILITY = null;

 

public static void register()

{

CapabilityManager.INSTANCE.register(IItemHandler.class, new Capability.IStorage<IItemHandler>()

{

public NBTBase writeNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side)

{

return null;

}

 

public void readNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side, NBTBase nbt)

{

 

}

}, ItemStackHandler.class);

}

 

public static class ProviderGunParts implements ICapabilitySerializable<NBTTagCompound>

{

public static final ItemStackHandler stackHandler = new ItemStackHandler(10); // 10 For the amount of slots.

 

public boolean hasCapability(Capability<?> capability, EnumFacing facing)

{

return capability == GUN_PART_CAPABILITY;

}

 

public <T> T getCapability(Capability<T> capability, EnumFacing facing)

{

if (capability == GUN_PART_CAPABILITY)

{

return (T) stackHandler;

}

 

return null;

}

 

public NBTTagCompound serializeNBT()

{

return (NBTTagCompound) GUN_PART_CAPABILITY.getStorage().writeNBT(GUN_PART_CAPABILITY, stackHandler, (EnumFacing) null);

}

 

public void deserializeNBT(NBTTagCompound nbt)

{

GUN_PART_CAPABILITY.getStorage().readNBT(GUN_PART_CAPABILITY, stackHandler, (EnumFacing) null, nbt);

}

}

}

 

public class CapabilityEvents

{

public void attachCap(AttachCapabilitiesEvent.Item event)

{

if (event.getItem() == CGItems.base_gun)

{

event.addCapability(new ResourceLocation(References.MOD_NAME + ":GunParts"), new CapabilitiesGunParts.ProviderGunParts());

}

}

}

 

 

Firstly, is this correct, and secondly, what would I put in the write/read methods?

Link to comment
Share on other sites

Do not register a

Capability

for

IItemHandler

, Forge already does that.

 

Do not use

AttachCapabilitiesEvent

for your own objects, it's only for external objects.

 

Do not store the

IItemHandler

in a static field, each instance of the provider must have its own instance of

IItemHandler

.

 

The

CapabilitiesGunParts.GUN_PART_CAPABILITY

will be populated with the

IItemHandler

Capability

, but there's no real reason to have the field since you can just use

CapabilityItemHandler.ITEM_HANDLER_CAPABILITY

.

 

Always use the

@Override

annotation on override methods.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

So instead of creating my own capability, I could instead just use CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, and just replace GUN_PART_CAPABILITY like this:

 

 

public class ProviderGunParts implements ICapabilitySerializable<NBTTagCompound>

{

public ItemStackHandler stackHandler = new ItemStackHandler(10);

 

public boolean hasCapability(Capability<?> capability, EnumFacing facing)

{

return capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;

}

 

public <T> T getCapability(Capability<T> capability, EnumFacing facing)

{

if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)

{

return (T) this.stackHandler;

}

 

return null;

}

 

public NBTTagCompound serializeNBT()

{

return (NBTTagCompound) CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getStorage().

                writeNBT(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY,this.stackHandler, (EnumFacing) null);

}

 

public void deserializeNBT(NBTTagCompound nbt)

{

CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getStorage().readNBT(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, this.stackHandler, (EnumFacing) null, nbt);

}

}

 

 

and I do not need to use the AttachCapabilityEvent.Item, I just use the Item#initCapabilities method

Link to comment
Share on other sites

That code looks correct, yes.

 

I'd personally make the

stackHandler

field

private final IItemHandler

rather than

public ItemStackHandler

just to ensure that external code can't replace it, but it's not strictly necessary. You can optionally add a public getter method for it.

 

There's no reason to cast

null

to any type except in very specific circumstances, you only see that in Minecraft's code because the compiler automatically inserts it.

 

Use

Item#initCapabilities

instead of

AttachCapabilitiesEvent.Item

for your own items, yes.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Give your

TileEntity

an

IItemHandler

field for its own inventory. If you want things like hoppers and pipes to interact with it, override the

ICapabilityProvider

methods inherited by

TileEntity

. Make sure you call the super methods if the

Capability

isn't

CapabilityItemHandler.ITEM_HANDLER_CAPABILITY

so capabilities attached from

AttachCapabilitiesEvent.TileEntity

still work.

 

To get the item's inventory, use the

ICapabilityProvider

methods inherited by

ItemStack

.

 

The model will probably require an

IModel

, an

ICustomModelLoader

and an

ItemOverrideList

. I don't know much about the model system myself, I suggest you look at Forge's

ModelDynBucket

or Tinkers' Construct's tool models.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Firstly, how would I go about creating an IItemHandler for the inventory. Also hoppers, pipes, ect. will not be able to interact with this. Secondly, what I want to do with the bench is have, sorta different pages inside of it. Like have a page for editing the gun, and a page for private storage, like and ender chest. So what exactly would I need in terms of the TileEntity, Gui, and Container, for this?

 

Also, aside from the bench, each player should have materials, not actual inventory items, that will be dropped by enemies, and be picked up and added to the materials for the player. Is there a way to make different drops for each player?

Link to comment
Share on other sites

Firstly, how would I go about creating an IItemHandler for the inventory. Also hoppers, pipes, ect. will not be able to interact with this.

Create an

ItemStackHandler

field and initialise it with a new instance. Read it from and write it to NBT like any other field of your

TileEntity

using the

INBTSerializable

methods.

 

If you don't want hopper and pipes to interact with it, don't expose it as a capability. Instead, create a regular getter method so your GUI code can access it.

 

Secondly, what I want to do with the bench is have, sorta different pages inside of it. Like have a page for editing the gun, and a page for private storage, like and ender chest. So what exactly would I need in terms of the TileEntity, Gui, and Container, for this?

I'm not that familiar with the GUI system myself, so I can only provide basic advice. You'll probably need to implement each page as a separate GUI and have buttons/tabs to switch between them. When the player clicks one of these, send a packet to the server to open the new page's GUI.

 

Tinkers' Construct's tinker table GUIs have similar functionality to this (though each tab is for a separate block), consider looking at how that's implemented.

 

Also, aside from the bench, each player should have materials, not actual inventory items, that will be dropped by enemies, and be picked up and added to the materials for the player. Is there a way to make different drops for each player?

You'll want to create your own capability to store the materials and attach it to players using

AttachCapabilitiesEvent.Entity

.

 

I'm not sure exactly how you plan for these materials to be dropped, but you should have access to the player that most recently attacked the entity.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.