aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/anthonyhilyard/iceberg/util/DynamicResourcePack.java
blob: 4c0bfbf79c6834e5be94dd27bea72d1ee3bdc195 (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package com.anthonyhilyard.iceberg.util;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.metadata.MetadataSectionSerializer;
import net.minecraft.server.packs.resources.IoSupplier;

/**
 * DynamicResourcePack allows resources that are defined arbitrarily to do cool things with resources.
 * For example, resources that change in response to game state, resource proxies, or resources downloaded from the internet.
 */
public class DynamicResourcePack implements PackResources
{
	private record DynamicResourceKey(String type, String namespace, String path) {}

	private final String packName;
	private Map<DynamicResourceKey, IoSupplier<InputStream>> dynamicResourceMap = new HashMap<DynamicResourceKey, IoSupplier<InputStream>>();

	public DynamicResourcePack(String packName)
	{
		this.packName = packName;
	}

	public void clear()
	{
		dynamicResourceMap.clear();
	}

	public boolean removeResource(PackType type, ResourceLocation location)
	{
		DynamicResourceKey key = new DynamicResourceKey(type.getDirectory(), location.getNamespace(), location.getPath());
		if (dynamicResourceMap.containsKey(key))
		{
			dynamicResourceMap.remove(key);
			return true;
		}
		else
		{
			return false;
		}
	}

	public boolean registerResource(PackType type, ResourceLocation location, IoSupplier<InputStream> resourceSupplier)
	{
		return register(type.getDirectory(), location.getNamespace(), location.getPath(), resourceSupplier);
	}

	public boolean registerRootResource(String path, IoSupplier<InputStream> resourceSupplier)
	{
		return register("root", "", path, resourceSupplier);
	}

	private boolean register(String directory, String namespace, String path, IoSupplier<InputStream> resourceSupplier)
	{
		DynamicResourceKey key = new DynamicResourceKey(directory, namespace, path);
		if (!dynamicResourceMap.containsKey(key))
		{	
			dynamicResourceMap.put(key, resourceSupplier);
			return true;
		}
		return false;
	}

	@Override
	@Nullable
	public IoSupplier<InputStream> getRootResource(String... path)
	{
		try
		{
			return getResource("root", "", String.join("/", path));
		}
		catch (IOException e)
		{
			return null;
		}
	}

	@Override
	@Nullable
	public IoSupplier<InputStream> getResource(PackType type, ResourceLocation location)
	{
		try
		{
			return getResource(type.getDirectory(), location.getNamespace(), location.getPath());
		}
		catch (IOException e)
		{
			return null;
		}
	}

	private IoSupplier<InputStream> getResource(String directory, String namespace, String path) throws IOException
	{
		DynamicResourceKey key = new DynamicResourceKey(directory, namespace, path);
		if (dynamicResourceMap.containsKey(key))
		{
			return dynamicResourceMap.get(key);
		}
		else
		{
			throw new FileNotFoundException("Can't find dynamic resource " + path + ". Please ensure it has been registered.");
		}
	}

	@Override
	public void listResources(PackType type, String namespace, String path, ResourceOutput output)
	{
		dynamicResourceMap.entrySet().stream()
		.filter(entry -> entry.getKey().namespace.contentEquals(namespace))
		.filter(entry -> entry.getKey().path.startsWith(path))
		.filter(entry -> entry.getKey().type.contentEquals(type.getDirectory()))
		.forEach(entry -> output.accept(new ResourceLocation(namespace, entry.getKey().path), entry.getValue()));
	}

	@Override
	public Set<String> getNamespaces(PackType type)
	{
		Set<String> namespaces = new HashSet<>();
		for (DynamicResourceKey key : dynamicResourceMap.keySet())
		{
			if (type.getDirectory().contentEquals(key.type))
			{
				namespaces.add(key.namespace);
			}
		}
		return namespaces;
	}

	@Override
	public <T> T getMetadataSection(MetadataSectionSerializer<T> p_10291_) throws IOException
	{
		// Does nothing for now.
		// TODO: Add metadata?  Probably not needed right?
		return null;
	}

	@Override
	public String packId()
	{
		return packName;
	}

	@Override
	public void close()
	{
	}
}