|
1 | 1 | package net.swofty.packer; |
2 | 2 |
|
| 3 | +import net.swofty.packer.packs.ravengard.RavengardPackDefinition; |
| 4 | +import net.swofty.packer.packs.skyblock.SkyblockPackDefinition; |
3 | 5 | import team.unnamed.creative.BuiltResourcePack; |
4 | | -import team.unnamed.creative.base.Writable; |
5 | | -import team.unnamed.creative.metadata.pack.FormatVersion; |
| 6 | +import team.unnamed.creative.server.ResourcePackServer; |
| 7 | +import team.unnamed.creative.server.handler.ResourcePackRequestHandler; |
6 | 8 |
|
7 | | -import java.io.ByteArrayOutputStream; |
8 | 9 | import java.io.IOException; |
9 | | -import java.io.UncheckedIOException; |
10 | | -import java.nio.file.Files; |
11 | | -import java.nio.file.Path; |
12 | | -import java.security.MessageDigest; |
13 | | -import java.security.NoSuchAlgorithmException; |
14 | | -import java.util.HexFormat; |
15 | | -import java.util.stream.Stream; |
16 | | -import java.util.zip.ZipEntry; |
17 | | -import java.util.zip.ZipOutputStream; |
18 | | - |
19 | | -public class HypixelPackBuilder { |
20 | | - private static final FormatVersion FORMAT_VERSION = FormatVersion.of(FormatVersion.FORMAT_26_1); |
21 | | - |
22 | | - private final PackDefinition definition; |
23 | | - |
24 | | - public HypixelPackBuilder(PackDefinition definition) { |
25 | | - this.definition = definition; |
26 | | - } |
27 | | - |
28 | | - public BuiltResourcePack build() { |
29 | | - Path packDirectory = Path.of(definition.getPackDirectory()).toAbsolutePath(); |
| 10 | +import java.io.OutputStream; |
| 11 | +import java.nio.charset.StandardCharsets; |
| 12 | +import java.util.List; |
| 13 | +import java.util.Map; |
| 14 | +import java.util.concurrent.Executors; |
| 15 | +import java.util.function.Function; |
| 16 | +import java.util.stream.Collectors; |
| 17 | + |
| 18 | +public class HypixelPackServer { |
| 19 | + private static final String DEFAULT_HOST = "0.0.0.0"; |
| 20 | + private static final int DEFAULT_PORT = 7270; |
| 21 | + |
| 22 | + static void main(String[] args) throws IOException { |
| 23 | + String host = DEFAULT_HOST; |
| 24 | + int port = DEFAULT_PORT; |
| 25 | + |
| 26 | + for (int i = 0; i < args.length - 1; i++) { |
| 27 | + switch (args[i]) { |
| 28 | + case "-h", "--host" -> host = args[++i]; |
| 29 | + case "-p", "--port" -> port = Integer.parseInt(args[++i]); |
| 30 | + } |
| 31 | + } |
30 | 32 |
|
31 | | - if (!Files.isDirectory(packDirectory)) { |
32 | | - throw new IllegalStateException( |
33 | | - "Pack directory does not exist: " + packDirectory |
34 | | - ); |
| 33 | + Map<String, BuiltResourcePack> packs = List.of( |
| 34 | + RavengardPackDefinition.INSTANCE, |
| 35 | + SkyblockPackDefinition.INSTANCE |
| 36 | + ).stream() |
| 37 | + .map(HypixelPackServer::buildPack) |
| 38 | + .collect(Collectors.toMap( |
| 39 | + pack -> pack.hash() + ".zip", |
| 40 | + Function.identity(), |
| 41 | + (first, second) -> first |
| 42 | + )); |
| 43 | + |
| 44 | + ResourcePackServer server = ResourcePackServer.server() |
| 45 | + .address(host, port) |
| 46 | + .handler(createRequestHandler(packs)) |
| 47 | + .executor(Executors.newFixedThreadPool(4)) |
| 48 | + .build(); |
| 49 | + server.start(); |
| 50 | + |
| 51 | + System.out.println("Resource pack server started on " + host + ":" + port); |
| 52 | + for (String fileName : packs.keySet()) { |
| 53 | + System.out.println("Pack URL: http://" + host + ":" + port + "/" + fileName); |
35 | 54 | } |
| 55 | + System.out.println("Press Ctrl+C to stop."); |
| 56 | + |
| 57 | + Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
| 58 | + System.out.println("Shutting down pack server..."); |
| 59 | + server.stop(5); |
| 60 | + })); |
36 | 61 |
|
37 | 62 | try { |
38 | | - byte[] bytes = zipDirectory(packDirectory); |
39 | | - |
40 | | - MessageDigest digest = MessageDigest.getInstance("SHA-1"); |
41 | | - String hash = HexFormat.of().formatHex(digest.digest(bytes)); |
42 | | - |
43 | | - return BuiltResourcePack.of( |
44 | | - Writable.bytes(bytes), |
45 | | - hash |
46 | | - ); |
47 | | - } catch (IOException e) { |
48 | | - throw new UncheckedIOException("Failed to build resource pack", e); |
49 | | - } catch (NoSuchAlgorithmException e) { |
50 | | - throw new IllegalStateException("SHA-1 is unavailable", e); |
51 | | - } |
| 63 | + Thread.currentThread().join(); |
| 64 | + } catch (InterruptedException ignored) {} |
52 | 65 | } |
53 | 66 |
|
54 | | - private byte[] zipDirectory(Path directory) throws IOException { |
55 | | - ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| 67 | + private static BuiltResourcePack buildPack(PackDefinition definition) { |
| 68 | + System.out.println("Building resource pack '" + definition.getPackName() + "'..."); |
| 69 | + System.out.println("Pack directory: " + definition.getPackDirectory()); |
56 | 70 |
|
57 | | - try (ZipOutputStream zip = new ZipOutputStream(output); |
58 | | - Stream<Path> paths = Files.walk(directory)) { |
| 71 | + BuiltResourcePack built = new HypixelPackBuilder(definition).build(); |
| 72 | + System.out.println("Resource pack built. Hash: " + built.hash()); |
| 73 | + return built; |
| 74 | + } |
59 | 75 |
|
60 | | - paths.filter(Files::isRegularFile).forEach(path -> { |
61 | | - String entryName = directory.relativize(path) |
62 | | - .toString() |
63 | | - .replace('\\', '/'); |
| 76 | + private static ResourcePackRequestHandler createRequestHandler(Map<String, BuiltResourcePack> packs) { |
| 77 | + return (request, exchange) -> { |
| 78 | + String path = exchange.getRequestURI().getPath(); |
| 79 | + String fileName = path.substring(path.lastIndexOf('/') + 1); |
64 | 80 |
|
65 | | - try { |
66 | | - zip.putNextEntry(new ZipEntry(entryName)); |
67 | | - Files.copy(path, zip); |
68 | | - zip.closeEntry(); |
69 | | - } catch (IOException e) { |
70 | | - throw new UncheckedIOException(e); |
71 | | - } |
72 | | - }); |
73 | | - } catch (UncheckedIOException e) { |
74 | | - throw e.getCause(); |
75 | | - } |
| 81 | + BuiltResourcePack pack = packs.get(fileName); |
76 | 82 |
|
77 | | - return output.toByteArray(); |
| 83 | + if (pack == null) { |
| 84 | + byte[] response = "Resource pack not found\n".getBytes(StandardCharsets.UTF_8); |
| 85 | + exchange.getResponseHeaders().set("Content-Type", "text/plain"); |
| 86 | + exchange.sendResponseHeaders(404, response.length); |
| 87 | + try (OutputStream output = exchange.getResponseBody()) { |
| 88 | + output.write(response); |
| 89 | + } |
| 90 | + return; |
| 91 | + } |
| 92 | + |
| 93 | + byte[] response = pack.data().toByteArray(); |
| 94 | + exchange.getResponseHeaders().set("Content-Type", "application/zip"); |
| 95 | + exchange.sendResponseHeaders(200, response.length); |
| 96 | + try (OutputStream output = exchange.getResponseBody()) { |
| 97 | + output.write(response); |
| 98 | + } |
| 99 | + }; |
78 | 100 | } |
79 | | - |
80 | 101 | } |
0 commit comments