diff --git a/src/common/resources/lang/en_US/strings.lang b/src/common/resources/lang/en_US/strings.lang
index a72990d37..577dc8aba 100644
--- a/src/common/resources/lang/en_US/strings.lang
+++ b/src/common/resources/lang/en_US/strings.lang
@@ -133,6 +133,19 @@ sign.image.afk=AFK
 sign.image.brb=BRB
 sign.image.heart=Heart
 
+record.13=13
+record.cat=Cat
+record.blocks=Blocks
+record.chirp=Chirp
+record.far=Far
+record.mall=Mall
+record.mellohi=Mellohi
+record.stal=Stal
+record.strad=Strad
+record.ward=Ward
+record.wait=Wait
+record.dog=Dog
+
 flag.full=You have too many flags on this map!
 flag.overwrite=Cannot overwrite an existing pattern.
 flag.copied=Flag pattern copied.
diff --git a/src/common/resources/lang/en_US/subtitles.lang b/src/common/resources/lang/en_US/subtitles.lang
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java
index e28144cfb..ed0ed089b 100644
--- a/src/main/java/net/minecraft/client/Minecraft.java
+++ b/src/main/java/net/minecraft/client/Minecraft.java
@@ -19,11 +19,12 @@ import java.util.Random;
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 
+import net.minecraft.client.sound.SoundRepository;
 import net.minecraft.client.world.chunk.provider.ChunkProviderDynamic;
+import org.jetbrains.annotations.Nullable;
 import org.lwjgl.LWJGLException;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
-import org.lwjgl.opengl.Display;
 import org.lwjgl.opengl.GL11;
 
 import com.mojang.nbt.CompoundTag;
@@ -189,7 +190,11 @@ public class Minecraft
     public volatile boolean isGamePaused;
     public RenderEngine renderEngine;
     public FontRenderer fontRenderer;
-    public GuiScreen currentScreen;
+    /**
+     * Current gui the player is looking at
+     * is null when in a world during normal play
+     */
+    public @Nullable GuiScreen currentScreen;
     public LoadingScreenRenderer loadingScreen;
     public WorldRenderer worldRenderer;
     public ThreadDownloadResources downloadResourcesThread;
@@ -442,7 +447,9 @@ public class Minecraft
 
         texturePackList = new TexturePackList(this, mcDataDir);
         renderEngine = new RenderEngine(this, texturePackList, gameSettings);
-        
+
+        SoundRepository.initialize(this);
+
         // Show load screen as early as possible
         // Do not put stuff that takes a while to load before this,
         // otherwise the loading time will happen while the window is black
@@ -2023,8 +2030,7 @@ public class Minecraft
         System.out.println("FORCING RELOAD!");
         sndManager = new SoundEngine();
         sndManager.init(gameSettings);
-        downloadResourcesThread.reloadResources();
-        renderEngine.refreshTexturesAndDisplayErrors();
+        texturePackList.refresh();
         renderer.reload();
         if (renderGlobal != null){
             renderGlobal.loadRenderers();
@@ -2173,7 +2179,7 @@ public class Minecraft
             loadingScreen.progressStage("");
         }
 
-        sndManager.playStreaming(null, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F);
+        sndManager.stopMusic();
         if(theWorld != null)
         {
             theWorld.saveWorldIndirectly(loadingScreen);
@@ -2343,33 +2349,6 @@ public class Minecraft
         theWorld.dropOldChunks();
     }
 
-    public void installResource(String s, File file)
-    {
-        int i = s.indexOf("/");
-        String s1 = s.substring(0, i);
-        s = s.substring(i + 1);
-        if(s1.equalsIgnoreCase("sound"))
-        {
-            sndManager.addSound(s, file);
-        } else
-        if(s1.equalsIgnoreCase("newsound"))
-        {
-            sndManager.addSound(s, file);
-        } else
-        if(s1.equalsIgnoreCase("streaming"))
-        {
-            sndManager.addStreaming(s, file);
-        } else
-        if(s1.equalsIgnoreCase("music"))
-        {
-            sndManager.addMusic(s, file);
-        } else
-        if(s1.equalsIgnoreCase("newmusic"))
-        {
-            sndManager.addMusic(s, file);
-        }
-    }
-
     public String getRendererDebugInfo()
     {
         return renderGlobal.getRendererDebugInfo();
diff --git a/src/main/java/net/minecraft/client/gui/GuiCredits.java b/src/main/java/net/minecraft/client/gui/GuiCredits.java
index 1dc580ded..2b3d24f7c 100644
--- a/src/main/java/net/minecraft/client/gui/GuiCredits.java
+++ b/src/main/java/net/minecraft/client/gui/GuiCredits.java
@@ -5,6 +5,7 @@ import net.minecraft.client.render.Scissor;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.command.TextFormatting;
+import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.MathHelper;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
@@ -25,16 +26,16 @@ public class GuiCredits extends GuiScreen {
     private static final int BUTTON_SPACING = 4;
 
     private static final String[] SONGS = {
-        "cat",
-        "blocks",
-        "chirp",
-        "far",
-        "mall",
-        "mellohi",
-        "stal",
-        "strad",
-        "ward",
-        "dog",
+        "record.cat",
+        "record.blocks",
+        "record.chirp",
+        "record.far",
+        "record.mall",
+        "record.mellohi",
+        "record.stal",
+        "record.strad",
+        "record.ward",
+        "record.dog",
     };
 
     protected int top;
@@ -91,14 +92,14 @@ public class GuiCredits extends GuiScreen {
     @Override
     public void tick() {
         if (!playing) {
-            mc.sndManager.playStreaming(SONGS[(int) (Math.random() * SONGS.length)], 0, 0, 0, 1.0f, 1.0f);
+            mc.sndManager.playMusic(SONGS[(int) (Math.random() * SONGS.length)], 0, 0, 0, 1.0f, 1.0f);
             playing = true;
         }
     }
 
     @Override
     public void onClosed() {
-        mc.sndManager.playStreaming(null, 0, 0, 0, 0, 0);
+        mc.sndManager.stopMusic();
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java
index 359f01da7..00d4ac2b6 100644
--- a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java
+++ b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java
@@ -357,7 +357,7 @@ public class GuiMainMenu extends GuiScreen
     		int ib = (int) java.lang.Math.round(b * 255);
     		int color = 0xFF000000 + (ib << 16) + (ib << 8) + (ib);
     		mc.fontRenderer.drawCenteredString(
-                i18n.translateKeyAndFormat("gui.main_menu.label.downloading_resources", mc.downloadResourcesThread.downloadProgress, mc.downloadResourcesThread.toDownload),
+                i18n.translateKeyAndFormat("gui.main_menu.label.downloading_resources", mc.downloadResourcesThread.downloadProgress.get(), mc.downloadResourcesThread.toDownload),
                 width / 2, 16, color);
     	}
     }
diff --git a/src/main/java/net/minecraft/client/gui/GuiSoundTest.java b/src/main/java/net/minecraft/client/gui/GuiSoundTest.java
index 24b5de7b2..d9ecefd6a 100644
--- a/src/main/java/net/minecraft/client/gui/GuiSoundTest.java
+++ b/src/main/java/net/minecraft/client/gui/GuiSoundTest.java
@@ -1,12 +1,11 @@
 package net.minecraft.client.gui;
 
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.gui.modelviewer.elements.GuiListenerButton;
 import net.minecraft.client.gui.modelviewer.elements.GuiListenerTextField;
 import net.minecraft.client.gui.modelviewer.elements.IListenerElement;
 import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.client.sound.SoundEngine;
-import net.minecraft.client.sound.SoundEntry;
+import net.minecraft.client.sound.SoundEvent;
 import net.minecraft.client.sound.SoundRepository;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.sound.SoundCategory;
@@ -14,10 +13,8 @@ import net.minecraft.core.util.helper.Utils;
 import org.jetbrains.annotations.Nullable;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.GL11;
-import paulscode.sound.SoundSystem;
 
 import java.io.File;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -28,17 +25,11 @@ public class GuiSoundTest extends GuiScreen{
     protected int top;
     protected int bottom;
 
-    protected Field[] repoFields;
-    protected SoundRepository[] repos;
-
-    protected int repoIndex;
-    protected SoundRepository currentRepo;
     protected int entryIndex = 0;
-    @Nullable
-    protected SoundEntry currentEntry;
+    protected @Nullable SoundEvent currentEntry;
+    protected List<SoundEvent> allEntries;
 
     protected GuiListenerButton leftEntry;
-    protected GuiListenerButton leftRepo;
 
     protected float volume = 1;
     protected float pitch = 1;
@@ -51,25 +42,9 @@ public class GuiSoundTest extends GuiScreen{
     }
 
     public void initRepos(){
-        List<Field> fields = new ArrayList<>();
-        for (Field f : SoundEngine.class.getFields()){
-            if (f.getType().isAssignableFrom(SoundRepository.class)){
-                fields.add(f);
-            }
-        }
-        repoFields = new Field[fields.size()];
-        repos = new SoundRepository[fields.size()];
-        for (int i = 0; i < fields.size(); i++) {
-            repoFields[i] = fields.get(i);
-            try {
-                repos[i] = (SoundRepository) fields.get(i).get(Minecraft.getMinecraft(this).sndManager);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException(e);
-            }
-        }
+        allEntries = SoundRepository.SOUNDS.getAllEvents();
 
-        currentRepo = repos[0];
-        currentEntry = currentRepo.getAllEntries().get(0);
+        currentEntry = allEntries.get(0);
         entryIndex = 0;
     }
     @Override
@@ -104,22 +79,15 @@ public class GuiSoundTest extends GuiScreen{
             mc.displayGuiScreen(null);
         }));
 
-        leftRepo = add(new GuiListenerButton(1, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20), 20, 20, "<")
-            .setActionListener(() -> cycleRepo(-1)));
-        add(new GuiListenerButton(2, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20), 20, 20, ">")
-            .setActionListener(() -> cycleRepo(1)));
-
         leftEntry = add(new GuiListenerButton(11, width - (20 + BUTTON_SPACING) * 2, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, "<")
             .setActionListener(() -> cycleEntry(-1)));
         add(new GuiListenerButton(12, width - (20 + BUTTON_SPACING) * 1, bottom - (BUTTON_SPACING + 20) * 2, 20, 20, ">")
             .setActionListener(() -> cycleEntry(1)));
 
