
Mctittles
Members-
Posts
44 -
Joined
-
Last visited
Everything posted by Mctittles
-
So I figured it out. Here is how to get an input stream from an audio resource: resourceLocation = currentRecord.getRecordResource("records." + myNewRecord.recordName); SoundEventAccessorComposite sound = Minecraft.getMinecraft().getSoundHandler().getSound(resourceLocation); resourceLocationFile = sound.func_148720_g().getSoundPoolEntryLocation(); InputStream inputStream = Minecraft.getMinecraft().getResourceManager().getResource(resourceLocationFile).getInputStream(); Using JAudioTagger I was able to get the song length of an .ogg file. This isn't ideal for most projects because it requires a file location instead of an inputStream. Right now it works for me because all my files are in a resourcePack that everyone has a copy of but in the future I'd like to find a way using only the inputStream: resourceLocation = currentRecord.getRecordResource("records." + myNewRecord.recordName); try { SoundEventAccessorComposite sound = Minecraft.getMinecraft().getSoundHandler().getSound(resourceLocation); resourceLocationFile = sound.func_148720_g().getSoundPoolEntryLocation(); File soundFile = new File("resourcepacks/moreMusic/assets/minecraft/" + resourceLocationFile.getResourcePath()); AudioFile f = AudioFileIO.read(soundFile); AudioHeader audioHeader = f.getAudioHeader(); currentLength=audioHeader.getTrackLength(); PacketHandler.INSTANCE.sendToServer(new ClientSendsServerGetsSongTimes(slotSent, counter, currentLength, this)); } catch (Exception ignored) { ignored.printStackTrace(); }
-
I may have found a way digging deep in the minecraft sound files to get the length from an input stream. But as per my original post I can't seem to get an input stream returned from a resource.
-
Thanks! I'm looking into ogg libraries now. Would be good if I could just use the minecraft soundsystem to get the song length but I don't see any way to do that. The files I'm working with will always be in a resource pack (mod is designed to allow you to add music), but either way I don't see how to convert an InputStream into an audio input stream. Any suggestions?
-
I tried a direct file just to see if the rest of the code would work: try { File file = new File("C:/Users/Mctittles/AppData/Roaming/.minecraft/resourcepacks/moreMusic/assets/minecraft/sounds/01 - Intro-.ogg"); AudioInputStream audioInputStream= AudioSystem.getAudioInputStream(file); AudioFormat format = audioInputStream.getFormat(); long frames = audioInputStream.getFrameLength(); double durationInSeconds = (frames+0.0) / format.getFrameRate(); moreMusic.logger.info("Length in seconds: "+durationInSeconds); } catch (Exception ignored) { moreMusic.logger.info("couldn't get the resource for song length: "+ignored); } Unfortunately I get this error: javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input file So I guess I need two things now. Getting the file from a resource AND getting the length of an ogg file. Bummer...
-
It appears I need to get the file name to put in resourceLocation. The music items for my mod are added via a config and linked to a resourcepack .json file. Anyone know how to get the file name so I can path to it?
-
Made a new post as this topic title was no longer relevant: http://www.minecraftforge.net/forum/index.php/topic,25374.0.html
-
I'd like to get the length of a music file. This is how I currently get the resource for my item: ResourceLocation resourceLocation = currentRecord.getRecordResource("records." + currentRecord.recordName); However that doesn't work in the following: try { AudioInputStream audioInputStream = (AudioInputStream)Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(); AudioFormat format = audioInputStream.getFormat(); long frames = audioInputStream.getFrameLength(); double durationInSeconds = (frames+0.0) / format.getFrameRate(); moreMusic.logger.info("Length in seconds: "+durationInSeconds); } catch (Exception ignored) { moreMusic.logger.info("couldn't get the resource for song length: "+ignored); } I get the error: java.io.FileNotFoundException: minecraft:records.record2 Does anyone know the correct way to do this? I do not know the name of the song file because in this mod users add them with resource packs.
-
Well, I've got part of it figured out for getting the song length: try { AudioInputStream audioInputStream = (AudioInputStream)Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(); AudioFormat format = audioInputStream.getFormat(); long frames = audioInputStream.getFrameLength(); double durationInSeconds = (frames+0.0) / format.getFrameRate(); } Only problem is I don't know what to put in for resourceLocation. Using this does not work: ResourceLocation resourceLocation = currentRecord.getRecordResource(currentRecord.recordName); java.io.FileNotFoundException: minecraft:record2 The sound locations are set in a .json file so maybe that's part of the problem. That and I really don't understand how Minecraft resources work .
-
Yes and that's expected. This mod also allows you to add as much music as you like through a config + resource pack and everyone on the server has the same one. So looking into getting path to file from Resource then how to get sound length of .ogg.
-
I'm modifying code for a multi disc jukebox that is currently using the clients to determine when a song is done and then all clients tell all other clients to play the next track, but that method causes a number of problems like: When someone mutes their volume all tracks skip for everyone. If there is lag involved or a connection hiccup the user with the lag causes tracks to skip. Sometimes messages get doubled and it tries to play a track twice. etc... So logically it would be better if the server was the only one who told people when to change tracks. Only one message and missing files, volume, etc wouldn't interfere with it. Of course since the server doesn't use the soundsystem and actually have the files I was going to use System.currentTimeMillis() to keep track of play time and send the length of the songs to the server whenever the container is changed. Currently I have it successfully changing tracks every 10 seconds and it works great, but the only piece of the puzzle left is to get the length of the song.
-
Good idea, I'll give it a try. I actually changed my code to stop with an identifier cause I couldn't get this to work, but I'll get back to it in a bit as I would prefer not to have to keep track of the previous sound manually.
-
Ahh yes I see. Thanks! Looking through paul's sound system class I can't find anything to get the length either. Looks like I'm going to have to see how to do it in Java against the .ogg directly.
-
I'm trying to get the length of a music sound so I can send it to the server and the server can determine when the sound is done playing. I was looking into getting playingSoundsStopTime from the SoundManger class, however looking through the code I find this is how it's set: this.playingSoundsStopTime.put(s, Integer.valueOf(this.playTime + 20)); So it just adds 20 ticks to it? That doesn't seem correct, otherwise music would always stop playing after 20 ticks...
-
Hello. So what am I doing wrong here? Map<ChunkCoordinates, ISound> mapSoundPositions = ReflectionHelper.getPrivateValue(RenderGlobal.class, Minecraft.getMinecraft().renderGlobal, "field_147593_P", "mapSoundPositions"); ISound sound =mapSoundPositions.get(new ChunkCoordinates(xCoord, yCoord, zCoord)); if (sound != null) { HashBiMap<String, ISound> playingSounds = ReflectionHelper.getPrivateValue(SoundManager.class, SoundManagerInstances.soundManagerInstance, "playingSounds", "field_148629_h"); String soundString= playingSounds.inverse().get(sound); SoundManagerInstances.soundSystemInstance.stop(soundString); } There is definitely a sound at the coordinates but the "sound" is always null.
-
Reflection field name change in minecraft environment?
Mctittles replied to Mctittles's topic in Modder Support
Oh, looks like you can also pass an array of field names so it works in both environments (I think). I'm learning! -
Reflection field name change in minecraft environment?
Mctittles replied to Mctittles's topic in Modder Support
Thanks! That works! I also noticed the ReflectionHelper is overloaded to allow checking by index of field. Was going to try and see if that works as well; might be quicker to use in the future. -
So, I'm modding in Intellig and using this: return ReflectionHelper.getPrivateValue(SoundHandler.class, getSoundHandler(), "sndManager"); Which works fine until I try it in the actual minecraft game. Then I get an error: ReflectionHelper$UnableToAccessFieldException ... java.lang.NoSuchFieldException: sndManager So it seems the field has changed. How do I tell what I should use for a field that will work in minecraft and build in dev? I'm building for 1.7.10-10.13.0.1207 btw.
-
100% chance of spawning a random item in dungeon chest
Mctittles replied to Mctittles's topic in Modder Support
Yea, but I figured since it's so many items (currently over 2000), instead of creating a new array of objects it would be better to access the one that already exists. I did change it to: Item objectReturned = GameData.getItemRegistry().getObject("moreMusic:record" + randomRecordNum); With help from jabelar. -
Grabbing an instance of GameData / iItemRegistry
Mctittles replied to Mctittles's topic in Modder Support
Ok I understand. Thanks, that was exactly what I was looking for originally. I didn't find that method in the class when I checked before. -
Grabbing an instance of GameData / iItemRegistry
Mctittles replied to Mctittles's topic in Modder Support
Well I'm adding hundreds of items through a config and need to grab a random item from a list. To me it seemed better to get the item back (numbered string) this way instead of storing another array of items since one already exists. -
Does forge contain any tools to read/write to region files. For the last step of my mod I need to add a way to insert my items into existing chests in an already generated world. I have the items being generated in new dungeons but we have a lot of land loaded on our server and I'd like to randomly place items in dungeon,mineshaft,temple chests that already exist. (I understand this will fill player chests too)
-
100% chance of spawning a random item in dungeon chest
Mctittles replied to Mctittles's topic in Modder Support
Found a solution. I'm not sure if it's the best one but it works. First in my main preInit I add in new items with a high enough chance so that's all that spawns: ChestGenHooks ChestGenHooksDungeon; WeightedRandomChestContent[] dungeonChestContentArray; ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.DUNGEON_CHEST); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.DUNGEON_CHEST,totalRecordsCreated) ); ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.PYRAMID_DESERT_CHEST); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.PYRAMID_DESERT_CHEST,totalRecordsCreated) ); ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.PYRAMID_JUNGLE_CHEST); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.PYRAMID_JUNGLE_CHEST,totalRecordsCreated) ); ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.STRONGHOLD_CORRIDOR); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.STRONGHOLD_CORRIDOR,totalRecordsCreated) ); ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.STRONGHOLD_LIBRARY); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.STRONGHOLD_LIBRARY,totalRecordsCreated) ); ChestGenHooksDungeon=ChestGenHooks.getInfo(ChestGenHooks.STRONGHOLD_CROSSING); dungeonChestContentArray=ChestGenHooksDungeon.getItems(new Random()); ChestGenHooksDungeon.addItem( new recordRandomChestDungeon(new ItemStack(Items.netherbrick), 1, 10, 99999,dungeonChestContentArray,ChestGenHooks.STRONGHOLD_CROSSING,totalRecordsCreated) ); Item newPressPlate = new pressPlate().setCreativeTab(recordsTab); GameRegistry.registerItem(newPressPlate, "pressPlate"); GameRegistry.addRecipe(new ItemStack(newPressPlate, 1), " A ", "BBB", "CCC", 'A', Items.stick, 'B', Blocks.iron_block, 'C', Blocks.gold_block ); Then in my class I override the forge generateChestContent to fill the chest with what I want the first time it's called, then hack in the default item generation for the rest of the items: package com.cblend.moreMusic; import cpw.mods.fml.common.registry.FMLControlledNamespacedRegistry; import cpw.mods.fml.common.registry.GameData; import net.minecraft.init.Items; import net.minecraft.inventory.IInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.WeightedRandom; import net.minecraft.util.WeightedRandomChestContent; import net.minecraftforge.common.ChestGenHooks; import java.util.Arrays; import java.util.Random; public class recordRandomChestDungeon extends WeightedRandomChestContent { public static final String MINESHAFT_CORRIDOR = "mineshaftCorridor"; public static final String PYRAMID_JUNGLE_CHEST = "pyramidJungleChest"; public static final String STRONGHOLD_CORRIDOR = "strongholdCorridor"; public static final String STRONGHOLD_LIBRARY = "strongholdLibrary"; public static final String STRONGHOLD_CROSSING = "strongholdCrossing"; public static final String DUNGEON_CHEST = "dungeonChest"; public static final String PYRAMID_DESERT_CHEST = "pyramidDesertyChest"; static IInventory lastInventory; static int totalRecords; final WeightedRandomChestContent[] origRandomContent; final String category; public recordRandomChestDungeon(ItemStack itemStackSent, int minChance, int maxChance, int chanceWeight, WeightedRandomChestContent[] sentRandomContent, String categorySent, int totalRecordsSent) { super(itemStackSent, minChance, maxChance, chanceWeight); origRandomContent = Arrays.copyOf(sentRandomContent, sentRandomContent.length); category = categorySent; totalRecords = totalRecordsSent; } @Override protected ItemStack[] generateChestContent(Random random, IInventory newInventory) { if (!newInventory.equals(lastInventory)) { lastInventory = newInventory; int randomMin = 1; int randomMax = 5; if (category == STRONGHOLD_CROSSING || category == STRONGHOLD_LIBRARY || category == STRONGHOLD_CORRIDOR) { randomMin = 5; randomMax = 17; } if (category == PYRAMID_DESERT_CHEST || category == PYRAMID_JUNGLE_CHEST) { randomMin = 3; randomMax = 6; } int randomCount = random.nextInt((randomMax - randomMin) + 1) + randomMin; int randomRecordNum; for (int counter = 1; counter <= randomCount; counter++) { randomRecordNum = random.nextInt((totalRecords - 1) + 1) + 1; FMLControlledNamespacedRegistry<Item> myDataInstance = GameData.getItemRegistry(); Item objectReturned = myDataInstance.getObject("moreMusic:record" + randomRecordNum); if (objectReturned != null) { System.out.println("adding item"); newInventory.setInventorySlotContents(random.nextInt(newInventory.getSizeInventory()), new ItemStack(objectReturned, 1)); } } } int minAmount = 1; int maxAmount = 1; WeightedRandomChestContent weightedrandomchestcontent = (WeightedRandomChestContent) WeightedRandom.getRandomItem(random, origRandomContent); Item currentItem = weightedrandomchestcontent.theItemId.getItem(); switch (category) { case DUNGEON_CHEST: { if (currentItem.equals(Items.iron_ingot) || currentItem.equals(Items.wheat) || currentItem.equals(Items.gunpowder) || currentItem.equals(Items.string) || currentItem.equals(Items.redstone)) { maxAmount = 4; } break; } case STRONGHOLD_CORRIDOR: { if (currentItem.equals(Items.diamond) || currentItem.equals(Items.gold_ingot) || currentItem.equals(Items.bread) || currentItem.equals(Items.apple)) { maxAmount = 3; } else if (currentItem.equals(Items.iron_ingot)) { maxAmount = 5; } else if (currentItem.equals(Items.redstone)) { minAmount = 4; maxAmount = 9; } break; } case STRONGHOLD_CROSSING: { if (currentItem.equals(Items.gold_ingot) || currentItem.equals(Items.bread) || currentItem.equals(Items.apple)) { maxAmount = 3; } else if (currentItem.equals(Items.iron_ingot)) { maxAmount = 5; } else if (currentItem.equals(Items.redstone)) { minAmount = 4; maxAmount = 9; } else if (currentItem.equals(Items.coal)) { minAmount = 3; maxAmount = 8; } break; } case STRONGHOLD_LIBRARY: { if (currentItem.equals(Items.book)) { maxAmount = 3; } else if (currentItem.equals(Items.painting)) { minAmount = 2; maxAmount = 7; } else if (currentItem.equals(Items.enchanted_book)) { minAmount = 1; maxAmount = 5; } break; } case PYRAMID_JUNGLE_CHEST: case PYRAMID_DESERT_CHEST: { if (currentItem.equals(Items.diamond) || currentItem.equals(Items.emerald)) { maxAmount = 3; } else if (currentItem.equals(Items.bone)) { minAmount = 4; maxAmount = 6; } else if (currentItem.equals(Items.rotten_flesh)) { minAmount = 3; maxAmount = 7; } else if (currentItem.equals(Items.iron_ingot)) { maxAmount = 5; } else if (currentItem.equals(Items.gold_ingot)) { minAmount = 2; maxAmount = 7; } else if (currentItem.equals(Items.iron_ingot) || currentItem.equals(Items.wheat) || currentItem.equals(Items.gunpowder) || currentItem.equals(Items.string) || currentItem.equals(Items.redstone)) { maxAmount = 4; } break; } } return ChestGenHooks.generateStacks(random, weightedrandomchestcontent.theItemId, minAmount, maxAmount); } } The items I add will be replaced if the default happens to generate in the same slot, but it's the best I've come up with so far... -
Grabbing an instance of GameData / iItemRegistry
Mctittles replied to Mctittles's topic in Modder Support
Awesome, I found it FMLControlledNamespacedRegistry<Item> myDataInstance = GameData.getItemRegistry(); Item objectReturned = myDataInstance.getObject("moreMusic:record1"); -
Hey all. Just wondering if there is a way to get an instance of GameData so I can look up an item by it's name in iItemRegistry using "findItem(String modId, String name)". I see there is FMLCommonHandler.instance(), and not sure if I can get a GameData instance from that. Thanks!
-
100% chance of spawning a random item in dungeon chest
Mctittles replied to Mctittles's topic in Modder Support
I'm not sure that would help. I would like a guaranteed chance of having 1 to 10 of my custom items in a dungeon chest. Also I would like it in addition to the existing loot instead of replacing it (so I can have up to 10 items). If I lower the percent chance and add all the items there is still a chance that nothing at all will spawn. It also seems that I can't set the amount to spawn this way or add to the chest instead of replacing. Also there is the the fact that I'm adding hundreds of items, so adding via ChestGenHooks for each item seems inefficient.