Jump to content

Recommended Posts

Posted

Hello Forge-Community!

 

First of all, I'm an Austrian, so my English isn't the best!

Secondly, I'm a beginner in Java and Forge, please don't judge me too hard! ^^

 

Ok, I wanted to make an dynamic SoundManager which loads the sounds from a custom path respectively custom resource pack which implements IResourcePack!

Everything worked fine, my SoundManager, my ResourcePack and everything else, until I tried to register a sound manager individual for each map.

I tried to give each soundmanager an unique id, here are my classes: (and again, please don't judge me too much for my bad coding skills ^^)

 

My WorldEvents class:

http://pastebin.com/yPEH9QpX

 

My Registry class:

http://pastebin.com/DAzGip3t

 

My WorldRegistry class:

http://pastebin.com/dTRaqURj

 

My SoundManager & SoundFolder class:

http://pastebin.com/Rg1mRXWe

 

And my WorldData class:

http://pastebin.com/iqRyAQxr

 

I coded all myself except the WorldData class for which I needed a tutorial! ^^

Please don't reply with code examples (except there is no alternative)!

Just declare what's wrong if you can help me (like: something in this class must be static or mustn't be final) xD

 

Thank you :P

Posted

Because he would then have to work with zip files
This is not true.

[/qoute]

 

And this way, the resources come with the map, so the user don't have to download and set them manually :D
Vanilla Minecraft already supports bundling resource packs with a map.

 

but then it must be a zipped file, and I don't want this ^^

 

EDIT:

And the sounds must be registered anyway!

That's my actual problem, but im open to everything!

