/** Copyright (C) <2017> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.item; import java.util.HashMap; import java.util.List; import java.util.Map; import net.minecraft.block.Block; import net.minecraft.block.BlockPumpkin; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentTranslation; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.EnumFacing; import net.minecraft.util.StatCollector; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zeldaswordskills.ZSSAchievements; import zeldaswordskills.ZSSMain; import zeldaswordskills.api.entity.ISongTeacher; import zeldaswordskills.api.item.IRightClickEntity; import zeldaswordskills.block.BlockSongInscription; import zeldaswordskills.block.BlockWarpStone; import zeldaswordskills.creativetab.ZSSCreativeTabs; import zeldaswordskills.entity.player.ZSSPlayerSongs; import zeldaswordskills.handler.GuiHandler; import zeldaswordskills.ref.ModInfo; import zeldaswordskills.songs.AbstractZeldaSong; import zeldaswordskills.songs.ZeldaSongs; import zeldaswordskills.util.PlayerUtils; public class ItemInstrument extends BaseModItem implements IRightClickEntity { public static enum Instrument { OCARINA_FAIRY("ocarina_fairy", GuiHandler.GUI_OCARINA, 1), OCARINA_TIME("ocarina_time", GuiHandler.GUI_OCARINA, 5); private final String unlocalizedName; private final int guiId; /** Power level of songs performed with this instrument, 0 having no effect and 5 having maximum effect */ private final int power; private Instrument(String name, int guiId, int power) { this.unlocalizedName = name; this.guiId = guiId; this.power = Math.min(power, 5); } public String getUnlocalizedName() { return unlocalizedName; } public int getGuiId() { return guiId; } /** Returns power level of songs performed with this instrument, from 0 to 10 */ public int getPower() { return power; } } /** Map of teacher name->song taught, retrieved by the teacher's class */ private static final Map<Class<? extends EntityLiving>, Map<String, AbstractZeldaSong>> teachersForClass = new HashMap<Class<? extends EntityLiving>, Map<String, AbstractZeldaSong>>(); public ItemInstrument() { super(); setMaxDamage(0); setHasSubtypes(true); setMaxStackSize(1); setUnlocalizedName("instrument"); setCreativeTab(ZSSCreativeTabs.tabMisc); } public Instrument getInstrument(ItemStack stack) { return Instrument.values()[stack.getItemDamage() % Instrument.values().length]; } /** * Returns {@link Instrument#getPower} for determining effects of the {@link AbstractZeldaSong} */ public int getSongStrength(ItemStack stack) { return getInstrument(stack).getPower(); } @Override public void onCreated(ItemStack stack, World world, EntityPlayer player) { if (getInstrument(stack) == ItemInstrument.Instrument.OCARINA_FAIRY) { player.triggerAchievement(ZSSAchievements.ocarinaCraft); } } @Override public boolean doesSneakBypassUse(World world, BlockPos pos, EntityPlayer player) { Block block = world.getBlockState(pos).getBlock(); return block instanceof BlockWarpStone || block instanceof BlockSongInscription; } @Override public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) { if (world.isRemote) { // instruments have client-side only Guis // check if song to learn was set from entity interaction ZSSPlayerSongs songs = ZSSPlayerSongs.get(player); if (songs.preventSongGui) { songs.preventSongGui = false; // prevent opening GUI this time only } else if (songs.songToLearn != null) { player.openGui(ZSSMain.instance, GuiHandler.GUI_LEARN_SONG, player.worldObj, 0, 0, 0); } else { player.openGui(ZSSMain.instance, getInstrument(stack).getGuiId(), world, 0, 0, 0); } } return stack; } @Override public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing face, float hitX, float hitY, float hitZ) { if (world.isRemote) { if (isScarecrowAt(world, pos) && ZSSPlayerSongs.get(player).canOpenScarecrowGui(true)) { player.openGui(ZSSMain.instance, GuiHandler.GUI_SCARECROW, world, pos.getX(), pos.getY(), pos.getZ()); } else { player.openGui(ZSSMain.instance, getInstrument(stack).getGuiId(), world, 0, 0, 0); } } return true; } @Override public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { return true; } @Override public boolean onRightClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { ISongTeacher.TeachingResult result = null; if (entity instanceof ISongTeacher) { result = ((ISongTeacher) entity).getTeachingResult(stack, player); } else if (!player.isSneaking() && entity.hasCustomName() && teachersForClass.containsKey(entity.getClass())) { Map<String, AbstractZeldaSong> teacherSongs = teachersForClass.get(entity.getClass()); result = new ISongTeacher.TeachingResult(teacherSongs.get(entity.getCustomNameTag()), true, true); } if (result != null) { if (player.worldObj.isRemote && result.songToLearn != null) { ZSSPlayerSongs.get(player).songToLearn = result.songToLearn; if (!result.displayChat) { // don't display default chat messages } else if (ZSSPlayerSongs.get(player).isSongKnown(result.songToLearn)) { PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.ocarina.review", new ChatComponentTranslation(result.songToLearn.getTranslationString())); } else { PlayerUtils.sendTranslatedChat(player, "chat.zss.npc.ocarina.learn", new ChatComponentTranslation(result.songToLearn.getTranslationString())); } } return result.cancel; // If true, skips straight to Item#onItemRightClick } return false; // Entity#interact will determine if Item#onItemRightClick is called } /** * Returns true if the blocks around the position form a scarecrow figure, * assuming that the given position is one of the central blocks (not the 'arms') */ private boolean isScarecrowAt(World world, BlockPos pos) { int i = 0; while (i < 2 && world.getBlockState(pos).getBlock() == Blocks.hay_block) { ++i; pos = pos.up(); } // should now always have the head Block block = world.getBlockState(pos).getBlock(); if (block instanceof BlockPumpkin) { pos = pos.down(); for (int dy = i; dy < 2; ++dy) { if (world.getBlockState(pos.down(dy)).getBlock() != Blocks.hay_block) { return false; } } if (world.getBlockState(pos.east()).getBlock() == Blocks.hay_block && world.getBlockState(pos.west()).getBlock() == Blocks.hay_block) { return true; } if (world.getBlockState(pos.north()).getBlock() == Blocks.hay_block && world.getBlockState(pos.south()).getBlock() == Blocks.hay_block) { return true; } } return false; } @Override public String getUnlocalizedName(ItemStack stack) { return getUnlocalizedName() + "." + Instrument.values()[stack.getItemDamage() % Instrument.values().length].unlocalizedName; } @Override public String[] getVariants() { String[] variants = new String[Instrument.values().length]; for (Instrument type : Instrument.values()) { variants[type.ordinal()] = ModInfo.ID + ":" + type.unlocalizedName; } return variants; } @Override @SideOnly(Side.CLIENT) public void getSubItems(Item item, CreativeTabs tab, List<ItemStack> list) { for (Instrument instrument : Instrument.values()) { list.add(new ItemStack(item, 1, instrument.ordinal())); } } @Override @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, EntityPlayer player, List<String> list, boolean advanced) { list.add(EnumChatFormatting.ITALIC + StatCollector.translateToLocal("tooltip.zss.instrument." + getInstrument(stack).getUnlocalizedName() + ".desc")); } static { Map<String, AbstractZeldaSong> teacherSongs = new HashMap<String, AbstractZeldaSong>(); teacherSongs.put("Guru-Guru", ZeldaSongs.songStorms); teacherSongs.put("Impa", ZeldaSongs.songZeldasLullaby); teacherSongs.put("Malon", ZeldaSongs.songEpona); teacherSongs.put("Saria", ZeldaSongs.songSaria); teachersForClass.put(EntityVillager.class, teacherSongs); } }