File size: 3,280 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package net.minecraft.client.sounds;

import com.google.common.collect.Sets;
import com.mojang.blaze3d.audio.Channel;
import com.mojang.blaze3d.audio.Library;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class ChannelAccess {
    private final Set<ChannelAccess.ChannelHandle> channels = Sets.newIdentityHashSet();
    final Library library;
    final Executor executor;

    public ChannelAccess(Library p_120125_, Executor p_120126_) {
        this.library = p_120125_;
        this.executor = p_120126_;
    }

    public CompletableFuture<ChannelAccess.ChannelHandle> createHandle(Library.Pool p_120129_) {
        CompletableFuture<ChannelAccess.ChannelHandle> completablefuture = new CompletableFuture<>();
        this.executor.execute(() -> {
            Channel channel = this.library.acquireChannel(p_120129_);
            if (channel != null) {
                ChannelAccess.ChannelHandle channelaccess$channelhandle = new ChannelAccess.ChannelHandle(channel);
                this.channels.add(channelaccess$channelhandle);
                completablefuture.complete(channelaccess$channelhandle);
            } else {
                completablefuture.complete(null);
            }
        });
        return completablefuture;
    }

    public void executeOnChannels(Consumer<Stream<Channel>> p_120138_) {
        this.executor.execute(() -> p_120138_.accept(this.channels.stream().map(p_174978_ -> p_174978_.channel).filter(Objects::nonNull)));
    }

    public void scheduleTick() {
        this.executor.execute(() -> {
            Iterator<ChannelAccess.ChannelHandle> iterator = this.channels.iterator();

            while (iterator.hasNext()) {
                ChannelAccess.ChannelHandle channelaccess$channelhandle = iterator.next();
                channelaccess$channelhandle.channel.updateStream();
                if (channelaccess$channelhandle.channel.stopped()) {
                    channelaccess$channelhandle.release();
                    iterator.remove();
                }
            }
        });
    }

    public void clear() {
        this.channels.forEach(ChannelAccess.ChannelHandle::release);
        this.channels.clear();
    }

    @OnlyIn(Dist.CLIENT)
    public class ChannelHandle {
        @Nullable
        Channel channel;
        private boolean stopped;

        public boolean isStopped() {
            return this.stopped;
        }

        public ChannelHandle(final Channel p_120150_) {
            this.channel = p_120150_;
        }

        public void execute(Consumer<Channel> p_120155_) {
            ChannelAccess.this.executor.execute(() -> {
                if (this.channel != null) {
                    p_120155_.accept(this.channel);
                }
            });
        }

        public void release() {
            this.stopped = true;
            ChannelAccess.this.library.releaseChannel(this.channel);
            this.channel = null;
        }
    }
}