(sry if my first post wasn't declaring this obviously)

Posted

Because the user don't need additional programs to edit content, not beacause he hasn't such programms, but it costs more time for the user ^^

second reason, my code will be much bigger with zip methods if I want my mod to change files in that zip!

But if you recommend this way rather than mine, then I really should do that ^^

 

Ok, now with the sound registry

Register the sounds everytime the user added a new sound

Should I do this with a FileWatcher that notifies the mod to register new sounds?

But then the sounds also registered for other maps :/

Posted

Because the user don't need additional programs to edit content, not beacause he hasn't such programms, but it costs more time for the user ^^
While developing the map the user can use the folder resource pack method and only zip up the resource pack when they distribute the map.

 

Must the user do this by itself, or do i have to make this possible with my mod

 

second reason, my code will be much bigger with zip methods if I want my mod to change files in that zip!
Why do you want to edit the user's resource pack?  :o

 

Haha no, I meant that if the user use the method to change single textures, my mod changes them!

But now I know, that I should do this with resourcepacks too ^^

 

Register the sounds everytime the user added a new sound

Should I do this with a FileWatcher that notifies the mod to register new sounds?

Make the IResourcePack regenerate the generated sounds.json data using an
IResourceManagerReloadListener

, which will tell you when Minecraft reloads the resources. You can then use the file watch API to tell Minecraft to reload resources automatically if a new file is added.

 

Yeah, but the new sounds aren't registered in the forge registry then ^^

(wow, i really should do something for my english, horrible :o)

Posted
You cannot register stuff to registries after preInit. If you must create new SoundEvents, you must restart the game.

Sure, it has worked when I registered them by loading the world ^^

But then they also registered for all worlds, because they registered for the mod and not for single world

And if a world uses a sound with the same name as another, there was a conflict, because soundevents can't registered twice

but I think you already know that haha :D

so i tried to give each world an UUID which the sound also gets

and thats why I let my mod write the sounds JSON, otherwise the user has to write the uuid in front of each sound in the sounds.json :P

Posted

Doing this will cause all kinds of problems because of dynamic ID remapping (IDs change between worlds). If you just add stuff later, the registries might break.

 

Where would these newly created sound events be played from anyways?

 

Ok, didn't know that!

NPCs for example.

The user can set the sound via a GUI.

Or for background music, like in adventure games triggered by a block ^^

 

Maybe I should create a new instance of the existing soundsystem and edit some base classes to mute the old one?

But I think that's not a good idea, mod compatibility is a big problem then!

Although it doesn't matter if my mod is compatible or not, because it should be a single mod anyway.

Ah, maybe I should say that this mod should be a SinglePlayer mod!

I think that's very important information ^^

Posted

I know that's not supported, but it's possible!

I've done it many times!

 

Unfortunately I am not currently at my IDE so I am not 100% sure how you might want to solve this. One idea would be to bypass the SoundEvent registry, but I am not sure how feasible that is.

Maybe i could create an class implementing the IWorldEventListener and create my own

 

public void playSound(@Nullable EntityPlayer player, double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch)
    {
        net.minecraftforge.event.entity.PlaySoundAtEntityEvent event = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAtEntity(player, soundIn, category, volume, pitch);
        if (event.isCanceled() || event.getSound() == null) return;
        soundIn = event.getSound();
        category = event.getCategory();
        volume = event.getVolume();
        pitch = event.getPitch();

        for (int i = 0; i < this.eventListeners.size(); ++i)
        {
            ((IWorldEventListener)this.eventListeners.get(i)).playSoundToAllNearExcept(player, soundIn, category, x, y, z, volume, pitch);
        }
    }

method.

 

I know that this isn't easy, because there are so many other classes needed to play the sound,

but if i could create my own SoundPlayEvent and register the soundevents in an additional map (temporary data, until i unloaded a map and register new soundevents after loading another map)

in my mod, would that work then?

I create a new superclass for my entities that handle the new sound management and let my existing entity inherit from that class!

Maybe this should work ^^

 

EDIT:

I could read thorugh the classes to learn how the sound system is working and then create my OWN CUSTOM sound system, especially for this mod ^^

Posted

After many hours of struggling, i've found this useful method:

 

public void playSound(ISound p_sound)
    {
        if (this.loaded)
        {
            p_sound = net.minecraftforge.client.ForgeHooksClient.playSound(this, p_sound);
            if (p_sound == null) return;

            SoundEventAccessor soundeventaccessor = p_sound.createAccessor(this.sndHandler);
            ResourceLocation resourcelocation = p_sound.getSoundLocation();

            if (soundeventaccessor == null)
            {
                if (UNABLE_TO_PLAY.add(resourcelocation))
                {
                    LOGGER.warn(LOG_MARKER, "Unable to play unknown soundEvent: {}", new Object[] {resourcelocation});
                }
            }
            else
            {
                if (!this.listeners.isEmpty())
                {
                    for (ISoundEventListener isoundeventlistener : this.listeners)
                    {
                        isoundeventlistener.soundPlay(p_sound, soundeventaccessor);
                    }
                }

                if (this.sndSystem.getMasterVolume() <= 0.0F)
                {
                    LOGGER.debug(LOG_MARKER, "Skipped playing soundEvent: {}, master volume was zero", new Object[] {resourcelocation});
                }
                else
                {
                    Sound sound = p_sound.getSound();

                    if (sound == SoundHandler.MISSING_SOUND)
                    {
                        if (UNABLE_TO_PLAY.add(resourcelocation))
                        {
                            LOGGER.warn(LOG_MARKER, "Unable to play empty soundEvent: {}", new Object[] {resourcelocation});
                        }
                    }
                    else
                    {
                        float f3 = p_sound.getVolume();
                        float f = 16.0F;

                        if (f3 > 1.0F)
                        {
                            f *= f3;
                        }

                        SoundCategory soundcategory = p_sound.getCategory();
                        float f1 = this.getClampedVolume(p_sound);
                        float f2 = this.getClampedPitch(p_sound);

                        if (f1 == 0.0F)
                        {
                            LOGGER.debug(LOG_MARKER, "Skipped playing sound {}, volume was zero.", new Object[] {sound.getSoundLocation()});
                        }
                        else
                        {
                            boolean flag = p_sound.canRepeat() && p_sound.getRepeatDelay() == 0;
                            String s = MathHelper.getRandomUuid(ThreadLocalRandom.current()).toString();
                            ResourceLocation resourcelocation1 = sound.getSoundAsOggLocation();

                            if (sound.isStreaming())
                            {
                                this.sndSystem.newStreamingSource(false, s, getURLForSoundResource(resourcelocation1), resourcelocation1.toString(), flag, p_sound.getXPosF(), p_sound.getYPosF(), p_sound.getZPosF(), p_sound.getAttenuationType().getTypeInt(), f);
                                net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.sound.PlayStreamingSourceEvent(this, p_sound, s));
                            }
                            else
                            {
                                this.sndSystem.newSource(false, s, getURLForSoundResource(resourcelocation1), resourcelocation1.toString(), flag, p_sound.getXPosF(), p_sound.getYPosF(), p_sound.getZPosF(), p_sound.getAttenuationType().getTypeInt(), f);
                                net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.client.event.sound.PlaySoundSourceEvent(this, p_sound, s));
                            }

                            LOGGER.debug(LOG_MARKER, "Playing sound {} for event {} as channel {}", new Object[] {sound.getSoundLocation(), resourcelocation1, s});
                            this.sndSystem.setPitch(s, f2);
                            this.sndSystem.setVolume(s, f1);
                            this.sndSystem.play(s);
                            this.playingSoundsStopTime.put(s, Integer.valueOf(this.playTime + 20));
                            this.playingSounds.put(s, p_sound);

                            if (soundcategory != SoundCategory.MASTER)
                            {
                                this.categorySounds.put(soundcategory, s);
                            }

                            if (p_sound instanceof ITickableSound)
                            {
                                this.tickableSounds.add((ITickableSound)p_sound);
                            }
                        }
                    }
                }
            }
        }
    }

 