-        add(new GuiListenerButton(20, width/2 - 100, bottom - (BUTTON_SPACING + 20), 100 - BUTTON_SPACING/2, 20, I18n.getInstance().translateKey("gui.sound_test.button.play"))
-            .setActionListener(() -> playEntry(false))
-        );
-        add(new GuiListenerButton(21, width/2 + 100 - (100 - BUTTON_SPACING/2), bottom - (BUTTON_SPACING + 20), 100 - BUTTON_SPACING/2, 20, I18n.getInstance().translateKey("gui.sound_test.button.play_stream"))
-            .setActionListener(() -> playEntry(true))
+        GuiListenerButton b = add(new GuiListenerButton(20, width/2 - 100, bottom - (BUTTON_SPACING + 20), 200, 20, I18n.getInstance().translateKey("gui.sound_test.button.play"))
+            .setActionListener(this::playEntry)
         );
+        b.playSound = false;
         add(new GuiListenerButton(22, width/2 + 100 + BUTTON_SPACING, bottom - (BUTTON_SPACING + 20), 20, 20, "X")
             .setActionListener(this::stopSound)
         );
@@ -136,7 +104,6 @@ public class GuiSoundTest extends GuiScreen{
             .setActionListener(() -> {
                 mc.sndManager = new SoundEngine();
                 mc.sndManager.init(mc.gameSettings);
-                mc.downloadResourcesThread.reloadResources();
                 initRepos();
             });
 
@@ -175,23 +142,10 @@ public class GuiSoundTest extends GuiScreen{
     {
     }
 
-    protected void cycleRepo(int offset) {
-        int index = (repoIndex + offset + repos.length) % repos.length;
-        currentRepo = repos[index];
-        repoIndex = index;
-        try {
-            currentEntry = currentRepo.getAllEntries().get(0);
-            entryIndex = 0;
-        } catch (Exception e) {
-            currentEntry = null;
-            entryIndex = -1;
-        }
-    }
-
     protected void cycleEntry(int offset) {
-        if (currentRepo.getAllEntries().size() <= 0) return;
-        int index = (entryIndex + offset + currentRepo.getAllEntries().size()) % currentRepo.getAllEntries().size();
-        currentEntry = currentRepo.getAllEntries().get(index);
+        if (allEntries.size() <= 0) return;
+        int index = (entryIndex + offset + allEntries.size()) % allEntries.size();
+        currentEntry = allEntries.get(index);
         entryIndex = index;
     }
 
@@ -202,17 +156,13 @@ public class GuiSoundTest extends GuiScreen{
 
         fontRenderer.drawCenteredString(I18n.getInstance().translateKey("gui.sound_test.label.title"), width/2, 5, 0xFFFFFF);
 
-        fontRenderer.drawCenteredString(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.repo", repoFields[repoIndex].getName()), width/2, top + 10, 0xFFFFFF);
-
-        String msg = I18n.getInstance().translateKey("gui.sound_test.label.select_repo");
-        fontRenderer.drawString(msg, leftRepo.getX() - BUTTON_SPACING - fontRenderer.getStringWidth(msg), leftRepo.getY() + 6, 0xFFFFFF);
-        msg = I18n.getInstance().translateKey("gui.sound_test.label.select_entry");
+        String msg = I18n.getInstance().translateKey("gui.sound_test.label.select_entry");
         fontRenderer.drawString(msg, leftEntry.getX() - BUTTON_SPACING - fontRenderer.getStringWidth(msg), leftEntry.getY() + 6, 0xFFFFFF);
 
         StringBuilder builder = new StringBuilder();
-        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.id", currentEntry == null ? null : currentEntry.soundID), width - 10)).append("\n");
-        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.name", currentEntry == null ? null : currentEntry.name), width - 10)).append("\n");
-        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.url", String.valueOf(currentEntry == null ? null : (showURL ? currentEntry.url : "REDACTED"))), width - 10)).append("\n");
+        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.id", currentEntry == null ? null : currentEntry.getEventID()), width - 10)).append("\n");
+//        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.name", currentEntry == null ? null : currentEntry.name), width - 10)).append("\n");
+//        builder.append(fontRenderer.wrapFormattedStringToWidth(I18n.getInstance().translateKeyAndFormat("gui.sound_test.label.url", String.valueOf(currentEntry == null ? null : (showURL ? currentEntry.url : "REDACTED"))), width - 10)).append("\n");
         String[] lines = builder.toString().split("\n");
         int y = top + 30;
         for (String line : lines) {
@@ -247,17 +197,9 @@ public class GuiSoundTest extends GuiScreen{
         }
     }
 
-    public void playEntry(boolean asStream) {
+    public void playEntry() {
         if (currentEntry == null) return;
-        if (asStream) {
-            final float streamingVolume = 16F;
-            SoundSystem soundSystem = SoundEngine.getSoundSystem();
-            soundSystem.newStreamingSource(true, "debug", currentEntry.url, currentEntry.name, false, 0, 0, 0, 2, streamingVolume * 4F);
-            soundSystem.setVolume("debug", volume * mc.gameSettings.masterVolume.value);
-            soundSystem.play("debug");
-        } else  {
-            mc.sndManager.playSoundEntry(currentEntry, "debug", SoundCategory.GUI_SOUNDS, volume, pitch);
-        }
+        mc.sndManager.playSoundWithIdAtPos(currentEntry.getRandomEntry(), SoundCategory.ENTITY_SOUNDS, 0, 0, 0, 1, 1, "debug");
     }
 
     public void stopSound() {
diff --git a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
index 8cfc36ef7..8619de121 100644
--- a/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
+++ b/src/main/java/net/minecraft/client/net/thread/ThreadDownloadResources.java
@@ -8,8 +8,10 @@ import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import com.b100.json.JsonParser;
 import com.b100.json.element.JsonElement;
@@ -22,14 +24,14 @@ import net.minecraft.client.Minecraft;
 
 public class ThreadDownloadResources extends Thread {
 
-    public static String[] extractFiles = new String[]{"sound/ui/ui_back.ogg", "sound/ui/ui_click.ogg", "sound/ui/ui_focus.ogg", "sound/ui/ui_scroll.ogg", "sound/ui/crafting_fail.ogg", "sound/ui/crafting_made.ogg"};
+    public static String[] extractFiles = new String[]{"ui/ui_back.ogg", "ui/ui_click.ogg", "ui/ui_focus.ogg", "ui/ui_scroll.ogg", "ui/crafting_fail.ogg", "ui/crafting_made.ogg"};
     public static String resourceDomain = "https://api.betterthanadventure.net/MinecraftResources/";
 
     public final Minecraft mc;
     public File resourcesFolder;
 
     public volatile boolean downloading = false;
-    public volatile int downloadProgress;
+    public AtomicInteger downloadProgress = new AtomicInteger(0);
     public volatile int toDownload;
 
     public ThreadDownloadResources(File file, Minecraft minecraft) {
@@ -46,10 +48,10 @@ public class ThreadDownloadResources extends Thread {
 	public void run() {
         try {
             // Copy files out of jar
-            for (int i = 0; i < extractFiles.length; i++) {
-                File file = new File(resourcesFolder, "newsound/random/" + extractFiles[i]);
-                if (!file.exists()) {
-                    transferDataAndClose(ThreadDownloadResources.class.getResourceAsStream("/" + extractFiles[i]), new FileOutputStream(createNewFile(file)));
+            for (String extractResource : extractFiles) {
+                File output = new File(resourcesFolder, "minecraft/sounds/" + extractResource);
+                if (!output.exists()) {
+                    transferDataAndClose(ThreadDownloadResources.class.getResourceAsStream("/assets/minecraft/sounds/" + extractResource), Files.newOutputStream(createNewFile(output).toPath()));
                 }
             }
 
@@ -71,45 +73,8 @@ public class ThreadDownloadResources extends Thread {
         } catch (Exception e) {
             e.printStackTrace();
         }
-        load();
     }
 
-    public void reloadResources() {
-        load();
-    }
-
-    public void load() {
-        System.out.println("Loading Sounds...");
-        List<File> files;
-
-        if (mc.gameSettings.loadAllSounds.value) {
-            files = getAllFiles(resourcesFolder);
-        } else {
-            files = new ArrayList<>();
-            for (JsonElement element : new JsonParser().parseStream(ThreadDownloadResources.class.getResourceAsStream("/sounds.json")).getArray("sounds")) {
-                files.add(new File(resourcesFolder, element.getAsString().value));
-            }
-        }
-
-        int pathLength = resourcesFolder.getAbsolutePath().length() + 1;
-        int installCount = 0;
-        for (File file : files) {
-        	if(!file.exists()) {
-        		continue;
-        	}
-            String string = file.getAbsolutePath().substring(pathLength).replace("\\", "/");
-            if (string.indexOf("/") != -1) {
-                try {
-                    mc.installResource(string, file);
-                } catch (Exception e) {
-                    System.err.println("Could not install resource: " + string + " " + e.getClass().getName() + ": " + e.getMessage());
-                }
-                installCount++;
-            }
-        }
-
-        System.out.println("Installed " + installCount + " Sound Files!");
-    }
 
     public void downloadResources() {
         String xmlString = StringUtils.getWebsiteContentAsString(resourceDomain);
@@ -132,8 +97,10 @@ public class ThreadDownloadResources extends Thread {
             if (tag.name().equals("Contents")) {
 
                 String name = tag.getAsContentTag().get("Key").getAsStringTag().content();
+                String fileName = remapDirectory(name);
                 long size = tag.getAsContentTag().get("Size").getAsStringTag().getLong();
-                File soundFile = new File(resourcesFolder, name);
+
+                File soundFile = new File(resourcesFolder, "minecraft/sounds/" + fileName);
 
                 if (!soundFile.isFile() || (!mc.gameSettings.allowSoundOverrides.value && soundFile.length() != size)) {
                     entries.add(new SoundEntry(soundFile, name, size));
@@ -141,7 +108,7 @@ public class ThreadDownloadResources extends Thread {
             }
         }
 
-        if (entries.size() == 0) {
+        if (entries.isEmpty()) {
             return;
         }
 
@@ -151,7 +118,7 @@ public class ThreadDownloadResources extends Thread {
         for (SoundEntry soundEntry : entries) {
             try {
                 downloadSoundFile(soundEntry.name, soundEntry.file);
-                downloadProgress++;
+                downloadProgress.incrementAndGet();
             } catch (Exception e) {
                 throw new RuntimeException("Error downloading sound file: " + soundEntry.name, e);
             }
@@ -160,13 +127,30 @@ public class ThreadDownloadResources extends Thread {
         downloading = false;
     }
 
+    private String remapDirectory(String path) {
+        // hard coded remapping
+        if (path.startsWith("newsound/")) {
+            path = path.replaceFirst("newsound/", "");
+        }
+        if (path.startsWith("sound/")) {
+            path = path.replaceFirst("sound/", "");
+        }
+        if (path.startsWith("streaming/")) {
+            path = path.replaceFirst("streaming/", "record/");
+        }
+        if (path.startsWith("newmusic/")) {
+            path = path.replaceFirst("newmusic/", "music/");
+        }
+        return path;
+    }
+
     private void downloadSoundFile(String name, File file) throws Exception {
         String url = resourceDomain + name;
         url = url.replace(" ", "%20");
 
         System.out.println("Downloading File: " + url);
 
-        transferDataAndClose(new BufferedInputStream(new URL(url).openStream()), new BufferedOutputStream(new FileOutputStream(createNewFile(file))));
+        transferDataAndClose(new BufferedInputStream(new URL(url).openStream()), new BufferedOutputStream(Files.newOutputStream(createNewFile(file).toPath())));
     }
 
     private static class SoundEntry {
diff --git a/src/main/java/net/minecraft/client/option/VolumeOption.java b/src/main/java/net/minecraft/client/option/VolumeOption.java
index c49b1d156..1a1959a39 100644
--- a/src/main/java/net/minecraft/client/option/VolumeOption.java
+++ b/src/main/java/net/minecraft/client/option/VolumeOption.java
@@ -20,7 +20,7 @@ public class VolumeOption extends FloatOption{
 		gameSettings.mc.sndManager.updateOptions();
 		SoundSystem soundSystem = SoundEngine.getSoundSystem();
 		if (soundCategory != SoundCategory.GUI_SOUNDS && !soundSystem.playing("sound_audio_options")) {
-			gameSettings.mc.sndManager.playSoundId(soundCategory.changedSound, soundCategory, 1f, 1f, "sound_audio_options");
+			gameSettings.mc.sndManager.playSoundWithID(soundCategory.changedSound, soundCategory, 1f, 1f, "sound_audio_options");
 		} else if (soundCategory != SoundCategory.GUI_SOUNDS) {
 			soundSystem.setVolume("sound_audio_options", SoundCategoryHelper.getEffectiveVolume(soundCategory, gameSettings));
 		}
diff --git a/src/main/java/net/minecraft/client/render/RenderGlobal.java b/src/main/java/net/minecraft/client/render/RenderGlobal.java
index b80b29f54..0f28d5b52 100644
--- a/src/main/java/net/minecraft/client/render/RenderGlobal.java
+++ b/src/main/java/net/minecraft/client/render/RenderGlobal.java
@@ -6,7 +6,6 @@ import net.minecraft.client.entity.particle.Particle;
 import net.minecraft.client.entity.particle.ParticleDispatcher;
 import net.minecraft.client.gui.GuiPhotoMode;
 import net.minecraft.client.gui.modelviewer.GuiModelViewer;
-import net.minecraft.client.option.enums.RenderDistance;
 import net.minecraft.client.render.block.model.BlockModel;
 import net.minecraft.client.render.block.model.BlockModelDispatcher;
 import net.minecraft.client.render.block.model.LeavesBlockModel;
@@ -21,6 +20,7 @@ import net.minecraft.client.render.tessellator.Tessellator;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.MusicDiscItem;
+import net.minecraft.core.lang.I18n;
 import net.minecraft.core.util.phys.HitResult;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.Blocks;
@@ -1555,12 +1555,12 @@ public class RenderGlobal
         if(soundPath != null)
         {
             if (author != null && !author.isEmpty()){
-                mc.ingameGUI.setRecordPlayingMessage(author + " - " + soundPath);
+                mc.ingameGUI.setRecordPlayingMessage(author + " - " + I18n.getInstance().translateKey(soundPath));
             } else {
-                mc.ingameGUI.setRecordPlayingMessage(soundPath);
+                mc.ingameGUI.setRecordPlayingMessage(I18n.getInstance().translateKey(soundPath));
             }
         }
-        mc.sndManager.playStreaming(soundPath, x, y, z, 1.0F, 1.0F);
+        mc.sndManager.playMusic(soundPath, x, y, z, 1.0F, 1.0F);
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/render/WorldRenderer.java b/src/main/java/net/minecraft/client/render/WorldRenderer.java
index 67d020b34..4416e744b 100644
--- a/src/main/java/net/minecraft/client/render/WorldRenderer.java
+++ b/src/main/java/net/minecraft/client/render/WorldRenderer.java
@@ -399,7 +399,7 @@ public class WorldRenderer
     private float getZoomedFOV(float currentFov, float partialTick){
         currentFov *= 0.45f;
         float prevZoomProgress = zoomProgress;
-        zoomProgress -= Mouse.getDWheel()/0.256f;
+        zoomProgress -= Mouse.getDWheel()/4f;
         zoomProgress = MathHelper.clamp(zoomProgress, -7.5f, 7.5f);
         final float maxFOV = 160f;
         final float minFOV = 5f;
@@ -495,10 +495,12 @@ public class WorldRenderer
         int c = 200;
         if(mc.gameSettings.enableVsync.value) // VSync
         {
-        	c = mc.gameWindow.getFrequency(); // Cap fps when minimized
+//        	c = mc.gameWindow.getFrequency(); // Cap fps when minimized
+            c = 999;
         } else {
             c = mc.gameSettings.customFpsLimit.value;
         }
+        if (c <= 0) c = 1;
         glViewport(0, 0, mc.resolution.width, mc.resolution.height);
         if(mc.theWorld != null)
         {
diff --git a/src/main/java/net/minecraft/client/render/entity/SquidRenderer.java b/src/main/java/net/minecraft/client/render/entity/SquidRenderer.java
index 1818c6beb..00f7c1ece 100644
--- a/src/main/java/net/minecraft/client/render/entity/SquidRenderer.java
+++ b/src/main/java/net/minecraft/client/render/entity/SquidRenderer.java
@@ -24,13 +24,17 @@ public class SquidRenderer extends MobRenderer<SquidMob>
     @Override
     protected void setupRotations(SquidMob squid, float ticksExisted, float bodyYaw, float partialTick)
     {
-        float pitch = squid.xBodyRotO + (squid.xBodyRot - squid.xBodyRotO) * partialTick;
-        float yaw = squid.zBodyRotO + (squid.zBodyRot - squid.zBodyRotO) * partialTick;
-        GL11.glTranslatef(0.0F, 0.5F, 0.0F);
-        GL11.glRotatef(180F - bodyYaw, 0.0F, 1.0F, 0.0F);
-        GL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);
-        GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
-        GL11.glTranslatef(0.0F, -1.2F, 0.0F);
+        if (squid.isSpecial()) {
+            super.setupRotations(squid, ticksExisted, bodyYaw, partialTick);
+        } else {
+            float pitch = squid.xBodyRotO + (squid.xBodyRot - squid.xBodyRotO) * partialTick;
+            float yaw = squid.zBodyRotO + (squid.zBodyRot - squid.zBodyRotO) * partialTick;
+            GL11.glTranslatef(0.0F, 0.5F, 0.0F);
+            GL11.glRotatef(180F - bodyYaw, 0.0F, 1.0F, 0.0F);
+            GL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);
+            GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
+            GL11.glTranslatef(0.0F, -1.2F, 0.0F);
+        }
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java b/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
index 02e97ce0c..1d5b68f9d 100644
--- a/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
+++ b/src/main/java/net/minecraft/client/render/texturepack/TexturePackList.java
@@ -2,7 +2,7 @@ package net.minecraft.client.render.texturepack;
 
 import net.minecraft.client.Minecraft;
 import net.minecraft.client.render.FontRenderer;
-import net.minecraft.core.Global;
+import net.minecraft.client.sound.SoundRepository;
 import org.jetbrains.annotations.Nullable;
 
 import java.io.File;
@@ -87,8 +87,11 @@ public class TexturePackList
 		mc.renderEngine.refreshTexturesAndDisplayErrors();
 		mc.fontRenderer = new FontRenderer(mc, mc.gameSettings, "/font/default.png", mc.renderEngine);
 		mc.renderGlobal.loadRenderers();
-		mc.currentScreen.refreshFontRenderer();
+		if (mc.currentScreen != null) {
+			mc.currentScreen.refreshFontRenderer();
+		}
 		mc.renderEngine.updateDynamicTextures(false);
+		SoundRepository.reload();
 	}
 
 	public boolean updateAvailableTexturePacks() {
@@ -192,6 +195,10 @@ public class TexturePackList
     {
         return new ArrayList<>(availableTexturePacks);
     }
+    public List<TexturePack> selectedTexturePacks()
+    {
+        return new ArrayList<>(selectedPacks);
+    }
 
     public TexturePack getDefaultTexturePack()
     {
diff --git a/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java b/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
index 384e4e205..2545519d3 100644
--- a/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
+++ b/src/main/java/net/minecraft/client/render/window/GameWindowGLFW.java
@@ -1,14 +1,21 @@
 package net.minecraft.client.render.window;
 
+import static org.lwjgl.BufferUtils.createByteBuffer;
 import static org.lwjgl.glfw.GLFW.*;
 
-import java.awt.Panel;
+import java.awt.*;
+import java.awt.image.BufferedImage;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
 
+import javax.imageio.ImageIO;
 import javax.swing.JFrame;
 
+import net.minecraft.core.Global;
+import net.minecraft.core.util.helper.Color;
 import org.lwjgl.PointerBuffer;
+import org.lwjgl.glfw.GLFWImage;
 import org.lwjgl.glfw.GLFWVidMode;
 import org.lwjgl.input.Keyboard;
 import org.lwjgl.input.Mouse;
@@ -58,8 +65,8 @@ public class GameWindowGLFW implements GameWindow {
 		glfwWindowHint(GLFW_DECORATED, 1);
 		
 		// Create window
-		window = glfwCreateWindow(width, height, "Minecraft", 0, 0);
-		
+		window = glfwCreateWindow(width, height, "Better than Adventure! " + Global.VERSION, 0, 0);
+
 		// Center window
 		MonitorInfo monitor = new MonitorInfo(glfwGetPrimaryMonitor());
 		glfwSetWindowPos(window, (monitor.width - width) / 2, (monitor.height - height) / 2);
@@ -70,7 +77,25 @@ public class GameWindowGLFW implements GameWindow {
 			this.height = Math.max(1, height);
 			wasResized = true;
 		});
-		
+
+		// Setup Icon
+		iconLabel: {
+			int[] resolutions = new int[]{16, 32, 64, 128, 256};
+			GLFWImage.Buffer gb = GLFWImage.create(resolutions.length);
+			for (int i = 0; i < resolutions.length; i++) {
+				int res = resolutions[i];
+				ByteBuffer icon = getImageBuffer("/icon/" + res + ".png");
+				if (icon == null) {
+					System.err.println("Icon at resolution '" + res + "' is null! Skipping icons!");
+					gb.close();
+					break iconLabel;
+				}
+				GLFWImage iconGI = GLFWImage.create().set(res, res, icon);
+				gb.put(i, iconGI);
+			}
+			glfwSetWindowIcon(window, gb);
+		}
+
 		// Show window
 		glfwShowWindow(window);
 		
@@ -80,6 +105,7 @@ public class GameWindowGLFW implements GameWindow {
 
 		// Input setup
 		Display.setWindow(this);
+
 		
 		Method createKeyboard = null;
 		Method createMouse = null;
@@ -284,4 +310,38 @@ public class GameWindowGLFW implements GameWindow {
 			refreshRate = vidmode.refreshRate();
 		}
 	}
+
+	/**
+	 * Reads the specified image resource and returns the raw data as a ByteBuffer.
+	 *
+	 * @param resource   the resource to read
+	 * @return the resource data
+	 *
+     */
+	public static ByteBuffer getImageBuffer(String resource) {
+		try {
+			BufferedImage image = ImageIO.read(GameWindowGLFW.class.getResourceAsStream(resource));
+			ByteBuffer buf = createByteBuffer(image.getWidth() * image.getHeight() * 4);
+			// Manually filling out the damn buffer since I can't find any utility that actually does it properly
+			// I don't understand why icon loading for LWJGL3 is such a pain in the ass too
+			int index = 0;
+			for (int y = 0; y < image.getHeight(); y++) {
+				for (int x = 0; x < image.getWidth(); x++) {
+					int color = image.getRGB(x, y);
+					buf.put(index + 0, (byte) Color.redFromInt(color)); // Red
+					buf.put(index + 1, (byte) Color.greenFromInt(color)); // Green
+					buf.put(index + 2, (byte) Color.blueFromInt(color)); // Blue
+					buf.put(index + 3, (byte) Color.alphaFromInt(color)); // Alpha
+					index += 4;
+				}
+			}
+			buf.flip();
+			return buf;
+		}
+		catch (Exception e){
+			System.out.println("Couldn't open icon image...");
+			e.printStackTrace();
+			return null;
+		}
+	}
 }
diff --git a/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java b/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java
new file mode 100644
index 000000000..c49bd0eda
--- /dev/null
+++ b/src/main/java/net/minecraft/client/sound/NamedSoundRepository.java
@@ -0,0 +1,200 @@
+package net.minecraft.client.sound;
+
+import com.b100.utils.StreamUtils;
+import com.b100.utils.StringUtils;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import net.minecraft.client.render.texturepack.TexturePack;
+import net.minecraft.core.data.registry.Registry;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class NamedSoundRepository extends Registry<SoundEvent> {
+    public static final String JAR_SOUNDS_LOCATION_FORMAT = "/assets/%s/sounds/";
+    public static final String FOLDER_SOUNDS_LOCATION_FORMAT = "/resources/%s/sounds/";
+    public static final String TEXTURE_PACK_FOLDER_SOUNDS_LOCATION_FORMAT = "/packResources/%s/sounds/";
+
+    public final String namespace;
+    public final File rootFile;
+    public NamedSoundRepository(String namespace) {
+        this.namespace = namespace;
+        this.rootFile = new File(SoundRepository.mc.getMinecraftDir(), String.format(FOLDER_SOUNDS_LOCATION_FORMAT, namespace));
+        loadFromPath(String.format(JAR_SOUNDS_LOCATION_FORMAT, namespace) + "sounds.json");
+    }
+
+    public void loadFromPath(String path) {
+        List<Throwable> thrown = new ArrayList<>();
+        Map<String, SoundEvent> eventMap = new HashMap<>();
+
+        TexturePack defaultPack = SoundRepository.mc.texturePackList.getDefaultTexturePack();
+        loadFromPack(path, defaultPack, eventMap, thrown);
+
+        List<TexturePack> selectedPacks = SoundRepository.mc.texturePackList.selectedTexturePacks();
+        for (TexturePack p : selectedPacks) {
+            loadFromPack(path, p, eventMap, thrown);
+        }
+
+        File outRoot = new File(SoundRepository.mc.getMinecraftDir(), String.format(TEXTURE_PACK_FOLDER_SOUNDS_LOCATION_FORMAT, namespace));
+        outRoot.mkdirs();
+        for (Map.Entry<String, SoundEvent> e : eventMap.entrySet()) {
+            register(e.getKey(), e.getValue());
+            for (SoundEntry entry : e.getValue().getEntryBag().getEntries()) {
+                if (entry.type == SoundEntry.Type.FILE && entry.file != null && !entry.file.exists()) {
+                    entry.file = new File(outRoot, entry.name);
+                    try {
+                        entry.file.getParentFile().mkdirs();
+                        entry.file.createNewFile();
+                        StreamUtils.transferDataAndClose(entry.pack.getResourceAsStream(String.format(JAR_SOUNDS_LOCATION_FORMAT, namespace) + entry.name), Files.newOutputStream(entry.file.toPath()));
+                    } catch (Exception ex) {
+                        thrown.add(new RuntimeException("Failed to relocate entry '" + entry.name + "' to '" + entry.file + "'!", ex));
+                    }
+                }
+            }
+        }
+
+        thrown.forEach(Throwable::printStackTrace);
+    }
+
+    private void loadFromPack(String path, TexturePack pack, Map<String, SoundEvent> eventMap, List<Throwable> throwableList) {
+        if (!pack.hasFile(path)) return;
+
+        JsonObject json;
+        try {
+            json = loadStreamAsElement(pack.getResourceAsStream(path)).getAsJsonObject();
+        } catch (JsonParseException e) {
+            throwableList.add(e);
+            return;
+        }
+
+        for (Map.Entry<String, JsonElement> e : json.entrySet()) {
+            String fieldName = e.getKey();
+            JsonObject entryObj = e.getValue().getAsJsonObject();
+
+            boolean replaceEvent = false;
+            if (entryObj.has("replace")) {
+                try {
+                    replaceEvent = entryObj.get("replace").getAsBoolean();
+                } catch (RuntimeException ex) {
+                    throwableList.add(ex);
+                }
+            }
+
+            String subtitle = null;
+            if (entryObj.has("subtitle")) {
+                try {
+                    subtitle = entryObj.get("subtitle").getAsString();
+                } catch (RuntimeException ex) {
+                    throwableList.add(ex);
+                }
+            }
+
+            SoundEvent soundEvent = eventMap.get(fieldName);
+            if (soundEvent == null || replaceEvent) {
+                soundEvent = new SoundEvent(fieldName, subtitle);
+            }
+            if (subtitle != null) {
+                soundEvent.subtitleKey = subtitle;
+            }
+
+            soundLabel:
+            {
+                if (entryObj.has("sounds")) {
+
+                    JsonArray sounds;
+                    try {
+                        sounds = entryObj.getAsJsonArray("sounds");
+                    } catch (RuntimeException ex) {
+                        throwableList.add(ex);
+                        break soundLabel;
+                    }
+
+                    for (JsonElement element : sounds) {
+                        if (element.isJsonPrimitive()) {
+                            try {
+                                soundEvent.addSoundEntry(getSoundEntry(pack, element.getAsString()));
+                            } catch (RuntimeException ex) {
+                                throwableList.add(ex);
+                            }
+                        } else if (element.isJsonObject()) {
+                            try {
+                                soundEvent.addSoundEntry(getSoundEntry(pack, element.getAsJsonObject()));
+                            } catch (RuntimeException ex) {
+                                throwableList.add(ex);
+                            }
+                        }
+                    }
+                }
+            }
+            eventMap.put(fieldName, soundEvent);
+        }
+    }
+
+    public SoundEntry getSoundEntry(TexturePack pack, String path) {
+        return new SoundEntry(this, pack,path, 1, false, SoundEntry.Type.FILE);
+    }
+
+    public SoundEntry getSoundEntry(TexturePack pack, JsonObject jObj) throws JsonParseException {
+        String name = jObj.get("name").getAsString(); // Required
+
+        float volume = 1;
+        if (jObj.has("volume")) {
+            volume = jObj.get("volume").getAsFloat();
+        }
+
+        float pitch = 1;
+        if (jObj.has("pitch")) {
+            pitch = jObj.get("pitch").getAsFloat();
+        }
+
+        int weight = 1;
+        if (jObj.has("weight")) {
+            weight = jObj.get("weight").getAsInt();
+        }
+
+        boolean stream = false;
+        if (jObj.has("stream")) {
+            stream = jObj.get("stream").getAsBoolean();
+        }
+
+        int attenuation_distance = 16;
+        if (jObj.has("attenuation_distance")) {
+            attenuation_distance = jObj.get("attenuation_distance").getAsInt();
+        }
+
+        boolean preload = false;
+        if (jObj.has("preload")) {
+            preload = jObj.get("preload").getAsBoolean();
+        }
+
+        String type = "file";
+        if (jObj.has("type")) {
+            type = jObj.get("type").getAsString();
+        }
+
+        return new SoundEntry(this, pack, name, weight, stream, SoundEntry.Type.valueOf(type.toUpperCase(Locale.ROOT)));
+    }
+
+    private JsonElement loadStreamAsElement(InputStream stream) throws JsonParseException {
+        return JsonParser.parseString(StringUtils.readInputString(stream));
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("Sound Repo ").append(namespace).append("\n");
+        for (SoundEvent e : this) {
+            builder.append(e.toString()).append("\n");
+        }
+        return builder.toString();
+    }
+}
diff --git a/src/main/java/net/minecraft/client/sound/SoundEngine.java b/src/main/java/net/minecraft/client/sound/SoundEngine.java
index 7d107b2a6..39640ef00 100644
--- a/src/main/java/net/minecraft/client/sound/SoundEngine.java
+++ b/src/main/java/net/minecraft/client/sound/SoundEngine.java
@@ -1,12 +1,10 @@
 package net.minecraft.client.sound;
 
-import java.io.File;
-import java.io.IOException;
+import java.net.URL;
 import java.util.Random;
 
 import net.betterthanadventure.sound.LibraryLWJGL3OpenAL;
 import net.minecraft.client.Minecraft;
-import net.minecraft.core.Global;
 import net.minecraft.core.entity.Mob;
 import net.minecraft.core.sound.SoundCategory;
 import net.minecraft.core.util.helper.MathHelper;
@@ -15,23 +13,17 @@ import paulscode.sound.SoundSystem;
 import paulscode.sound.SoundSystemConfig;
 import paulscode.sound.codecs.CodecJOrbis;
 import paulscode.sound.codecs.CodecWav;
-import paulscode.sound.libraries.LibraryLWJGLOpenAL;
-
-// Referenced classes of package net.minecraft.src:
-//            SoundRepository, GameSettings, CodecMus, LocalPlayer,
-//            MathHelper, World, SoundEntry, Mob
 
 public class SoundEngine
 {
-	private static final int SOUND_DISTANCE = 16;
-	public static final int MUSIC_INTERVAL = 6000;
+	private static final int SOUND_DISTANCE = 16; // TODO have the sound engine handle sound distance again
+	private static final int MUSIC_INTERVAL = 6000;
 	private static SoundSystem soundSystem;
 	private static boolean loaded = false;
 
-	public final SoundRepository soundRepo;
-	public final SoundRepository streamingRepo;
-	public final SoundRepository musicRepo;
-	public final SoundRepository caveRepo;
+	public static final String BG_MUSIC = "BgMusic";
+	public static final String STREAMING = "Streaming";
+
 	private int idCounter;
 	private GameSettings options;
 	private final Random random;
@@ -39,67 +31,12 @@ public class SoundEngine
 	public int ticksBeforeMusic;
 	private boolean muted = false;
 
-	private static void loadModAudio(final String directory, final SoundRepository targetRepo)
-	{
-		final File file = Minecraft.getAppDir(directory);
-		try {
-			walkFolder(file, file, targetRepo);
-		} catch (final IOException ioexception) {
-			ioexception.printStackTrace();
-		}
-	}
-
-	private static void loadDevAudio(final String directory, final SoundRepository targetRepo)
-	{
-		final File file = new File(directory);
-		try {
-			walkFolder(file, file, targetRepo);
-		} catch (final IOException ioexception) {
-			ioexception.printStackTrace();
-		}
-	}
-
-    private static void walkFolder(final File baseFile, final File currentFile, final SoundRepository targetRepo) throws IOException {
-        if (currentFile.exists() || currentFile.mkdirs()) {
-            final File[] filesInCurrentDir = currentFile.listFiles();
-            if (filesInCurrentDir != null) {
-                for (File file : filesInCurrentDir) {
-                    if (!file.getName().startsWith(".")) {
-                        if (file.isDirectory()) {
-                            walkFolder(baseFile, file, targetRepo);
-                        } else if (file.isFile()) {
-                            final String name = file.getPath().substring(baseFile.getPath().length() + 1).replace('\\', '/');
-                            targetRepo.addSound(name, file);
-                        }
-                    }
-                }
-
-            }
-        }
-    }
-
 	public SoundEngine() {
-        soundRepo = new SoundRepository();
-        streamingRepo = new SoundRepository();
-        musicRepo = new SoundRepository();
-        caveRepo = new SoundRepository();
         idCounter = 0;
         random = new Random();
         ticksBeforeMusic = random.nextInt(MUSIC_INTERVAL);
     }
 
-    public void addMusic(final String name, final File file) {
-        musicRepo.addSound(name, file);
-    }
-
-    public void addSound(final String name, final File file) {
-        soundRepo.addSound(name, file);
-    }
-
-    public void addStreaming(final String name, final File file) {
-        streamingRepo.addSound(name, file);
-    }
-
 	public void destroy() {
 		if (loaded) {
 			soundSystem.cleanup();
@@ -141,21 +78,10 @@ public class SoundEngine
     }
 
     public void init(final GameSettings gamesettings) {
-        streamingRepo.trimDigits = false;
         options = gamesettings;
         if (!loaded && (gamesettings != null && SoundCategoryHelper.isAnyEnabled(gamesettings))) {
             loadLibrary();
         }
-		if (gamesettings != null && gamesettings.enableDevResourceLoading.value) {
-			loadDevAudio("devResources/sound", soundRepo);
-			loadDevAudio("devResources/streaming", streamingRepo);
-			loadDevAudio("devResources/music", musicRepo);
-			loadDevAudio("devResources/cavemusic", caveRepo);
-		}
-        loadModAudio("minecraft-bta/resources/mod/sound", soundRepo);
-        loadModAudio("minecraft-bta/resources/mod/streaming", streamingRepo);
-        loadModAudio("minecraft-bta/resources/mod/music", musicRepo);
-        loadModAudio("minecraft-bta/resources/mod/cavemusic", caveRepo);
 		mc = Minecraft.getMinecraft(this);
     }
 
@@ -165,9 +91,9 @@ public class SoundEngine
         }
         if (soundSystem != null && loaded) {
             if (SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options) == 0.0F) {
-                soundSystem.stop("BgMusic");
+                soundSystem.stop(BG_MUSIC);
             } else {
-                soundSystem.setVolume("BgMusic", SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
+                soundSystem.setVolume(BG_MUSIC, SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
             }
         }
     }
@@ -177,115 +103,167 @@ public class SoundEngine
             return;
         }
 
-        if (!soundSystem.playing("BgMusic") && !soundSystem.playing("streaming")) {
+        if (!soundSystem.playing(BG_MUSIC) && !soundSystem.playing(STREAMING)) {
             if (ticksBeforeMusic > 0) {
                 ticksBeforeMusic--;
                 return;
             }
-            SoundEntry entry;
+
+			// TODO a more sane way of grouping music pools with our new system
+			SoundEvent event;
             if (mc != null && mc.thePlayer != null && !mc.thePlayer.world.canBlockSeeTheSky(MathHelper.floor(mc.thePlayer.x), MathHelper.floor(mc.thePlayer.y), MathHelper.floor(mc.thePlayer.z))) {
-                entry = caveRepo.getAnyEntry();
+				event = SoundRepository.SOUNDS.getRandomSoundFromCategory("ambient.cave.");
             } else {
-                entry = musicRepo.getAnyEntry();
+				event = SoundRepository.SOUNDS.getRandomSoundFromCategory("music.");
             }
+			if (event == null) return;
+			SoundEntry entry = event.getRandomEntry();
             if (entry != null) {
                 ticksBeforeMusic = random.nextInt(MUSIC_INTERVAL) + MUSIC_INTERVAL;
-                soundSystem.backgroundMusic("BgMusic", entry.url, entry.name, false);
+                soundSystem.backgroundMusic("BgMusic", entry.getURL(), entry.name, false);
                 soundSystem.setVolume("BgMusic", SoundCategoryHelper.getEffectiveVolume(SoundCategory.MUSIC, options));
                 soundSystem.play("BgMusic");
             }
         }
     }
 
-	public void playSoundAt(final String soundPath, SoundCategory category, final float x, final float y, final float z, float volume, final float pitch)
-	{
+	public void playSound(String name, SoundCategory category, float volume, float pitch) {
+		playSound(SoundRepository.SOUNDS.getSoundEntry(name), category, volume, pitch);
+	}
+
+	public void playSound(SoundEntry entry, SoundCategory category, float volume, float pitch) {
 		if (!loaded || soundSystem == null || muted || !SoundCategoryHelper.isAnyEnabled(options))
 		{
 			return;
 		}
-		final SoundEntry soundEntry = soundRepo.getEntry(soundPath);
-		if (soundEntry != null && volume > 0.0F)
-		{
-			idCounter = (idCounter + 1) % 256;
-			final String soundIdName = "sound_" + idCounter;
-			float f5 = 16F;
-			if (volume > 1.0F)
-			{
-				f5 *= volume;
-			}
-			soundSystem.newSource(volume > 1.0F, soundIdName, soundEntry.url, soundEntry.name, false, x, y, z, 2, f5);
-			soundSystem.setPitch(soundIdName, pitch);
-			if (volume > 1.0F)
-			{
-				volume = 1.0F;
-			}
-			soundSystem.setVolume(soundIdName, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
-			soundSystem.play(soundIdName);
-		}
+		idCounter = (idCounter + 1) % 256;
+		final String soundName = "sound_" + idCounter;
+		playSoundWithID(entry, category, volume, pitch, soundName);
 	}
 
-	public void playSound(final String soundPath, SoundCategory category, float volume, final float pitch)
-	{
+	public void playSoundAt(String name, SoundCategory category, float x, float y, float z, float volume, float pitch) {
+		playSoundAt(SoundRepository.SOUNDS.getSoundEntry(name), category, x, y, z, volume, pitch);
+	}
+
+	public void playSoundAt(SoundEntry entry, SoundCategory category, float x, float y, float z, float volume, float pitch) {
 		if (!loaded || soundSystem == null || muted || !SoundCategoryHelper.isAnyEnabled(options))
 		{
 			return;
 		}
-		final SoundEntry soundEntry = soundRepo.getEntry(soundPath);
 		idCounter = (idCounter + 1) % 256;
 		final String soundName = "sound_" + idCounter;
-		playSoundEntry(soundEntry, soundName, category, volume, pitch);
+		playSoundWithIdAtPos(entry, category, x, y, z, volume, pitch, soundName);
 	}
-	public void playSoundEntry(SoundEntry entry, String soundSourceID, SoundCategory category, float volume, final float pitch) {
-		if (entry != null) {
-			soundSystem.newSource(false, soundSourceID, entry.url, entry.name, false, 0.0F, 0.0F, 0.0F, 0, 0.0F);
-			if (volume > 1.0F)
-			{
-				volume = 1.0F;
-			}
-			volume *= 0.25F;
-			soundSystem.setPitch(soundSourceID, pitch);
-			soundSystem.setVolume(soundSourceID, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
-			soundSystem.play(soundSourceID);
-		}
+
+	public void playSoundWithID(String name, SoundCategory category, float volume, final float pitch, String soundID) {
+		playSoundWithID(SoundRepository.SOUNDS.getSoundEntry(name), category, volume, pitch, soundID);
 	}
-	public void playSoundId(final String soundPath, SoundCategory category, float volume, final float pitch, String soundID){
+
+	public void playSoundWithID(SoundEntry entry, SoundCategory category, float volume, final float pitch, String soundID) {
 		if (!loaded || soundSystem == null || muted || !SoundCategoryHelper.isAnyEnabled(options))
 		{
 			return;
 		}
-		final SoundEntry soundEntry = soundRepo.getEntry(soundPath);
-		playSoundEntry(soundEntry, soundID, category, volume, pitch);
+		if (entry != null) {
+			if (entry.type == SoundEntry.Type.FILE) {
+				URL url = entry.getURL();
+				if (url != null){
+					if (entry.shouldStream) {
+						soundSystem.newStreamingSource(false, soundID, url, entry.name, false, 0, 0, 0, 2, 0);
+					} else {
+						soundSystem.newSource(false, soundID, url, entry.name, false, 0, 0, 0, 0, 0);
+					}
+					if (volume > 1.0F)
+					{
+						volume = 1.0F;
+					}
+					volume *= 0.25F;
+					soundSystem.setPitch(soundID, pitch);
+					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
+					soundSystem.play(soundID);
+				}
+			} else if (entry.type == SoundEntry.Type.EVENT) {
+				playSoundWithIdAtPos(entry.name, category, 0, 0, 0, volume, pitch, soundID);
+			}
+		}
+	}
+
+	public void playSoundWithIdAtPos(String name, SoundCategory category, float x, float y, float z, float volume, final float pitch, String soundID) {
+		playSoundWithIdAtPos(SoundRepository.SOUNDS.getSoundEntry(name), category, x, y, z, volume, pitch, soundID);
+	}
+
+	public void playSoundWithIdAtPos(SoundEntry entry, SoundCategory category, float x, float y, float z, float volume, final float pitch, String soundID) {
+		if (entry != null) {
+			if (entry.type == SoundEntry.Type.FILE) {
+				URL url = entry.getURL();
+				if (url != null){
+					float f5 = 16F;
+					if (volume > 1.0F)
+					{
+						f5 *= volume;
+					}
+					if (entry.shouldStream) {
+						soundSystem.newStreamingSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 2, f5);
+					} else {
+						soundSystem.newSource(volume > 1.0F, soundID, url, entry.name, false, x, y, z, 0, f5);
+					}
+					if (volume > 1.0F) {
+						volume = 1.0F;
+					}
+					soundSystem.setPitch(soundID, pitch);
+					soundSystem.setVolume(soundID, volume * SoundCategoryHelper.getEffectiveVolume(category, options));
+					soundSystem.play(soundID);
+				}
+			} else if (entry.type == SoundEntry.Type.EVENT) {
+				playSoundWithIdAtPos(entry.name, category, x, y, z, volume, pitch, soundID);
+			}
+		}
+	}
+
+	public void playMusic(String name, float x, float y, float z, float volume, float pitch) {
+		playMusic(SoundRepository.SOUNDS.getSoundEntry(name), x, y, z, volume, pitch);
 	}
 
-	public void playStreaming(final String soundPath, final float x, final float y, final float z, final float volume, final float pitch)
+	public void playMusic(SoundEntry entry, float x, float y, float z, float volume, float pitch)
 	{
 		if (!loaded || soundSystem == null || muted || !SoundCategoryHelper.isAnyEnabled(options))
 		{
 			return;
 		}
-		final String streaming = "streaming";
-		if (soundSystem.playing("streaming"))
+		final String streaming = STREAMING;
+		if (soundSystem.playing(STREAMING))
 		{
-			soundSystem.stop("streaming");
+			soundSystem.stop(STREAMING);
 		}
-		if (soundPath == null)
+		if (entry == null)
 		{
 			return;
 		}
-		final SoundEntry soundEntry = streamingRepo.getEntry(soundPath);
-		if (soundEntry != null && volume > 0.0F)
+		if (volume > 0.0F)
 		{
-			if (soundSystem.playing("BgMusic"))
+			if (soundSystem.playing(BG_MUSIC))
 			{
-				soundSystem.stop("BgMusic");
+				soundSystem.stop(BG_MUSIC);
 			}
 			final float streamingVolume = 16F;
-			soundSystem.newStreamingSource(true, streaming, soundEntry.url, soundEntry.name, false, x, y, z, 2, streamingVolume * 4F);
-			soundSystem.setVolume(streaming, 0.5F * options.masterVolume.value);
-			soundSystem.play(streaming);
+			if (entry.type == SoundEntry.Type.FILE) {
+				URL url = entry.getURL();
+				if (url != null) {
+					soundSystem.newStreamingSource(true, streaming, url, entry.name, false, x, y, z, 2, streamingVolume * 4F);
+					soundSystem.setVolume(streaming, 0.5F * options.masterVolume.value);
+					soundSystem.play(streaming);
+				}
+			} else if (entry.type == SoundEntry.Type.EVENT) {
+				playMusic(entry.name, x, y, z, volume, pitch);
+			}
 		}
 	}
 
+	public void stopMusic() {
+		soundSystem.stop(BG_MUSIC);
+		soundSystem.stop(STREAMING);
+	}
+
     private void loadLibrary() {
         try {
 			float[] volumeStore = new float[SoundCategory.values().length];
diff --git a/src/main/java/net/minecraft/client/sound/SoundEntry.java b/src/main/java/net/minecraft/client/sound/SoundEntry.java
index 8aa1b1c94..c08925db0 100644
--- a/src/main/java/net/minecraft/client/sound/SoundEntry.java
+++ b/src/main/java/net/minecraft/client/sound/SoundEntry.java
@@ -1,17 +1,69 @@
 package net.minecraft.client.sound;
 
+import net.minecraft.client.render.texturepack.TexturePack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.net.MalformedURLException;
 import java.net.URL;
 
-public class SoundEntry
-{
+public class SoundEntry {
+    public final @NotNull NamedSoundRepository parent;
+    public final @NotNull TexturePack pack;
+
+    public final @NotNull String name;
+
+    /**
+     * Weight of entry in random bag
+     */
+    public final int weight;
+
+    /**
+     *  Whether the audio should be played as a stream or not
+     */
+    public final boolean shouldStream;
+
+    /**
+     * How name field is interpreted
+     */
+    public final @NotNull Type type;
 
-    public String soundID;
-    public String name;
-    public URL url;
+    protected @Nullable File file;
 
-    public SoundEntry(String soundID, String name, URL url) {
-        this.soundID = soundID;
+    public SoundEntry(@NotNull NamedSoundRepository parent, @NotNull TexturePack pack, @NotNull String name, int weight, boolean shouldStream, @NotNull Type type) {
+        this.parent = parent;
+        this.pack = pack;
         this.name = name;
-        this.url = url;
+        this.weight = weight;
+        this.shouldStream = shouldStream;
+        this.type = type;
+        if (type == Type.FILE) {
+            file = new File(parent.rootFile, name);
+        } else {
+            file = null;
+        }
+    }
+
+    public @Nullable URL getURL() {
+        if (file == null || !file.exists()) return null;
+        try {
+            return file.toURI().toURL();
+        } catch (MalformedURLException e) {
+            System.err.println("Error getting url for sound '" + name + "'");
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public enum Type {
+        /**
+         * Name interpreted as a file path from a namespace
+         */
+        FILE,
+        /**
+         * Name interpreted as a link to a different Event pool
+         */
+        EVENT;
     }
 }
diff --git a/src/main/java/net/minecraft/client/sound/SoundEvent.java b/src/main/java/net/minecraft/client/sound/SoundEvent.java
new file mode 100644
index 000000000..5cd95112f
--- /dev/null
+++ b/src/main/java/net/minecraft/client/sound/SoundEvent.java
@@ -0,0 +1,64 @@
+package net.minecraft.client.sound;
+
+import net.minecraft.core.WeightedRandomBag;
+import net.minecraft.core.lang.I18n;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Random;
+
+public class SoundEvent {
+    private final WeightedRandomBag<SoundEntry> entryBag = new WeightedRandomBag<>();
+
+    private final @NotNull String id;
+    protected @Nullable String subtitleKey;
+    public SoundEvent(@NotNull String eventID, @Nullable String subtitleKey) {
+        this.id = eventID;
+        this.subtitleKey = subtitleKey;
+    }
+
+    public void addSoundEntry(SoundEntry entry) {
+        entryBag.addEntry(entry, entry.weight);
+    }
+
+    protected void clearSoundEntries() {
+        entryBag.clear();
+    }
+
+    public String getEventID() {
+        return id;
+    }
+
+    public SoundEntry getRandomEntry() {
+        return entryBag.getRandom();
+    }
+
+    public SoundEntry getRandomEntry(Random r) {
+        return entryBag.getRandom(r);
+    }
+
+    public @Nullable String getSubtitleKey() {
+        return subtitleKey;
+    }
+
+    public @Nullable String getSubtitleTranslated() {
+        return I18n.getInstance().translateKey(subtitleKey);
+    }
+
+    public boolean hasSubtitle() {
+        return subtitleKey != null;
+    }
+
+    public WeightedRandomBag<SoundEntry> getEntryBag() {
+        return entryBag;
+    }
+
+    @Override
+    public String toString() {
+        return "SoundEvent{" +
+            "entryBag=" + entryBag +
+            ", id='" + id + '\'' +
+            ", subtitleKey='" + subtitleKey + '\'' +
+            '}';
+    }
+}
diff --git a/src/main/java/net/minecraft/client/sound/SoundRepository.java b/src/main/java/net/minecraft/client/sound/SoundRepository.java
index 46f49d1ff..f0da324ee 100644
--- a/src/main/java/net/minecraft/client/sound/SoundRepository.java
+++ b/src/main/java/net/minecraft/client/sound/SoundRepository.java
@@ -1,83 +1,104 @@
 package net.minecraft.client.sound;
 
-import java.io.File;
-import java.net.MalformedURLException;
-import java.util.*;
-
-// Referenced classes of package net.minecraft.src:
-//            SoundEntry
-
-public class SoundRepository
-{
-    private final Random random;
-    private final Map<String, List<SoundEntry>> urls;
-    private final List<SoundEntry> allEntries;
-    public int entryCount;
-    public boolean trimDigits;
-
-
-    public SoundRepository()
-    {
-        random = new Random();
-        urls = new HashMap<>();
-        allEntries = new ArrayList<>();
-        entryCount = 0;
-        trimDigits = true;
+import net.minecraft.client.Minecraft;
+import net.minecraft.core.data.registry.Registry;
+import net.minecraft.core.util.collection.NamespaceID;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class SoundRepository extends Registry<NamedSoundRepository> {
+    protected static Minecraft mc = null;
+    public static SoundRepository SOUNDS = null;
+    public SoundRepository() {
+        registerNamespace("minecraft");
+    }
+
+    public void registerNamespace(@NotNull String namespace) {
+        register(namespace, new NamedSoundRepository(namespace));
+    }
+
+    public @Nullable SoundEvent getSoundEvent(@Nullable String key) {
+        if (key == null) return null;
+        return getSoundEvent(makeNamespaceFromKey(key));
+    }
+
+    public @Nullable SoundEvent getSoundEvent(@Nullable NamespaceID namespaceID) {
+        if (namespaceID == null) return null;
+        NamedSoundRepository soundRepository = getItem(namespaceID.namespace);
+        if (soundRepository == null) {
+            System.err.println("Could not find sound repository under namespace '" + namespaceID.namespace + "'!");
+            return null;
+        }
+        return soundRepository.getItem(namespaceID.value);
+    }
+
+    public @Nullable SoundEntry getSoundEntry(@Nullable String key) {
+        if (key == null) return null;
+        return getSoundEntry(makeNamespaceFromKey(key));
     }
 
-    public SoundEntry addSound(String fileName, File file)
-    {
-        String id = fileName;
-        try
-        {
-            id = id.substring(0, id.indexOf("."));
-            if(trimDigits)
-            {
-                while (Character.isDigit(id.charAt(id.length() - 1))) {
-                    id = id.substring(0, id.length() - 1);
+    public @Nullable SoundEntry getSoundEntry(@Nullable NamespaceID namespaceID) {
+        if (namespaceID == null) return null;
+        SoundEvent event = getSoundEvent(namespaceID);
+        if (event == null) {
+            System.err.println("Count not find sound event in namespace '" + namespaceID.namespace + "' matching key '" + namespaceID.value + "'!");
+            return null;
+        }
+        return event.getRandomEntry();
+    }
+
+    public @Nullable SoundEvent getRandomSoundFromCategory(@NotNull String category) {
+        List<SoundEvent> eventList = new ArrayList<>();
+        for (NamedSoundRepository nsr : this) {
+            nsr.iterator().forEachRemaining(soundEvent -> {
+                if (soundEvent.getEventID().startsWith(category)) {
+                    eventList.add(soundEvent);
                 }
-            }
-            id = id.replaceAll("/", ".");
-            if(!urls.containsKey(id))
-            {
-                urls.put(id, new ArrayList<>());
-            }
-            SoundEntry soundEntry = new SoundEntry(id, fileName, file.toURI().toURL());
-            urls.get(id).add(soundEntry);
-            allEntries.add(soundEntry);
-            entryCount++;
-            return soundEntry;
+            });
         }
-        catch(MalformedURLException e)
-        {
-        	throw new RuntimeException("Adding Sound: " + id + " ("+file.getAbsolutePath()+")", e);
+        if (eventList.isEmpty()) return null;
+        return eventList.get(new Random().nextInt(eventList.size()));
+    }
+
+    public List<SoundEvent> getAllEvents() {
+        List<SoundEvent> eventList = new ArrayList<>();
+
+        for (NamedSoundRepository nsr : this) {
+            nsr.iterator().forEachRemaining(eventList::add);
         }
+
+        return eventList;
     }
 
-    public SoundEntry getEntry(String name)
-    {
-        List<SoundEntry> values = urls.get(name);
-        if(values == null)
-        {
-            return null;
-        } else
-        {
-            return values.get(random.nextInt(values.size()));
+    private NamespaceID makeNamespaceFromKey(@NotNull String key) {
+        String namespace;
+        String value;
+        if (!key.contains(":")) {
+            namespace = "minecraft";
+            value = key;
+        } else {
+            String[] split = key.split(":");
+            if (split.length != 2) throw new IllegalArgumentException("Invalid key '" + key + "', there can only be 1 namespace value delimiter of ':'!");
+            namespace = split[0];
+            value = split[1];
+            if (namespace.isEmpty()) throw new IllegalArgumentException("Invalid key '" + key + "', Namespace must not be empty!");
         }
+        return new NamespaceID(namespace, value);
     }
 
-    public SoundEntry getAnyEntry()
-    {
-        if(allEntries.isEmpty())
-        {
-            return null;
-        } else
-        {
-            return allEntries.get(random.nextInt(allEntries.size()));
+    public static void initialize(Minecraft mc) {
+        SoundRepository.mc = mc;
+        if (SOUNDS == null) {
+            reload();
         }
     }
 
-    public List<SoundEntry> getAllEntries() {
-        return allEntries;
+    public static void reload() {
+        SOUNDS = new SoundRepository();
     }
+
 }
diff --git a/src/main/java/net/minecraft/core/WeightedRandomBag.java b/src/main/java/net/minecraft/core/WeightedRandomBag.java
index d0e1c8195..836ff9c70 100644
--- a/src/main/java/net/minecraft/core/WeightedRandomBag.java
+++ b/src/main/java/net/minecraft/core/WeightedRandomBag.java
@@ -78,4 +78,12 @@ public class WeightedRandomBag<T> {
         entries.clear();
         accumulatedWeight = 0;
     }
+
+    @Override
+    public String toString() {
+        return "WeightedRandomBag{" +
+            "entries=" + entries +
+            ", accumulatedWeight=" + accumulatedWeight +
+            '}';
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/animal/SquidMob.java b/src/main/java/net/minecraft/core/entity/animal/SquidMob.java
index 1ee9c5d3a..3f2357284 100644
--- a/src/main/java/net/minecraft/core/entity/animal/SquidMob.java
+++ b/src/main/java/net/minecraft/core/entity/animal/SquidMob.java
@@ -5,9 +5,11 @@ package net.minecraft.core.entity.animal;
 //            Material, World, MathHelper, NBTTagCompound, 
 //            Player
 
+import net.minecraft.core.MD5String;
 import net.minecraft.core.WeightedRandomLootObject;
 import net.minecraft.core.block.Block;
 import net.minecraft.core.block.material.Material;
+import net.minecraft.core.entity.player.Player;
 import net.minecraft.core.item.Items;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.DamageType;
@@ -84,7 +86,7 @@ public class SquidMob extends WaterAnimal
                 tentacleSpeed = (1.0F / (random.nextFloat() + 1.0F)) * 0.2F;
             }
         }
-        if(isInWater())
+        if(isInWater() && !isSpecial())
         {
             if(tentacleMovement < MathHelper.PI) // Speed burst
             {
@@ -118,19 +120,22 @@ public class SquidMob extends WaterAnimal
         } else
         {
             tentacleAngle = MathHelper.abs(MathHelper.sin(tentacleMovement)) * MathHelper.PI * 0.25F;
+            if (!isSpecial()) {
 
-            if(!isMultiplayerEntity)
-            {
-                xd = 0.0D;
-                yd -= 0.08D;
-                yd *= 0.98D;
-                zd = 0.0D;
+                if(!isMultiplayerEntity)
+                {
+                    xd = 0.0D;
+                    yd -= 0.08D;
+                    yd *= 0.98D;
+                    zd = 0.0D;
+                }
+                xBodyRot += (double)(-90F - xBodyRot) * 0.02D;
             }
-            xBodyRot += (double)(-90F - xBodyRot) * 0.02D;
         }
     }
     @Override
     public void trySuffocate(){
+        if (isSpecial()) return;
         if(isAlive() && !isUnderLiquid(Material.water) && canBreatheUnderwater())
         {
             airSupply--;
@@ -149,12 +154,24 @@ public class SquidMob extends WaterAnimal
     @Override
 	public void moveEntityWithHeading(float moveStrafing, float moveForward)
     {
-        move(xd, yd, zd);
+        if (isSpecial()) {
+            super.moveEntityWithHeading(moveStrafing, moveForward);
+        } else {
+            move(xd, yd, zd);
+        }
     }
 
     @Override
 	protected void updateAI()
     {
+        if (isSpecial()) {
+            Player closest = world.getClosestPlayer(x, y, z, 10);
+            if (closest != null) {
+                setTarget(closest);
+            }
+            super.updateAI();
+            return;
+        }
         if(random.nextInt(50) == 0 || !wasInWater || tx == 0.0F && ty == 0.0F && tz == 0.0F)
         {
             float f = random.nextFloat() * MathHelper.PI * 2.0F;
@@ -214,4 +231,8 @@ public class SquidMob extends WaterAnimal
     protected boolean makeStepSound() {
     	return false;
     }
+
+    public boolean isSpecial() {
+        return nickname != null && nickname.hashCode() == 678229435;
+    }
 }
diff --git a/src/main/java/net/minecraft/core/entity/monster/GhastMob.java b/src/main/java/net/minecraft/core/entity/monster/GhastMob.java
index 8b06efdf9..b7d47da47 100644
--- a/src/main/java/net/minecraft/core/entity/monster/GhastMob.java
+++ b/src/main/java/net/minecraft/core/entity/monster/GhastMob.java
@@ -63,7 +63,7 @@ public class GhastMob extends FlyingMob
         }
         else
         {
-            return "/assets/minecraft/textures/entity/ghast_fire/" + getSkinVariant() + ".png";
+            return "/assets/minecraft/textures/entity/ghast_fire/" + getTextureReference() + ".png";
         }
     }
 
@@ -180,12 +180,12 @@ public class GhastMob extends FlyingMob
                 if(attackCharge == 20)
                 {
                     world.playSoundAtEntity(null, this, "mob.ghast.fireball", getSoundVolume(), (random.nextFloat() - random.nextFloat()) * 0.2F + 1.0F);
-                    FireballProjectile entityfireball = new FireballProjectile(world, this, vX, vY, vZ);
+                    FireballProjectile fireball = new FireballProjectile(world, this, vX, vY, vZ);
 
-                    entityfireball.x = x + vec3.x * d8;
-                    entityfireball.y = y + (double)(bbHeight / 2.0F) + 0.5D;
-                    entityfireball.z = z + vec3.z * d8;
-                    world.entityJoinedWorld(entityfireball);
+                    fireball.x = x + vec3.x * d8;
+                    fireball.y = y + (double)(bbHeight / 2.0F) + 0.5D;
+                    fireball.z = z + vec3.z * d8;
+                    world.entityJoinedWorld(fireball);
                     attackCharge = -40;
                 }
             } else
diff --git a/src/main/java/net/minecraft/core/entity/player/Player.java b/src/main/java/net/minecraft/core/entity/player/Player.java
index 26f1b0456..0e28885db 100644
--- a/src/main/java/net/minecraft/core/entity/player/Player.java
+++ b/src/main/java/net/minecraft/core/entity/player/Player.java
@@ -12,14 +12,14 @@ import net.minecraft.core.block.Blocks;
 import net.minecraft.core.block.entity.BlockEntity;
 import net.minecraft.core.block.entity.DispenserBlockEntity;
 import net.minecraft.core.block.entity.FlagBlockEntity;
+import net.minecraft.core.block.entity.FurnaceBlockEntity;
 import net.minecraft.core.block.entity.SignBlockEntity;
 import net.minecraft.core.block.entity.TrommelBlockEntity;
-import net.minecraft.core.block.entity.FurnaceBlockEntity;
 import net.minecraft.core.block.material.Material;
 import net.minecraft.core.data.gamerule.GameRules;
 import net.minecraft.core.entity.Entity;
-import net.minecraft.core.entity.FishingBobberEntity;
 import net.minecraft.core.entity.EntityDispatcher;
+import net.minecraft.core.entity.FishingBobberEntity;
 import net.minecraft.core.entity.ItemEntity;
 import net.minecraft.core.entity.LightningEntity;
 import net.minecraft.core.entity.Mob;
@@ -30,32 +30,32 @@ import net.minecraft.core.entity.monster.CreeperMob;
 import net.minecraft.core.entity.monster.GhastMob;
 import net.minecraft.core.entity.monster.GiantMob;
 import net.minecraft.core.entity.monster.Monster;
-import net.minecraft.core.entity.monster.ZombiePigMob;
 import net.minecraft.core.entity.monster.SkeletonMob;
 import net.minecraft.core.entity.monster.SlimeMob;
 import net.minecraft.core.entity.monster.SnowmanMob;
 import net.minecraft.core.entity.monster.SpiderMob;
 import net.minecraft.core.entity.monster.ZombieMob;
+import net.minecraft.core.entity.monster.ZombiePigMob;
 import net.minecraft.core.entity.projectile.ArrowProjectile;
-import net.minecraft.core.entity.projectile.GoldenArrowProjectile;
 import net.minecraft.core.entity.projectile.CannonballProjectile;
 import net.minecraft.core.entity.projectile.FireballProjectile;
+import net.minecraft.core.entity.projectile.GoldenArrowProjectile;
 import net.minecraft.core.entity.vehicle.BoatEntity;
 import net.minecraft.core.entity.vehicle.MinecartEntity;
 import net.minecraft.core.enums.ArtType;
 import net.minecraft.core.enums.EnumDropCause;
 import net.minecraft.core.enums.EnumSleepStatus;
 import net.minecraft.core.item.Item;
-import net.minecraft.core.item.Items;
 import net.minecraft.core.item.ItemStack;
+import net.minecraft.core.item.Items;
 import net.minecraft.core.item.tool.SwordToolItem;
 import net.minecraft.core.lang.I18n;
 import net.minecraft.core.net.command.TextFormatting;
 import net.minecraft.core.player.gamemode.Gamemode;
-import net.minecraft.core.player.inventory.menu.AbstractContainerMenu;
-import net.minecraft.core.player.inventory.menu.InventoryMenu;
 import net.minecraft.core.player.inventory.container.Container;
 import net.minecraft.core.player.inventory.container.Inventory;
+import net.minecraft.core.player.inventory.menu.AbstractContainerMenu;
+import net.minecraft.core.player.inventory.menu.InventoryMenu;
 import net.minecraft.core.util.collection.NamespaceID;
 import net.minecraft.core.util.helper.DamageType;
 import net.minecraft.core.util.helper.MathHelper;
@@ -69,7 +69,6 @@ import net.minecraft.server.entity.player.ServerPlayer;
 
 import java.util.ArrayList;
 import java.util.Comparator;
-import java.util.Iterator;
 import java.util.List;
 
 public abstract class Player extends Mob
@@ -871,40 +870,31 @@ public abstract class Player extends Mob
         return false;
     }
 
-    protected void alertWolves(Mob entityliving, boolean flag)
+    protected void alertWolves(Mob attacker, boolean flag)
     {
-        if((entityliving instanceof CreeperMob) || (entityliving instanceof GhastMob))
+        if((attacker instanceof CreeperMob) || (attacker instanceof GhastMob))
         {
             return;
         }
-        if(entityliving instanceof WolfMob)
+        if(attacker instanceof WolfMob)
         {
-            WolfMob entitywolf = (WolfMob)entityliving;
-            if(entitywolf.isWolfTamed() && username.equals(entitywolf.getWolfOwner()))
+            WolfMob wolf = (WolfMob)attacker;
+            if(wolf.isWolfTamed() && username.equals(wolf.getWolfOwner()))
             {
                 return;
             }
         }
-        if((entityliving instanceof Player) && !func_27025_G())
+        if((attacker instanceof Player) && !func_27025_G())
         {
             return;
         }
-        List list = world.getEntitiesWithinAABB(WolfMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
-        Iterator iterator = list.iterator();
-        do
-        {
-            if(!iterator.hasNext())
-            {
-                break;
-            }
-            Entity entity = (Entity)iterator.next();
-            WolfMob entitywolf1 = (WolfMob)entity;
-            if(entitywolf1.isWolfTamed() && entitywolf1.getTarget() == null && username.equals(entitywolf1.getWolfOwner()) && (!flag || !entitywolf1.isWolfSitting()))
-            {
-                entitywolf1.setWolfSitting(false);
-                entitywolf1.setTarget(entityliving);
+        List<Entity> list = world.getEntitiesWithinAABB(WolfMob.class, AABB.getTemporaryBB(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D).grow(16D, 4D, 16D));
+        for (Entity entity : list) {
+            WolfMob wolf = (WolfMob) entity;
+            if (wolf.isWolfTamed() && wolf.getTarget() == null && username.equals(wolf.getWolfOwner()) && (!flag || !wolf.isWolfSitting())) {
+                wolf.setTarget(attacker);
             }
-        } while(true);
+        }
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/core/entity/projectile/FireballProjectile.java b/src/main/java/net/minecraft/core/entity/projectile/FireballProjectile.java
index 55d1fae8e..ca5a643eb 100644
--- a/src/main/java/net/minecraft/core/entity/projectile/FireballProjectile.java
+++ b/src/main/java/net/minecraft/core/entity/projectile/FireballProjectile.java
@@ -45,9 +45,9 @@ public class FireballProjectile extends Projectile
         setPos(x, y, z);
         heightOffset = 0.0F;
         xd = yd = zd = 0.0D;
-        vX += random.nextGaussian() * 0.4D;
-        vY += random.nextGaussian() * 0.4D;
-        vZ += random.nextGaussian() * 0.4D;
+        vX += random.nextGaussian() * 1.2D;
+        vY += random.nextGaussian() * 1.2D;
+        vZ += random.nextGaussian() * 1.2D;
         setAccel(vX, vY, vZ);
     }
     private void setAccel(double vX, double vY, double vZ){
@@ -85,7 +85,7 @@ public class FireballProjectile extends Projectile
                 if(result.entity != null)
                 {
                     if (result.entity instanceof GhastMob){
-                        result.entity.hurt(owner, 5, DamageType.COMBAT);
+                        result.entity.hurt(owner, 20, DamageType.COMBAT);
                     } else {
                         result.entity.hurt(owner, damage, DamageType.COMBAT);
                     }
diff --git a/src/main/java/net/minecraft/core/item/Items.java b/src/main/java/net/minecraft/core/item/Items.java
index dde9bcd62..4ffc579cc 100644
--- a/src/main/java/net/minecraft/core/item/Items.java
+++ b/src/main/java/net/minecraft/core/item/Items.java
@@ -329,18 +329,18 @@ public final class Items {
         FOOD_COOKIE = (new FoodItem("food.cookie", "minecraft:item/food_cookie", 16485, 1, 0, false, 16));
         MAP = new MapItem("map", "minecraft:item/map", 16486);
         TOOL_SHEARS = new ToolShearsItem("tool.shears", "minecraft:item/tool_shears", 16487, ToolMaterial.iron);
-        RECORD_13 = (new MusicDiscItem("record.13", "minecraft:item/record_13", 18384, "13", "C418"));
-        RECORD_CAT = (new MusicDiscItem("record.cat", "minecraft:item/record_cat", 18385, "cat", "C418"));
-        RECORD_BLOCKS = (new MusicDiscItem("record.blocks", "minecraft:item/record_blocks", 18386, "blocks", "C418"));
-        RECORD_CHIRP = (new MusicDiscItem("record.chirp", "minecraft:item/record_chirp", 18387, "chirp", "C418"));
-        RECORD_FAR = (new MusicDiscItem("record.far", "minecraft:item/record_far", 18388, "far", "C418"));
-        RECORD_MALL = (new MusicDiscItem("record.mall", "minecraft:item/record_mall", 18389, "mall", "C418"));
-        RECORD_MELLOHI = (new MusicDiscItem("record.mellohi", "minecraft:item/record_mellohi", 18390, "mellohi", "C418"));
-        RECORD_STAL = (new MusicDiscItem("record.stal", "minecraft:item/record_stal", 18391, "stal", "C418"));
-        RECORD_STRAD = (new MusicDiscItem("record.strad", "minecraft:item/record_strad", 18392, "strad", "C418"));
-        RECORD_WARD = (new MusicDiscItem("record.ward", "minecraft:item/record_ward", 18393, "ward", "C418"));
-        RECORD_WAIT = (new MusicDiscItem("record.wait", "minecraft:item/record_wait", 18394, "wait", "C418"));
-        RECORD_DOG = (new MusicDiscItem("record.dog", "minecraft:item/record_dog", 18395, "dog", "C418"));
+        RECORD_13 = (new MusicDiscItem("record.13", "minecraft:item/record_13", 18384, "record.13", "C418"));
+        RECORD_CAT = (new MusicDiscItem("record.cat", "minecraft:item/record_cat", 18385, "record.cat", "C418"));
+        RECORD_BLOCKS = (new MusicDiscItem("record.blocks", "minecraft:item/record_blocks", 18386, "record.blocks", "C418"));
+        RECORD_CHIRP = (new MusicDiscItem("record.chirp", "minecraft:item/record_chirp", 18387, "record.chirp", "C418"));
+        RECORD_FAR = (new MusicDiscItem("record.far", "minecraft:item/record_far", 18388, "record.far", "C418"));
+        RECORD_MALL = (new MusicDiscItem("record.mall", "minecraft:item/record_mall", 18389, "record.mall", "C418"));
+        RECORD_MELLOHI = (new MusicDiscItem("record.mellohi", "minecraft:item/record_mellohi", 18390, "record.mellohi", "C418"));
+        RECORD_STAL = (new MusicDiscItem("record.stal", "minecraft:item/record_stal", 18391, "record.stal", "C418"));
+        RECORD_STRAD = (new MusicDiscItem("record.strad", "minecraft:item/record_strad", 18392, "record.strad", "C418"));
+        RECORD_WARD = (new MusicDiscItem("record.ward", "minecraft:item/record_ward", 18393, "record.ward", "C418"));
+        RECORD_WAIT = (new MusicDiscItem("record.wait", "minecraft:item/record_wait", 18394, "record.wait", "C418"));
+        RECORD_DOG = (new MusicDiscItem("record.dog", "minecraft:item/record_dog", 18395, "record.dog", "C418"));
         NETHERCOAL = (new Item("nethercoal", "minecraft:item/nethercoal", 16488));
         ARMOR_HELMET_STEEL = (new ArmorItem("armor.helmet.steel", "minecraft:item/armor_helmet_steel", 16489, ArmorMaterial.STEEL, IArmorItem.PIECE_HEAD));
         ARMOR_CHESTPLATE_STEEL = (new ArmorItem("armor.chestplate.steel", "minecraft:item/armor_chestplate_steel", 16490, ArmorMaterial.STEEL, IArmorItem.PIECE_CHEST));
diff --git a/src/main/resources/sounds.json b/src/main/resources/assets/minecraft/sounds/mojangSounds.json
similarity index 100%
rename from src/main/resources/sounds.json
rename to src/main/resources/assets/minecraft/sounds/mojangSounds.json
diff --git a/src/main/resources/assets/minecraft/sounds/sounds.json b/src/main/resources/assets/minecraft/sounds/sounds.json
new file mode 100644
index 000000000..3c024bb37
--- /dev/null
+++ b/src/main/resources/assets/minecraft/sounds/sounds.json
@@ -0,0 +1,721 @@
+{
+  "mob.wolf.bark": {
+    "sounds": [
+      "mob/wolf/bark1.ogg",
+      "mob/wolf/bark2.ogg",
+      "mob/wolf/bark3.ogg"
+    ]
+  },
+  "mob.sheep": {
+    "sounds": [
+      "mob/sheep1.ogg",
+      "mob/sheep2.ogg",
+      "mob/sheep3.ogg"
+    ]
+  },
+  "note.snare": {
+    "sounds": [
+      "note/snare.ogg"
+    ]
+  },
+  "random.glass": {
+    "sounds": [
+      "random/glass1.ogg",
+      "random/glass2.ogg",
+      "random/glass3.ogg"
+    ]
+  },
+  "mob.zombiepig.zpigangry": {
+    "sounds": [
+      "mob/zombiepig/zpigangry1.ogg",
+      "mob/zombiepig/zpigangry2.ogg",
+      "mob/zombiepig/zpigangry3.ogg",
+      "mob/zombiepig/zpigangry4.ogg"
+    ]
+  },
+  "random.door_open": {
+    "sounds": [
+      "random/door_open.ogg"
+    ]
+  },
+  "mob.spider": {
+    "sounds": [
+      "mob/spider1.ogg",
+      "mob/spider2.ogg",
+      "mob/spider3.ogg",
+      "mob/spider4.ogg"
+    ]
+  },
+  "mob.wolf.growl": {
+    "sounds": [
+      "mob/wolf/growl1.ogg",
+      "mob/wolf/growl2.ogg",
+      "mob/wolf/growl3.ogg"
+    ]
+  },
+  "mob.ghast.charge": {
+    "sounds": [
+      "mob/ghast/charge.ogg"
+    ]
+  },
+  "tile.piston.out": {
+    "sounds": [
+      "tile/piston/out.ogg"
+    ]
+  },
+  "damage.fallsmall": {
+    "sounds": [
+      "damage/fallsmall.ogg"
+    ]
+  },
+  "ui.crafting_fail": {
+    "sounds": [
+      "ui/crafting_fail.ogg"
+    ]
+  },
+  "mob.chicken": {
+    "sounds": [
+      "mob/chicken1.ogg",
+      "mob/chicken2.ogg",
+      "mob/chicken3.ogg"
+    ]
+  },
+  "damage.hurtflesh": {
+    "sounds": [
+      "damage/hurtflesh1.ogg",
+      "damage/hurtflesh2.ogg",
+      "damage/hurtflesh3.ogg"
+    ]
+  },
+  "liquid.water": {
+    "sounds": [
+      "liquid/water.ogg"
+    ]
+  },
+  "random.door_close": {
+    "sounds": [
+      "random/door_close.ogg"
+    ]
+  },
+  "mob.wolf.death": {
+    "sounds": [
+      "mob/wolf/death.ogg"
+    ]
+  },
+  "mob.zombiehurt": {
+    "sounds": [
+      "mob/zombiehurt1.ogg",
+      "mob/zombiehurt2.ogg"
+    ]
+  },
+  "portal.portal": {
+    "sounds": [
+      "portal/portal.ogg"
+    ]
+  },
+  "random.fizz": {
+    "sounds": [
+      "random/fizz.ogg"
+    ]
+  },
+  "note.harp": {
+    "sounds": [
+      "note/harp.ogg"
+    ]
+  },
+  "step.snow": {
+    "sounds": [
+      "step/snow1.ogg",
+      "step/snow2.ogg",
+      "step/snow3.ogg",
+      "step/snow4.ogg"
+    ]
+  },
+  "mob.wolf.whine": {
+    "sounds": [
+      "mob/wolf/whine.ogg"
+    ]
+  },
+  "note.pling": {
+    "sounds": [
+      "note/pling.ogg"
+    ]
+  },
+  "step.sand": {
+    "sounds": [
+      "step/sand1.ogg",
+      "step/sand2.ogg",
+      "step/sand3.ogg",
+      "step/sand4.ogg"
+    ]
+  },
+  "ambient.weather.rain": {
+    "sounds": [
+      "ambient/weather/rain1.ogg",
+      "ambient/weather/rain2.ogg",
+      "ambient/weather/rain3.ogg",
+      "ambient/weather/rain4.ogg"
+    ]
+  },
+  "mob.zombiepig.zpighurt": {
+    "sounds": [
+      "mob/zombiepig/zpighurt1.ogg",
+      "mob/zombiepig/zpighurt2.ogg"
+    ]
+  },
+  "mob.wolf.howl": {
+    "sounds": [
+      "mob/wolf/howl1.ogg",
+      "mob/wolf/howl2.ogg"
+    ]
+  },
+  "mob.skeletondeath": {
+    "sounds": [
+      "mob/skeletondeath.ogg"
+    ]
+  },
+  "portal.trigger": {
+    "sounds": [
+      "portal/trigger.ogg"
+    ]
+  },
+  "ui.crafting_made": {
+    "sounds": [
+      "ui/crafting_made.ogg"
+    ]
+  },
+  "random.drr": {
+    "sounds": [
+      "random/drr.ogg"
+    ]
+  },
+  "mob.zombiepig.zpigdeath": {
+    "sounds": [
+      "mob/zombiepig/zpigdeath.ogg"
+    ]
+  },
+  "ambient.weather.thunder": {
+    "sounds": [
+      "ambient/weather/thunder1.ogg",
+      "ambient/weather/thunder2.ogg",
+      "ambient/weather/thunder3.ogg"
+    ]
+  },
+  "mob.creeper": {
+    "sounds": [
+      "mob/creeper1.ogg",
+      "mob/creeper2.ogg",
+      "mob/creeper3.ogg",
+      "mob/creeper4.ogg"
+    ]
+  },
+  "ui.ui_focus": {
+    "sounds": [
+      "ui/ui_focus.ogg"
+    ]
+  },
+  "mob.creeperdeath": {
+    "sounds": [
+      "mob/creeperdeath.ogg"
+    ]
+  },
+  "note.hat": {
+    "sounds": [
+      "note/hat.ogg"
+    ]
+  },
+  "mob.slime": {
+    "sounds": [
+      "mob/slime1.ogg",
+      "mob/slime2.ogg",
+      "mob/slime3.ogg",
+      "mob/slime4.ogg",
+      "mob/slime5.ogg"
+    ]
+  },
+  "mob.skeletonhurt": {
+    "sounds": [
+      "mob/skeletonhurt1.ogg",
+      "mob/skeletonhurt2.ogg",
+      "mob/skeletonhurt3.ogg",
+      "mob/skeletonhurt4.ogg"
+    ]
+  },
+  "mob.wolf.panting": {
+    "sounds": [
+      "mob/wolf/panting.ogg"
+    ]
+  },
+  "note.bass": {
+    "sounds": [
+      "note/bass.ogg"
+    ]
+  },
+  "random.fuse": {
+    "sounds": [
+      "random/fuse.ogg"
+    ]
+  },
+  "ambient.cave.cave": {
+    "sounds": [
+      "ambient/cave/cave1.ogg",
+      "ambient/cave/cave10.ogg",
+      "ambient/cave/cave11.ogg",
+      "ambient/cave/cave12.ogg",
+      "ambient/cave/cave13.ogg",
+      "ambient/cave/cave2.ogg",
+      "ambient/cave/cave3.ogg",
+      "ambient/cave/cave4.ogg",
+      "ambient/cave/cave5.ogg",
+      "ambient/cave/cave6.ogg",
+      "ambient/cave/cave7.ogg",
+      "ambient/cave/cave8.ogg",
+      "ambient/cave/cave9.ogg"
+    ]
+  },
+  "mob.ghast.fireball": {
+    "sounds": [
+      "mob/ghast/fireball4.ogg"
+    ]
+  },
+  "fire.ignite": {
+    "sounds": [
+      "fire/ignite.ogg"
+    ]
+  },
+  "ui.ui_click": {
+    "sounds": [
+      "ui/ui_click.ogg"
+    ]
+  },
+  "mob.chickenhurt": {
+    "sounds": [
+      "mob/chickenhurt1.ogg",
+      "mob/chickenhurt2.ogg"
+    ]
+  },
+  "mob.cowhurt": {
+    "sounds": [
+      "mob/cowhurt1.ogg",
+      "mob/cowhurt2.ogg",
+      "mob/cowhurt3.ogg"
+    ]
+  },
+  "ui.ui_back": {
+    "sounds": [
+      "ui/ui_back.ogg"
+    ]
+  },
+  "mob.ghast.affectionate scream": {
+    "sounds": [
+      "mob/ghast/affectionate scream.ogg"
+    ]
+  },
+  "mob.ghast.death": {
+    "sounds": [
+      "mob/ghast/death.ogg"
+    ]
+  },
+  "random.click": {
+    "sounds": [
+      "random/click.ogg"
+    ]
+  },
+  "mob.zombiepig.zpig": {
+    "sounds": [
+      "mob/zombiepig/zpig1.ogg",
+      "mob/zombiepig/zpig2.ogg",
+      "mob/zombiepig/zpig3.ogg",
+      "mob/zombiepig/zpig4.ogg"
+    ]
+  },
+  "mob.chickenplop": {
+    "sounds": [
+      "mob/chickenplop.ogg"
+    ]
+  },
+  "random.explode": {
+    "sounds": [
+      "random/explode.ogg"
+    ]
+  },
+  "mob.pig": {
+    "sounds": [
+      "mob/pig1.ogg",
+      "mob/pig2.ogg",
+      "mob/pig3.ogg"
+    ]
+  },
+  "random.bow": {
+    "sounds": [
+      "random/bow.ogg"
+    ]
+  },
+  "step.cloth": {
+    "sounds": [
+      "step/cloth1.ogg",
+      "step/cloth2.ogg",
+      "step/cloth3.ogg",
+      "step/cloth4.ogg"
+    ]
+  },
+  "mob.pigdeath": {
+    "sounds": [
+      "mob/pigdeath.ogg"
+    ]
+  },
+  "random.hurt": {
+    "sounds": [
+      "random/hurt.ogg"
+    ]
+  },
+  "random.splash": {
+    "sounds": [
+      "random/splash.ogg"
+    ]
+  },
+  "random.breath": {
+    "sounds": [
+      "random/breath.ogg"
+    ]
+  },
+  "mob.wolf.hurt": {
+    "sounds": [
+      "mob/wolf/hurt1.ogg",
+      "mob/wolf/hurt2.ogg",
+      "mob/wolf/hurt3.ogg"
+    ]
+  },
+  "liquid.lava": {
+    "sounds": [
+      "liquid/lava.ogg"
+    ]
+  },
+  "mob.zombie": {
+    "sounds": [
+      "mob/zombie1.ogg",
+      "mob/zombie2.ogg",
+      "mob/zombie3.ogg"
+    ]
+  },
+  "note.bd": {
+    "sounds": [
+      "note/bd.ogg"
+    ]
+  },
+  "ui.ui_scroll": {
+    "sounds": [
+      "ui/ui_scroll.ogg"
+    ]
+  },
+  "mob.ghast.moan": {
+    "sounds": [
+      "mob/ghast/moan1.ogg",
+      "mob/ghast/moan2.ogg",
+      "mob/ghast/moan3.ogg",
+      "mob/ghast/moan4.ogg",
+      "mob/ghast/moan5.ogg",
+      "mob/ghast/moan6.ogg",
+      "mob/ghast/moan7.ogg"
+    ]
+  },
+  "fire.fire": {
+    "sounds": [
+      "fire/fire.ogg"
+    ]
+  },
+  "step.stone": {
+    "sounds": [
+      "step/stone1.ogg",
+      "step/stone2.ogg",
+      "step/stone3.ogg",
+      "step/stone4.ogg"
+    ]
+  },
+  "mob.ghast.scream": {
+    "sounds": [
+      "mob/ghast/scream1.ogg",
+      "mob/ghast/scream2.ogg",
+      "mob/ghast/scream3.ogg",
+      "mob/ghast/scream4.ogg",
+      "mob/ghast/scream5.ogg"
+    ]
+  },
+  "damage.fallbig": {
+    "sounds": [
+      "damage/fallbig1.ogg",
+      "damage/fallbig2.ogg"
+    ]
+  },
+  "liquid.lavapop": {
+    "sounds": [
+      "liquid/lavapop.ogg"
+    ]
+  },
+  "note.bassattack": {
+    "sounds": [
+      "note/bassattack.ogg"
+    ]
+  },
+  "mob.spiderdeath": {
+    "sounds": [
+      "mob/spiderdeath.ogg"
+    ]
+  },
+  "random.wood click": {
+    "sounds": [
+      "random/wood click.ogg"
+    ]
+  },
+  "step.grass": {
+    "sounds": [
+      "step/grass1.ogg",
+      "step/grass2.ogg",
+      "step/grass3.ogg",
+      "step/grass4.ogg"
+    ]
+  },
+  "mob.skeleton": {
+    "sounds": [
+      "mob/skeleton1.ogg",
+      "mob/skeleton2.ogg",
+      "mob/skeleton3.ogg"
+    ]
+  },
+  "mob.slimeattack": {
+    "sounds": [
+      "mob/slimeattack1.ogg",
+      "mob/slimeattack2.ogg"
+    ]
+  },
+  "mob.zombiedeath": {
+    "sounds": [
+      "mob/zombiedeath.ogg"
+    ]
+  },
+  "tile.piston.in": {
+    "sounds": [
+      "tile/piston/in.ogg"
+    ]
+  },
+  "mob.cow": {
+    "sounds": [
+      "mob/cow1.ogg",
+      "mob/cow2.ogg",
+      "mob/cow3.ogg",
+      "mob/cow4.ogg"
+    ]
+  },
+  "step.gravel": {
+    "sounds": [
+      "step/gravel1.ogg",
+      "step/gravel2.ogg",
+      "step/gravel3.ogg",
+      "step/gravel4.ogg"
+    ]
+  },
+  "random.pop": {
+    "sounds": [
+      "random/pop.ogg"
+    ]
+  },
+  "step.wood": {
+    "sounds": [
+      "step/wood1.ogg",
+      "step/wood2.ogg",
+      "step/wood3.ogg",
+      "step/wood4.ogg"
+    ]
+  },
+  "portal.travel": {
+    "sounds": [
+      "portal/travel.ogg"
+    ]
+  },
+  "liquid.splash": {
+    "sounds": [
+      "liquid/splash.ogg"
+    ]
+  },
+  "mob.wolf.shake": {
+    "sounds": [
+      "mob/wolf/shake.ogg"
+    ]
+  },
+  "record.mall": {
+    "sounds": [
+      {
+        "name": "record/mall.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.dog": {
+    "sounds": [
+      {
+        "name": "record/dog.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "record.chirp": {
+    "sounds": [
+      {
+        "name": "record/chirp.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.blocks": {
+    "sounds": [
+      {
+        "name": "record/blocks.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.cat": {
+    "sounds": [
+      {
+        "name": "record/cat.mus",
+        "stream": true
+      },
+      {
+        "name": "record/cat.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "record.far": {
+    "sounds": [
+      {
+        "name": "record/far.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.mellohi": {
+    "sounds": [
+      {
+        "name": "record/mellohi.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.wait": {
+    "sounds": [
+      {
+        "name": "record/wait.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.13": {
+    "sounds": [
+      {
+        "name": "record/13.mus",
+        "stream": true
+      },
+      {
+        "name": "record/13.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "record.11": {
+    "sounds": [
+      {
+        "name": "record/11.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.ward": {
+    "sounds": [
+      {
+        "name": "record/ward.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.stal": {
+    "sounds": [
+      {
+        "name": "record/stal.mus",
+        "stream": true
+      }
+    ]
+  },
+  "record.strad": {
+    "sounds": [
+      {
+        "name": "record/strad.mus",
+        "stream": true
+      }
+    ]
+  },
+  "music.nuance": {
+    "sounds": [
+      {
+        "name": "music/nuance1.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/nuance2.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "music.hal": {
+    "sounds": [
+      {
+        "name": "music/hal1.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/hal2.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/hal3.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/hal4.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "music.piano": {
+    "sounds": [
+      {
+        "name": "music/piano1.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/piano2.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/piano3.ogg",
+        "stream": true
+      }
+    ]
+  },
+  "music.calm": {
+    "sounds": [
+      {
+        "name": "music/calm1.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/calm2.ogg",
+        "stream": true
+      },
+      {
+        "name": "music/calm3.ogg",
+        "stream": true
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/src/main/resources/sound/ui/crafting_fail.ogg b/src/main/resources/assets/minecraft/sounds/ui/crafting_fail.ogg
similarity index 100%
rename from src/main/resources/sound/ui/crafting_fail.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/crafting_fail.ogg
diff --git a/src/main/resources/sound/ui/crafting_made.ogg b/src/main/resources/assets/minecraft/sounds/ui/crafting_made.ogg
similarity index 100%
rename from src/main/resources/sound/ui/crafting_made.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/crafting_made.ogg
diff --git a/src/main/resources/sound/ui/ui_back.ogg b/src/main/resources/assets/minecraft/sounds/ui/ui_back.ogg
similarity index 100%
rename from src/main/resources/sound/ui/ui_back.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/ui_back.ogg
diff --git a/src/main/resources/sound/ui/ui_click.ogg b/src/main/resources/assets/minecraft/sounds/ui/ui_click.ogg
similarity index 100%
rename from src/main/resources/sound/ui/ui_click.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/ui_click.ogg
diff --git a/src/main/resources/sound/ui/ui_focus.ogg b/src/main/resources/assets/minecraft/sounds/ui/ui_focus.ogg
similarity index 100%
rename from src/main/resources/sound/ui/ui_focus.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/ui_focus.ogg
diff --git a/src/main/resources/sound/ui/ui_scroll.ogg b/src/main/resources/assets/minecraft/sounds/ui/ui_scroll.ogg
similarity index 100%
rename from src/main/resources/sound/ui/ui_scroll.ogg
rename to src/main/resources/assets/minecraft/sounds/ui/ui_scroll.ogg
