package blusunrize.immersiveengineering.common.items; import blusunrize.immersiveengineering.ImmersiveEngineering; import blusunrize.immersiveengineering.api.ApiUtils; import blusunrize.immersiveengineering.api.Lib; import blusunrize.immersiveengineering.api.shader.CapabilityShader; import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper; import blusunrize.immersiveengineering.api.shader.CapabilityShader.ShaderWrapper_Item; import blusunrize.immersiveengineering.api.tool.BulletHandler; import blusunrize.immersiveengineering.api.tool.BulletHandler.IBullet; import blusunrize.immersiveengineering.api.tool.ITool; import blusunrize.immersiveengineering.client.models.IOBJModelCallback; import blusunrize.immersiveengineering.common.CommonProxy; import blusunrize.immersiveengineering.common.entities.EntityRevolvershot; import blusunrize.immersiveengineering.common.gui.IESlot; import blusunrize.immersiveengineering.common.items.IEItemInterfaces.IGuiItem; import blusunrize.immersiveengineering.common.util.IEAchievements; import blusunrize.immersiveengineering.common.util.IESounds; import blusunrize.immersiveengineering.common.util.ItemNBTHelper; import blusunrize.immersiveengineering.common.util.Utils; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import blusunrize.immersiveengineering.common.util.network.MessageSpeedloaderSync; import com.google.common.base.Optional; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import net.minecraft.client.renderer.block.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureMap; import net.minecraft.client.resources.I18n; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.Container; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.EnumAction; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.*; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.*; public class ItemRevolver extends ItemUpgradeableTool implements IOBJModelCallback<ItemStack>, ITool, IGuiItem { public ItemRevolver() { super("revolver", 1, "REVOLVER", "normal","speedloader"); } public static UUID speedModUUID = Utils.generateNewUUID(); public HashMap<String, TextureAtlasSprite> revolverIcons = new HashMap<>(); public TextureAtlasSprite revolverDefaultTexture; public void stichRevolverTextures(TextureMap map) { revolverDefaultTexture = ApiUtils.getRegisterSprite(map, "immersiveengineering:revolvers/revolver"); for(String key : specialRevolversByTag.keySet()) if(!key.isEmpty() && !specialRevolversByTag.get(key).tag.isEmpty()) { int split = key.lastIndexOf("_"); if(split<0) split = key.length(); revolverIcons.put(key, ApiUtils.getRegisterSprite(map, "immersiveengineering:revolvers/revolver_"+key.substring(0,split))); } } @Override public int getInternalSlots(ItemStack stack) { return 18+2+1; } @Override public Slot[] getWorkbenchSlots(Container container, ItemStack stack, IInventory invItem) { return new Slot[] { new IESlot.Upgrades(container, invItem,18+0, 80,32, "REVOLVER", stack, true), new IESlot.Upgrades(container, invItem,18+1,100,32, "REVOLVER", stack, true) }; } @Override public boolean canModify(ItemStack stack) { return stack.getItemDamage()!=1; } @Override public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { if(slotChanged) return true; if(oldStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null) && newStack.hasCapability(CapabilityShader.SHADER_CAPABILITY,null)) { ShaderWrapper wrapperOld = oldStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null); ShaderWrapper wrapperNew = newStack.getCapability(CapabilityShader.SHADER_CAPABILITY,null); if(!ItemStack.areItemStacksEqual(wrapperOld.getShaderItem(), wrapperNew.getShaderItem())) return true; } return super.shouldCauseReequipAnimation(oldStack,newStack,slotChanged); } @Override public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) { return new ICapabilityProvider() { ShaderWrapper_Item shaders = new ShaderWrapper_Item("immersiveengineering:revolver", stack); @Override public boolean hasCapability(Capability<?> capability, EnumFacing facing) { return capability== CapabilityShader.SHADER_CAPABILITY; } @Override public <T> T getCapability(Capability<T> capability, EnumFacing facing) { if(capability==CapabilityShader.SHADER_CAPABILITY) return (T)shaders; return null; } }; } @Override @SideOnly(Side.CLIENT) public void getSubItems(Item item, CreativeTabs tab, List list) { for(int i=0;i<2;i++) list.add(new ItemStack(this,1,i)); // for(Map.Entry<String, SpecialRevolver> e : specialRevolversByTag.entrySet()) // { // ItemStack stack = new ItemStack(this,1,0); // applySpecialCrafting(stack, e.getValue()); // this.recalculateUpgrades(stack); // list.add(stack); // } } @Override public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean adv) { if(stack.getItemDamage()!=1) { String tag = getRevolverDisplayTag(stack); if(!tag.isEmpty()) list.add(I18n.format(Lib.DESC_FLAVOUR+"revolver."+tag)); else if(ItemNBTHelper.hasKey(stack, "flavour")) list.add(I18n.format(Lib.DESC_FLAVOUR+"revolver."+ItemNBTHelper.getString(stack, "flavour"))); else if(stack.getItemDamage()==0) list.add(I18n.format(Lib.DESC_FLAVOUR+"revolver")); // ItemStack shader = getShaderItem(stack); // if(shader!=null) // { // list.add(TextFormatting.DARK_GRAY+shader.getDisplayName()); // ShaderCase sCase = ((IShaderItem)shader.getItem()).getShaderCase(shader, shader, getShaderType()); // } } } @Override public String getUnlocalizedName(ItemStack stack) { if(stack.getItemDamage()!=1) { String tag = getRevolverDisplayTag(stack); if(!tag.isEmpty()) return this.getUnlocalizedName()+"."+tag; } return super.getUnlocalizedName(stack); } @Override public boolean isFull3D() { return true; } @Override public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) { Multimap multimap = super.getAttributeModifiers(slot, stack); if(slot==EntityEquipmentSlot.MAINHAND) { double melee = getUpgrades(stack).getDouble("melee"); if(melee != 0) multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getAttributeUnlocalizedName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", melee, 0)); double speed = getUpgrades(stack).getDouble("speed"); if(speed != 0) multimap.put(SharedMonsterAttributes.MOVEMENT_SPEED.getAttributeUnlocalizedName(), new AttributeModifier(speedModUUID, "Weapon modifier", speed, 1)); } return multimap; } @Override public EnumAction getItemUseAction(ItemStack p_77661_1_) { return EnumAction.BOW; } @Override public void onUpdate(ItemStack stack, World world, Entity ent, int slot, boolean inHand) { if(!world.isRemote && stack.getItemDamage()!=1 && ent!=null && ItemNBTHelper.hasKey(stack, "blocked")) { int l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "casings", ent); if(l==0) ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderFill", "tile.piston.in",.3f,3, 1,6,1); l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderFill", ent); if(l==0) ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderClose", "fire.ignite",.6f,5, 1,6,1); l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderClose", ent); if(l==0) ItemNBTHelper.setDelayedSoundsForStack(stack, "cylinderSpin", "note.hat",.1f,5, 5,8,1); l = ItemNBTHelper.handleDelayedSoundsForStack(stack, "cylinderSpin", ent); if(l==0) ItemNBTHelper.remove(stack, "blocked"); } if(!world.isRemote && ItemNBTHelper.hasKey(stack, "cooldown")) { int cooldown = ItemNBTHelper.getInt(stack, "cooldown")-1; if(cooldown<=0) ItemNBTHelper.remove(stack, "cooldown"); else ItemNBTHelper.setInt(stack, "cooldown", cooldown); } } @Override public ActionResult<ItemStack> onItemRightClick(ItemStack revolver, World world, EntityPlayer player, EnumHand hand) { if(!world.isRemote) { if(player.isSneaking() || revolver.getItemDamage()==1) { CommonProxy.openGuiForItem(player, hand==EnumHand.MAIN_HAND? EntityEquipmentSlot.MAINHAND:EntityEquipmentSlot.OFFHAND); return new ActionResult(EnumActionResult.SUCCESS, revolver); } else if(this.getUpgrades(revolver).getBoolean("nerf")) world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 1f, 0.6f); else { if(ItemNBTHelper.getInt(revolver, "cooldown")>0) return new ActionResult(EnumActionResult.PASS, revolver); ItemStack[] bullets = getBullets(revolver); if(isEmpty(revolver)) { for(int i=0; i<player.inventory.getSizeInventory(); i++) { ItemStack loader = player.inventory.getStackInSlot(i); if(loader!=null && loader.getItem() == this && loader.getItemDamage()==1 && !isEmpty(loader)) { int dc = 0; for(ItemStack b : bullets) if(b!=null) { world.spawnEntityInWorld(new EntityItem(world, player.posX,player.posY,player.posZ, b )); dc++; } world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.ITEM_FLINTANDSTEEL_USE, SoundCategory.PLAYERS, .5f, 3f); ItemNBTHelper.setDelayedSoundsForStack(revolver, "casings", "random.successful_hit",.05f,5, dc/2, 8,2); setBullets(revolver, getBullets(loader)); setBullets(loader, new ItemStack[8]); player.inventory.setInventorySlotContents(i, loader); player.inventory.markDirty(); if (player instanceof EntityPlayerMP) ImmersiveEngineering.packetHandler.sendTo(new MessageSpeedloaderSync(i), (EntityPlayerMP)player); ItemNBTHelper.setBoolean(revolver, "blocked", true); return new ActionResult(EnumActionResult.SUCCESS, revolver); } } } if(!ItemNBTHelper.getBoolean(revolver, "blocked")) { if(bullets[0] != null && bullets[0].getItem() instanceof ItemBullet && ItemNBTHelper.hasKey(bullets[0], "bullet")) { String key = ItemNBTHelper.getString(bullets[0], "bullet"); IBullet bullet = BulletHandler.getBullet(key); if(bullet != null) { Vec3d vec = player.getLookVec(); boolean electro = getUpgrades(revolver).getBoolean("electro"); int count = bullet.getProjectileCount(player); if(count == 1) { Entity entBullet = getBullet(player, vec, vec, key, bullets[0], electro); player.worldObj.spawnEntityInWorld(bullet.getProjectile(player, bullets[0], entBullet, electro)); } else for(int i = 0; i < count; i++) { Vec3d vecDir = vec.addVector(player.getRNG().nextGaussian() * .1, player.getRNG().nextGaussian() * .1, player.getRNG().nextGaussian() * .1); Entity entBullet = getBullet(player, vec, vecDir, key, bullets[0], electro); player.worldObj.spawnEntityInWorld(bullet.getProjectile(player, bullets[0], entBullet, electro)); } bullets[0] = bullet.getCasing(bullets[0]); world.playSound(null, player.posX, player.posY, player.posZ, IESounds.revolverFire, SoundCategory.PLAYERS, 1f, 1f); } else world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.BLOCK_NOTE_HAT, SoundCategory.PLAYERS, 1f, 1f); } else world.playSound(null, player.posX, player.posY, player.posZ, SoundEvents.BLOCK_NOTE_HAT, SoundCategory.PLAYERS, 1f, 1f); ItemStack[] cycled = new ItemStack[getBulletSlotAmount(revolver)]; for(int i=1; i<cycled.length; i++) cycled[i-1] = bullets[i]; cycled[cycled.length-1] = bullets[0]; setBullets(revolver, cycled); ItemNBTHelper.setInt(revolver, "cooldown", 10); return new ActionResult(EnumActionResult.SUCCESS, revolver); } } } else if(!player.isSneaking() && revolver.getItemDamage() == 0) return new ActionResult(ItemNBTHelper.getInt(revolver, "cooldown") > 0 ? EnumActionResult.PASS : EnumActionResult.SUCCESS, revolver); return new ActionResult(EnumActionResult.SUCCESS, revolver); } EntityRevolvershot getBullet(EntityPlayer player, Vec3d vecSpawn, Vec3d vecDir, String type, ItemStack stack, boolean electro) { EntityRevolvershot bullet = new EntityRevolvershot(player.worldObj, player, vecDir.xCoord * 1.5, vecDir.yCoord * 1.5, vecDir.zCoord * 1.5, type, stack); bullet.motionX = vecDir.xCoord; bullet.motionY = vecDir.yCoord; bullet.motionZ = vecDir.zCoord; bullet.bulletElectro = electro; return bullet; } public boolean isEmpty(ItemStack stack) { ItemStack[] bullets = getBullets(stack); boolean empty = true; for(ItemStack b : bullets) if(b != null && b.getItem() instanceof ItemBullet && ItemNBTHelper.hasKey(b, "bullet")) empty=false; return empty; } public ItemStack[] getBullets(ItemStack revolver) { ItemStack[] stackList = this.getContainedItems(revolver); ItemStack[] bullets = new ItemStack[getBulletSlotAmount(revolver)]; System.arraycopy(stackList,0, bullets,0, bullets.length); return bullets; } public void setBullets(ItemStack revolver, ItemStack[] bullets) { ItemStack[] stackList = this.getContainedItems(revolver); for(int i=0; i<bullets.length; i++) stackList[i] = bullets[i]; for (int i = bullets.length;i<getBulletSlotAmount(revolver);i++) stackList[i] = null; this.setContainedItems(revolver, stackList); } public int getBulletSlotAmount(ItemStack revolver) { return 8+this.getUpgrades(revolver).getInteger("bullets"); } @Override public NBTTagCompound getUpgradeBase(ItemStack stack) { return ItemNBTHelper.getTagCompound(stack, "baseUpgrades"); } public String getRevolverDisplayTag(ItemStack revolver) { String tag = ItemNBTHelper.getString(revolver, "elite"); if(!tag.isEmpty()) { int split = tag.lastIndexOf("_"); if(split<0) split = tag.length(); return tag.substring(0,split); } return ""; } @SideOnly(Side.CLIENT) @Override public TextureAtlasSprite getTextureReplacement(ItemStack stack, String material) { String tag = ItemNBTHelper.getString(stack, "elite"); if(!tag.isEmpty()) return this.revolverIcons.get(tag); else return this.revolverDefaultTexture; } @SideOnly(Side.CLIENT) @Override public boolean shouldRenderGroup(ItemStack stack, String group) { if(group.equals("revolver_frame")||group.equals("barrel")||group.equals("cosmetic_compensator")) return true; HashSet<String> render = new HashSet<String>(); String tag = ItemNBTHelper.getString(stack, "elite"); String flavour = ItemNBTHelper.getString(stack, "flavour"); if(tag!=null && !tag.isEmpty() && specialRevolversByTag.containsKey(tag)) { SpecialRevolver r = specialRevolversByTag.get(tag); if(r!=null && r.renderAdditions!=null) for(String ss : r.renderAdditions) render.add(ss); } else if(flavour!=null && !flavour.isEmpty() && specialRevolversByTag.containsKey(flavour)) { SpecialRevolver r = specialRevolversByTag.get(flavour); if(r!=null && r.renderAdditions!=null) for(String ss : r.renderAdditions) render.add(ss); } NBTTagCompound upgrades = this.getUpgrades(stack); if(upgrades.getInteger("bullets")>0 && !render.contains("dev_mag")) render.add("player_mag"); if(upgrades.getDouble("melee")>0 && !render.contains("dev_bayonet")) { render.add("bayonet_attachment"); render.add("player_bayonet"); } if(upgrades.getBoolean("electro")) { render.add("player_electro_0"); render.add("player_electro_1"); } return render.contains(group); } @SideOnly(Side.CLIENT) @Override public Optional<TRSRTransformation> applyTransformations(ItemStack stack, String group, Optional<TRSRTransformation> transform) { return transform; } @SideOnly(Side.CLIENT) @Override public Matrix4 handlePerspective(ItemStack stack, TransformType cameraTransformType, Matrix4 perspective) { return perspective; } public String[] compileRender(ItemStack revolver) { HashSet<String> render = new HashSet<String>(); render.add("revolver_frame"); render.add("barrel"); render.add("cosmetic_compensator"); String tag = ItemNBTHelper.getString(revolver, "elite"); String flavour = ItemNBTHelper.getString(revolver, "flavour"); if(tag!=null && !tag.isEmpty() && specialRevolversByTag.containsKey(tag)) { SpecialRevolver r = specialRevolversByTag.get(tag); if(r!=null && r.renderAdditions!=null) for(String ss : r.renderAdditions) render.add(ss); } else if(flavour!=null && !flavour.isEmpty() && specialRevolversByTag.containsKey(flavour)) { SpecialRevolver r = specialRevolversByTag.get(flavour); if(r!=null && r.renderAdditions!=null) for(String ss : r.renderAdditions) render.add(ss); } NBTTagCompound upgrades = this.getUpgrades(revolver); if(upgrades.getInteger("bullets")>0 && !render.contains("dev_mag")) render.add("player_mag"); if(upgrades.getDouble("melee")>0 && !render.contains("dev_bayonet")) { render.add("bayonet_attachment"); render.add("player_bayonet"); } if(upgrades.getBoolean("electro")) { render.add("player_electro_0"); render.add("player_electro_1"); } return render.toArray(new String[render.size()]); } @Override public void onCreated(ItemStack stack, World world, EntityPlayer player) { if(stack==null || player==null) return; if(stack.getItemDamage()==1) return; String uuid = player.getUniqueID().toString(); if(specialRevolvers.containsKey(uuid)) { ArrayList<SpecialRevolver> list = new ArrayList(specialRevolvers.get(uuid)); if(!list.isEmpty()) { list.add(null); String existingTag = ItemNBTHelper.getString(stack, "elite"); if(existingTag.isEmpty()) applySpecialCrafting(stack, list.get(0)); else { int i=0; for(; i<list.size(); i++) if(list.get(i)!=null && existingTag.equals(list.get(i).tag)) break; int next = (i+1)%list.size(); applySpecialCrafting(stack, list.get(next)); } } } this.recalculateUpgrades(stack); } public void applySpecialCrafting(ItemStack stack, SpecialRevolver r) { if(r==null) { ItemNBTHelper.remove(stack, "elite"); ItemNBTHelper.remove(stack, "flavour"); ItemNBTHelper.remove(stack, "baseUpgrades"); return; } if(r.tag!=null && !r.tag.isEmpty()) ItemNBTHelper.setString(stack, "elite", r.tag); if(r.flavour!=null && !r.flavour.isEmpty()) ItemNBTHelper.setString(stack, "flavour", r.flavour); NBTTagCompound baseUpgrades = new NBTTagCompound(); for(Map.Entry<String, Object> e : r.baseUpgrades.entrySet()) { if(e.getValue() instanceof Boolean) baseUpgrades.setBoolean(e.getKey(), (Boolean)e.getValue()); else if(e.getValue() instanceof Integer) baseUpgrades.setInteger(e.getKey(), (Integer)e.getValue()); else if(e.getValue() instanceof Float) baseUpgrades.setDouble(e.getKey(), (Float)e.getValue()); else if(e.getValue() instanceof Double) baseUpgrades.setDouble(e.getKey(), (Double)e.getValue()); else if(e.getValue() instanceof String) baseUpgrades.setString(e.getKey(), (String)e.getValue()); } ItemNBTHelper.setTagCompound(stack, "baseUpgrades", baseUpgrades); } @Override public void removeFromWorkbench(EntityPlayer player, ItemStack stack) { ItemStack[] contents = this.getContainedItems(stack); player.addStat(IEAchievements.craftRevolver); if(contents[18]!=null&&contents[19]!=null) player.addStat(IEAchievements.upgradeRevolver); } public static final ArrayListMultimap<String, SpecialRevolver> specialRevolvers = ArrayListMultimap.create(); public static final Map<String, SpecialRevolver> specialRevolversByTag = new HashMap<String, SpecialRevolver>(); @Override public int getGuiID(ItemStack stack) { return Lib.GUIID_Revolver; } public static class SpecialRevolver { public final String[] uuid; public final String tag; public final String flavour; public final HashMap<String, Object> baseUpgrades; public final String[] renderAdditions; public SpecialRevolver(String[] uuid, String tag, String flavour, HashMap<String, Object> baseUpgrades, String[] renderAdditions) { this.uuid=uuid; this.tag=tag; this.flavour=flavour; this.baseUpgrades=baseUpgrades; this.renderAdditions=renderAdditions; } } @Override public boolean isTool(ItemStack item) { return true; } }