Jump to content

imacatlolol

Forge Modder
  • Posts

    274
  • Joined

  • Days Won

    5

Everything posted by imacatlolol

  1. Can't you? I believe the SERVER config type will do exactly what is desired, unless the javadocs are misleading me.
  2. I'll say it again, this time with a little more clarity, override onBlockClicked to activate it when it's left clicked. There's no built-in feature for detecting side collisions in the way you want. Maybe you could have it detect nearby entities and activate that way. Use something like World#getEntitiesWithinAABBExcludingEntity for that.
  3. It's not deactivating because you never do anything in your overridden tick method. Deactivate it there. Override onBlockClicked for activating when it's clicked.
  4. Since playing arbitrary sounds isn't a normally supported feature, there's quite a lot of work to do to make things behave properly. All those "func_######" methods are obfuscated, so the best way to learn what they are is to understand what is being put into them. For example, SoundSource#func_216422_a(float) doesn't have any clear purpose, but by looking at its usages in vanilla code I can find out that it sets the pitch of the sound source. Here's a rough explanation of how sounds are played, based on what you're trying to do: Something creates an instance of an ISound. Most things use an instance of SimpleSound since it contains all sorts of useful properties. This ISound instance is then passed into SoundHandler#play(ISound), which is then passed SoundEngine#play(ISound). This is where the sounds get played. A whole bunch of stuff happens here. Forge runs some event hooks, a few values are validated, subtitles get activated, etc. You can ditch most of this for your system, but I recommend keeping all of it and working around it in order to keep things as close to vanilla as possible. Now, in the else part of the if(sound == SoundHandler.MISSING_SOUND) branch, this is where things get interesting, and confusing. From here, variables and methods are mostly obfuscated and arbitrary, which makes things hard to read. When reverse engineering this process, you may want to copy the code elsewhere and change the variable names as you go to make things easier to understand. Adding comments to obfuscated method calls can help remind you what those methods do when you figure them out. Now here's the biggest hurdle to get over: channelmanager$entry. As you can see, channelmanager$entry is a channel created by the ChannelManager in SoundEngine. In order to play your own arbitrary sounds, you're going to need this ChannelManager instance. Trouble is, the field is private. You have two major options here. Use reflection to make the ChannelManager field in SoundEngine accessible. This isn't too hard, but you should have a very good understanding of how reflection works in Java before doing this since reflection can be dangerous. Use an access transformer to make the field accessible through Forge. I think this is the best solution of the two. Like reflection, you should learn how these work yourself to make sure you fully understand what you're doing, since this tool can also be dangerous. After channelmanager$entry has been configured from data in the ISound and its Sound (confusing, I know) about pitch, location, etc, it's time to actually play the sound! It has to do slightly different things if the sound is being streamed or not. Because we're working with a FileInputStream, I'm going to assume the sound will be streamed. First, AudioStreamManager#func_217917_b(ResourceLocation) is run. This supplies an IAudioStream by turning a ResourceLocation into an OggAudioStream. You can create an OggAudioStream from any InputStream, so try doing that with your FileInputStream! Will it work? No idea! I haven't tested it myself. Then, it plays the IAudioStream through the configured channelmanager$entry by calling SoundSource#func_216433_a(IAudioStream) followed by SoundSource#func_216438_c(). Congratulations, if you did everything right, you will have just played a sound from a file! This is about as close as I can get without directly spoon-feeding code or teaching basic Java. If people who are more experienced than me would like to improve any part of my explanation (or get rid of it, if it's too much hand-holding), it would be much appreciated.
  5. Check out ScreenShotHelper to see how screenshots are made. Thankfully it's a pretty painless process there. You may have to transfer pixel data from a NativeImage to a BufferedImage to do more complex image editing operations, however. I'd need to experiment with it to figure out the exact method for that. As for your concerns: Sadly I don't know of any clean workarounds for texture packs. Shaders and other client-side graphical mods would also be hard to work around. The process for any such workaround would certainly be way out of my skill set. To take a screenshot without the hud, use RenderGameOverlayEvent.Pre filtered by the ALL type and run the code there. It will also work when an overlay screen (like the inventory or pause menu) is being displayed since the event triggers before they render. You may want to use a higher event priority to ensure your code is run before other mods' code.
  6. Just do what @Animefan8888 said. Save the data in the list using a ListNBT with the write method, then read it back using the read method. Don't forget to call markDirty when the data changes in order to have it actually save.
  7. That's not a basic feature provided by Forge to my knowledge, but it is certainly possible. Loading files outside of the jar can be achieved using basic Java. Read up on FileInputStream. In order to use it, you can learn how the game plays sounds by exploring AudioStreamManager and SoundEngine among other related classes.
  8. No, all blocks of a given type share a single instance. Schedule a tick with the world (specifically use World#getPendingBlockTicks and schedule there) when it gets activated and override the tick method in the block to handle deactivation.
  9. You can find keycodes used by LWJGL in the GLFW class now. This has some more info on migrating away from the Keyboard class, if you're interested (not necessary for modding at all, but may be useful for learning about LWJGL).
  10. Doesn't seem to be anything wrong to me... Where are you calling those init functions for these classes?
  11. The block being used by your BlockItem is returning null in its registry object, and therefore "not present", when it goes to register the item. Please show your block registration code.
  12. Did you make sure to include Immersive Portals' dependencies? Check their mod page to make sure you have everything you need.
  13. Well, here's a couple ideas to try: To get rid of the roof bedrock you can override getBedrockRoofHeight to 0 in NetherGenSettings. After that, try making your own CaveWorldCarver that works the same as NetherCaveWorldCarver, but with a higher maximum height so that it breaks through the top. No idea if it'll work like you want, but it's worth trying. Experimentation is generally a good way to go.
  14. You would need to override createChunkGenerator and return your own chunk generator that generates terrain in the way that you want. It's not a simple process, but if you study how vanilla does it then you should get an idea of what to do.
  15. Don't just return true in isReady, having the effect run every tick is probably not what you want. Look at how vanilla does it. If you can't upload the log file here, put it on pastebin or make a github gist and link it here.
  16. That's a bit tougher, I don't actually know the best way to do that myself. One option would be to use inventoryTick; Check if the tags are present, and put them in if not. I'm sure someone who understands the system better than me could come up with a solution that isn't so hacky.
  17. Override performEffect instead of applyAttributesModifiersToEntity. Never use Thread#sleep, use isReady in this case.
  18. Don't create a new ItemStack at the end, use the one you made before.
  19. Don't create your own POWERED property, the creeper entity won't know what to do with it. You should either go back to NBT if that was working before, or use reflection/access transformers to access the actual POWERED property in the creeper entity class.
  20. You can modify mob AI by subscribing to EntityJoinWorldEvent.
  21. Just a heads up, running your addTags method in the item constructor is pointless, unless you're doing it to test it. Anyways, onCreated only fires when an item is crafted, which is why it's not working for you. You want to use fillItemGroup to change the stack in the creative tab.
  22. Oh dang, that's become so second-nature to me that I didn't even notice!
  23. If you want to prevent water from vaporizing, set doesWaterVaporize to false in the dimension's constructor method. Additionally, you should really be using DimensionManager's register methods for the sake of compatibility.
×
×
  • Create New...

Important Information

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