Could this work?:

1. Create custom SoundManager and inherit from the existing one

2. Get the most important fields via Java Reflection (because they're all private)

3. Override the playsound method

 

Maybe this should do it! ^^

Posted

I see opportunity here:

 

            p_sound = net.minecraftforge.client.ForgeHooksClient.playSound(this, p_sound);
            if (p_sound == null) return;

 

That thar is a Forge hook. You can write an event handler to do almost anything with that incoming p-sound, and then return null so that the vanilla method quits without doing anything else.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Posted

Yeah, I wanted to do so but I thought that would be way too insecure!

What if my sound overlaps another playing sounds and causes some problems?

I could use the SoundSystem in the SoundManager, but is this safe enough?

 

this.sndSystem.newStreamingSource(false, s, getURLForSoundResource(resourcelocation1), resourcelocation1.toString(), flag, p_sound.getXPosF(), p_sound.getYPosF(), p_sound.getZPosF(), p_sound.getAttenuationType().getTypeInt(), f);

 

For example!

 

When i was digging deeper, I found this one:

class SoundSystemStarterThread extends SoundSystem
    {
        private SoundSystemStarterThread()
        {
        }

        public boolean playing(String p_playing_1_)
        {
            synchronized (SoundSystemConfig.THREAD_SYNC)
            {
                if (this.soundLibrary == null)
                {
                    return false;
                }
                else
                {
                    Source source = (Source)this.soundLibrary.getSources().get(p_playing_1_);
                    return source == null ? false : source.playing() || source.paused() || source.preLoad;
                }
            }
        }
    }

 

But Threads are not my friends!

I know almost nothing about threads.

Doesn't matter how often I've read something about them!

Posted

How did I know that there will be a thread exception?

 

http://pastebin.com/pb8U8i2m

 

First time playing the sound worked just fine, but then:

 

[05:44:04] [Thread-14/ERROR]: Error in class 'CodecJOrbis'
[05:44:04] [Thread-14/ERROR]: Unable to acquire inputstream in method 'initialize'.
[05:44:04] [Thread-14/WARN]: ERROR MESSAGE:
[05:44:04] [Thread-14/INFO]: C:\Users\Rexozz\Desktop\forge 1.10 modding\PixelEngine\saves\Neue Welt\mapres\sounds\sound\block.grass.step.ogg (Das System kann die angegebene Datei nicht finden)
[05:44:04] [Thread-14/WARN]: STACK TRACE:
[05:44:04] [Thread-14/INFO]: java.io.FileInputStream.open0(Native Method)
[05:44:04] [Thread-14/INFO]: java.io.FileInputStream.open(Unknown Source)
[05:44:04] [Thread-14/INFO]: java.io.FileInputStream.<init>(Unknown Source)
[05:44:04] [Thread-14/INFO]: java.io.FileInputStream.<init>(Unknown Source)
[05:44:04] [Thread-14/INFO]: sun.net.www.protocol.file.FileURLConnection.connect(Unknown Source)
[05:44:04] [Thread-14/INFO]: sun.net.www.protocol.file.FileURLConnection.getInputStream(Unknown Source)
[05:44:04] [Thread-14/INFO]: paulscode.sound.codecs.CodecJOrbis.initialize(CodecJOrbis.java:281)
[05:44:04] [Thread-14/INFO]: paulscode.sound.libraries.LibraryLWJGLOpenAL.loadSound(LibraryLWJGLOpenAL.java:392)
[05:44:04] [Thread-14/INFO]: paulscode.sound.libraries.LibraryLWJGLOpenAL.newSource(LibraryLWJGLOpenAL.java:640)
[05:44:04] [Thread-14/INFO]: paulscode.sound.SoundSystem.CommandNewSource(SoundSystem.java:1800)
[05:44:04] [Thread-14/INFO]: paulscode.sound.SoundSystem.CommandQueue(SoundSystem.java:2415)
[05:44:04] [Thread-14/INFO]: paulscode.sound.CommandThread.run(CommandThread.java:121)

 

This is where the sound plays:

http://pastebin.com/gUsSSujt

Posted

Haha, it works now, I just wonder how long!

Are there any improvements that I could do?

 

PacketClass:

http://pastebin.com/KvCqVDM7

 

PlaySound in PEEntityCreature:

public class PEEntityCreature extends EntityCreature implements INpc{
public PEEntityCreature(World worldIn) {
	super(worldIn);
}

@Override
public void playSound(SoundEvent sound, float volume, float pitch) {
        if (!this.isSilent()){
        	if(sound.getSoundName().equals(this.getDeathSound().getSoundName())||sound.getSoundName().equals(this.getHurtSound().getSoundName()))
            	PacketHandler.sendToAllAround(new C00PacketSendSound(new ImplSound(sound,this.getSoundCategory(),volume,pitch,this.posX,this.posY,this.posZ)), this.dimension, this.posX, this.posY, this.posZ, volume > 1.0F ? (double)(16.0F * volume) : 16.0D);
        	else
        		super.playSound(sound, volume, pitch);
        }
    }
}

Guest
This topic is now closed to further replies.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Thank you so much! I didnt see it in the log😭😭  
    • So im completely new to modding in general, i have some experience in Behavior packs in minecraft bedrock and i would like to modify entities stats and attributes like in a behavior pack (health, damage, speed, xp drop...). The problem is that i cant find any information online on how to do that, and I have no clue on what to do and where to start. I am currently modding in 1.20.4 with IntelliJ if that helps. My final objective is to buff mobs health and damage (double it for exemple), but since there is no entity file anywhere i don't know how to change it... 😢
    • Unlock an Instant $100 OFF with the Exclusive Temu Coupon Code ALF401700! Whether you're a first-time shopper or a loyal returning customer, this verified Temu promo code ALF401700 is your gateway to incredible savings on thousands of products. By applying code ALF401700 at checkout, you’ll receive a guaranteed $100 discount on your purchase, plus enjoy additional savings of up to 50% OFF on selected items. This special coupon is designed to maximize your discounts, making your shopping experience at Temu more affordable than ever. Why Choose Temu Coupon Code ALF401700 in 2025? First-Time Shoppers: Score a massive 50% off your first order plus a flat $100 OFF using promo code ALF401700. Returning Customers: Don’t miss out! Use ALF401700 to claim a generous $100 OFF on your next purchase. Massive Clearance Sales: With Temu’s ongoing 2025 clearance events, this code unlocks up to 90% OFF on select deals. Global Reach: Whether you shop from the USA, Canada, Europe, Asia, or beyond, Temu coupon ALF401700 works worldwide. 2025’s Top Temu Discounts Powered by ALF401700: Temu $100 OFF New User Promo — ALF401700 Temu Exclusive Discount for Returning Shoppers — ALF401700 Memorial Day Special: $100 OFF Using ALF401700 Country-Specific Offers: USA, Japan, Mexico, Chile, Colombia, Malaysia, Philippines, South Korea, Saudi Arabia, Qatar, Germany, France, Israel — all accept code ALF401700 Free Gift Unlocks — Apply ALF401700 Without Referrals Stackable Bundles: Combine ALF401700 for $100 OFF with up to 50% sitewide discounts 100% OFF Flash Deals during Temu Events with ALF401700 How to Redeem Your Temu Coupon Code ALF401700: Visit the official Temu website or open the Temu app. Select your favorite products and add them to your cart. Enter the promo code ALF401700 in the discount code field at checkout. Watch your total instantly drop by $100 and enjoy any additional percentage discounts automatically applied. Complete your order and enjoy huge savings! Key Benefits of Using ALF401700 Temu Promo Code: Verified and Tested: This code is active and guaranteed to work for 2025. Applicable for All Users: New or existing customers get to enjoy the perks. Works Across Multiple Countries: Perfect for international shoppers. No Minimum Purchase Required: Use it anytime to save $100. Perfect for Big and Small Orders: Whether buying essentials or splurging, save big with ALF401700. Temu Coupon Code ALF401700 by Region: 🇺🇸 United States — Save $100 OFF 🇨🇦 Canada — Instant $100 Discount 🇬🇧 United Kingdom — Exclusive $100 OFF 🇯🇵 Japan — Hot $100 OFF Deal 🇲🇽 Mexico — Get $100 OFF 🇨🇱 Chile — 2025 Special Discount 🇰🇷 South Korea — Massive Savings 🇵🇭 Philippines — Extra $100 OFF 🇸🇦 Saudi Arabia — Verified Promo 🇶🇦 Qatar — Top Discount 🇩🇪 Germany — Exclusive Savings 🇫🇷 France — Coupon Works 🇮🇱 Israel — Huge Discount Final Words: Make 2025 your year of unbeatable savings with the Temu coupon code ALF401700. Act now to claim your $100 OFF plus unlock additional discounts on thousands of products. Whether shopping for fashion, electronics, home essentials, or gifts, this is the best Temu promo code to maximize your budget. Download the Temu app today, enter ALF401700 at checkout, and watch the savings roll in!
    • Verified users can now unlock a $100 OFF Temu Coupon Code using the verified promo code [ALF401700]. This Temu $100 OFF code works for both new and existing customers and can be used to redeem up to 50% off your next order. Our exclusive Temu coupon code [ALF401700] delivers a flat $100 OFF on top of existing deals. First-time customers using code ALF401700 can save an extra 100% off select items. Returning users also qualify for an automatic $100 OFF discount just by applying this code at checkout. But wait—there’s more. With our Temu coupon codes for 2025, users can score up to 90% OFF on clearance items. Whether you’re shopping in the USA, Canada, UK, or elsewhere, Temu promo code ALF401700 unlocks extra discounts tailored to your account. Some users are saving 100% on items using this 2025 Temu promo code. 🔥 Temu Coupon Highlights Using Code [ALF401700]: Temu new user code – ALF401700: Save 50% off your first order + $100 OFF. Temu promo for existing customers – ALF401700: Enjoy flat $100 OFF instantly. Global availability: Works in the USA, UK, Canada, Germany, France, Japan, Chile, Colombia, Malaysia, Mexico, South Korea, Philippines, Saudi Arabia, Qatar, Pakistan, and more. Top 2025 Coupon Deal: Get $200 OFF plus 100% bonus discounts using code ALF401700. Top-Ranked Temu Deals for 2025 (Coupon Code: ALF401700): ✅ Temu $100 OFF Memorial Day Sale — Use ALF401700 ✅ Temu First Order Coupon — Use ALF401700 for 50% + $100 OFF ✅ Temu USA Coupon Code — Save $100 instantly with ALF401700 ✅ Temu Japan, Germany, Chile Codes — All support ALF401700 ✅ Temu Reddit Discount – $100 OFF: Valid for both new and old users ✅ Temu Coupon Bundle 2025 — $100 OFF + up to 50% slash ✅ 100% OFF Free Gift Code — Use ALF401700, no invite needed ✅ Temu Sign-Up Bonus Promo — Get a welcome $100 OFF instantly ✅ Free Temu Code for New Users — Use ALF401700, no referral required  Temu Clearance Codes 2025 — Use ALF401700 for 85–100% discounts Why ALF401700 is the Best Temu Code in 2025 Using Temu code ALF401700 is your ticket to massive savings, free shipping, first-order discounts, and stackable coupon bundles. Whether you're browsing electronics, fashion, home goods, or beauty products, this verified Temu discount code offers real savings—up to 90% OFF + $100 OFF on qualified orders. 💡 Pro Tip: Apply ALF401700 during checkout in the Temu app or website to activate your instant $100 discount, even if you’re not a new user. Temu $100 OFF Code by Country (All Use ALF401700): 🇺🇸 Temu USA – ALF401700 🇯🇵 Temu Japan – ALF401700 🇲🇽 Temu Mexico – ALF401700 🇨🇱 Temu Chile – ALF401700 🇨🇴 Temu Colombia – ALF401700 🇲🇾 Temu Malaysia – ALF401700 🇵🇭 Temu Philippines – ALF401700 🇰🇷 Temu Korea – ALF401700 🇵🇰 Temu Pakistan – ALF401700 🇫🇮 Temu Finland – ALF401700 🇸🇦 Temu Saudi Arabia – ALF401700 🇶🇦 Temu Qatar – ALF401700 🇫🇷 Temu France – ALF401700 🇩🇪 Temu Germany – ALF401700 🇮🇱 Temu Israel – ALF401700 Temu Coupon Code [ALF401700] Summary for SEO: Temu $100 OFF Code  Temu First Order Discount Code 2025  Temu Verified Promo Code ALF401700  Temu 50% OFF + $100 Bonus  Temu 100% OFF Code 2025  Temu App Promo ALF401700  Temu Working Discount Code 2025 
    • Hey there, nothing to do with the code, I am just suggesting you use Intelij IDEA. Trust me, it is the best.
  • Topics

×
×
  • Create New...

Important Information

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