diff --git a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
index 3cec098b..e80ad5fc 100644
--- a/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
+++ b/VelocityCore/src/de/steamwar/velocitycore/VelocityCore.java
@@ -153,6 +153,7 @@ public class VelocityCore implements ReloadablePlugin {
new CheckListener();
new IPSanitizer();
new VersionAnnouncer();
+ new TexturePackSystem();
local = new Node.LocalNode();
if(MAIN_SERVER) {
diff --git a/VelocityCore/src/de/steamwar/velocitycore/listeners/TexturePackSystem.java b/VelocityCore/src/de/steamwar/velocitycore/listeners/TexturePackSystem.java
new file mode 100644
index 00000000..46da12da
--- /dev/null
+++ b/VelocityCore/src/de/steamwar/velocitycore/listeners/TexturePackSystem.java
@@ -0,0 +1,105 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.velocitycore.listeners;
+
+import com.velocitypowered.api.event.Subscribe;
+import com.velocitypowered.api.event.player.ServerPostConnectEvent;
+import com.velocitypowered.api.proxy.player.ResourcePackInfo;
+import de.steamwar.velocitycore.VelocityCore;
+import net.kyori.adventure.text.Component;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+// https://jd.papermc.io/velocity/3.4.0/com/velocitypowered/api/proxy/player/ResourcePackInfo.Builder.html#setHash(byte%5B%5D)
+public class TexturePackSystem extends BasicListener {
+
+ private static final File PACKS_DIR = new File("/var/www/packs");
+ private static final String BASE_ULR = "https://packs.steamwar.de/";
+ private TreeMap protocolVersionToPackVersion = new TreeMap<>();
+
+ public TexturePackSystem() {
+ // https://minecraft.wiki/w/Pack_format#List_of_resource_pack_formats
+ // https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol_version_numbers
+ protocolVersionToPackVersion.put(759, 9);
+ protocolVersionToPackVersion.put(761, 12);
+ protocolVersionToPackVersion.put(762, 13);
+ protocolVersionToPackVersion.put(763, 15);
+ protocolVersionToPackVersion.put(764, 18);
+ protocolVersionToPackVersion.put(765, 22);
+ protocolVersionToPackVersion.put(766, 32);
+ protocolVersionToPackVersion.put(767, 34);
+ protocolVersionToPackVersion.put(768, 42);
+ protocolVersionToPackVersion.put(769, 46);
+ protocolVersionToPackVersion.put(770, 55);
+ }
+
+ @Subscribe
+ public void onLogin(ServerPostConnectEvent event) {
+ if (event.getPreviousServer() != null) {
+ return;
+ }
+ VelocityCore.schedule(() -> {
+ int playerVersion = event.getPlayer().getProtocolVersion().getProtocol();
+ File selectedPack = null;
+ while (selectedPack == null) {
+ Map.Entry pack = protocolVersionToPackVersion.floorEntry(playerVersion);
+ if (pack == null) return;
+
+ for (File file : PACKS_DIR.listFiles()) {
+ if (file.getName().startsWith(pack.getValue() + "_")) {
+ selectedPack = file;
+ break;
+ }
+ }
+
+ playerVersion--;
+ }
+
+ String fileName = selectedPack.getName();
+ fileName = fileName.substring(fileName.indexOf('_') + 1, fileName.lastIndexOf('.'));
+ byte[] hash = hexStringToByteArray(fileName);
+
+ ResourcePackInfo resourcePackInfo = VelocityCore.getProxy().createResourcePackBuilder(BASE_ULR + selectedPack.getName())
+ .setId(UUID.nameUUIDFromBytes(fileName.getBytes(StandardCharsets.UTF_8)))
+ .setHash(hash)
+ .setShouldForce(false)
+ .setPrompt(Component.text("The SteamWar TexturePack improves GUIs!"))
+ .build();
+ event.getPlayer().sendResourcePacks(resourcePackInfo);
+ }).delay(500, TimeUnit.MILLISECONDS).schedule();
+ }
+
+ public static byte[] hexStringToByteArray(String s) {
+ int len = s.length();
+ byte[] data = new byte[len / 2];
+
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ + Character.digit(s.charAt(i+1), 16));
+ }
+
+ return data;
+ }
+}